@stll/folio-core 0.52.0 → 0.54.0

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 (389) hide show
  1. package/README.md +23 -0
  2. package/dist/ai-edits/apply.d.ts +26 -1
  3. package/dist/ai-edits/apply.js +1779 -141
  4. package/dist/ai-edits/batch-claims.d.ts +145 -0
  5. package/dist/ai-edits/batch-claims.js +275 -0
  6. package/dist/ai-edits/blockRange.js +9 -3
  7. package/dist/ai-edits/character-boundaries.d.ts +43 -0
  8. package/dist/ai-edits/character-boundaries.js +95 -0
  9. package/dist/ai-edits/clean-text.d.ts +33 -3
  10. package/dist/ai-edits/clean-text.js +52 -6
  11. package/dist/ai-edits/comment-lifecycle.d.ts +18 -0
  12. package/dist/ai-edits/comment-lifecycle.js +52 -0
  13. package/dist/ai-edits/headless.d.ts +91 -7
  14. package/dist/ai-edits/headless.js +520 -51
  15. package/dist/ai-edits/index.d.ts +2 -1
  16. package/dist/ai-edits/index.js +2 -1
  17. package/dist/ai-edits/minimal-replacement.d.ts +21 -6
  18. package/dist/ai-edits/minimal-replacement.js +134 -15
  19. package/dist/ai-edits/newListNumbering.d.ts +23 -0
  20. package/dist/ai-edits/newListNumbering.js +94 -0
  21. package/dist/ai-edits/note-references.d.ts +96 -0
  22. package/dist/ai-edits/note-references.js +139 -0
  23. package/dist/ai-edits/pending-suggestions.d.ts +79 -0
  24. package/dist/ai-edits/pending-suggestions.js +306 -0
  25. package/dist/ai-edits/read.d.ts +6 -4
  26. package/dist/ai-edits/read.js +113 -50
  27. package/dist/ai-edits/result-validation.d.ts +29 -0
  28. package/dist/ai-edits/result-validation.js +164 -0
  29. package/dist/ai-edits/revisionStretches.d.ts +17 -0
  30. package/dist/ai-edits/revisionStretches.js +80 -0
  31. package/dist/ai-edits/snapshot.d.ts +36 -3
  32. package/dist/ai-edits/snapshot.js +180 -25
  33. package/dist/ai-edits/table-cell-mutations.d.ts +4 -2
  34. package/dist/ai-edits/table-cell-mutations.js +6 -2
  35. package/dist/ai-edits/table-geometry.d.ts +1 -1
  36. package/dist/ai-edits/table-row-column-mutations.d.ts +44 -17
  37. package/dist/ai-edits/table-row-column-mutations.js +86 -34
  38. package/dist/ai-edits/types.d.ts +155 -16
  39. package/dist/compare/compare.d.ts +1 -1
  40. package/dist/compare/compare.js +65 -16
  41. package/dist/compare/content-alignment.d.ts +5 -1
  42. package/dist/compare/content-alignment.js +52 -34
  43. package/dist/compare/content-types.d.ts +7 -0
  44. package/dist/compare/content.d.ts +4 -1
  45. package/dist/compare/content.js +6 -1
  46. package/dist/compare/formatting.js +2 -1
  47. package/dist/compare/inline-atoms.d.ts +21 -4
  48. package/dist/compare/inline-atoms.js +138 -16
  49. package/dist/compare/inline-provenance.js +1 -1
  50. package/dist/compare/plan.js +10 -5
  51. package/dist/compare/scenario.js +14 -3
  52. package/dist/compare/section-boundary-properties.js +1 -1
  53. package/dist/compare/types.d.ts +4 -2
  54. package/dist/compare/types.js +2 -1
  55. package/dist/compare/verification.d.ts +1 -1
  56. package/dist/compare/verification.js +15 -3
  57. package/dist/controller/committedLayoutDiff.d.ts +25 -0
  58. package/dist/controller/committedLayoutDiff.js +71 -0
  59. package/dist/controller/contentControlWidgetController.d.ts +1 -1
  60. package/dist/controller/folioEditor.d.ts +1 -1
  61. package/dist/controller/fontReadiness.d.ts +70 -3
  62. package/dist/controller/fontReadiness.js +100 -10
  63. package/dist/controller/headerFooterEditorManager.js +6 -1
  64. package/dist/controller/layoutPipeline.d.ts +12 -10
  65. package/dist/controller/layoutPipeline.js +65 -11
  66. package/dist/controller/layoutRunOptions.d.ts +24 -0
  67. package/dist/controller/layoutRunOptions.js +17 -0
  68. package/dist/controller/layoutScheduler.d.ts +19 -14
  69. package/dist/controller/layoutScheduler.js +15 -12
  70. package/dist/controller/layoutSession.d.ts +26 -2
  71. package/dist/controller/layoutSession.js +1 -1
  72. package/dist/controller/noteEditorManager.js +8 -3
  73. package/dist/document-operations.d.ts +11 -2
  74. package/dist/document-operations.js +230 -21
  75. package/dist/docx/altChunk.d.ts +8 -0
  76. package/dist/docx/altChunk.js +17 -0
  77. package/dist/docx/archiveInflation.d.ts +127 -0
  78. package/dist/docx/archiveInflation.js +181 -0
  79. package/dist/docx/attributeRemainder.d.ts +1 -1
  80. package/dist/docx/blockContentParser.d.ts +64 -1
  81. package/dist/docx/blockContentParser.js +17 -4
  82. package/dist/docx/blockCustomXmlShell.d.ts +7 -0
  83. package/dist/docx/blockCustomXmlShell.js +14 -0
  84. package/dist/docx/blockPlainText.js +7 -0
  85. package/dist/docx/commentAnchorIndex.js +1 -1
  86. package/dist/docx/commentRangeIntegrity.js +8 -3
  87. package/dist/docx/commentReferenceNormalization.js +1 -1
  88. package/dist/docx/commentReplyMarkers.js +20 -1
  89. package/dist/docx/compatibility.d.ts +1 -1
  90. package/dist/docx/compatibility.js +34 -13
  91. package/dist/docx/containerChildren.gen.d.ts +1 -1
  92. package/dist/docx/containerChildren.gen.js +1 -0
  93. package/dist/docx/documentParser.js +12 -12
  94. package/dist/docx/drawingIdNormalization.d.ts +3 -1
  95. package/dist/docx/drawingIdNormalization.js +6 -1
  96. package/dist/docx/ensureParaIds.js +119 -97
  97. package/dist/docx/footnoteParser.js +8 -4
  98. package/dist/docx/headerFooterParser.js +3 -3
  99. package/dist/docx/headerFooterReferenceNormalization.d.ts +20 -1
  100. package/dist/docx/headerFooterReferenceNormalization.js +52 -27
  101. package/dist/docx/hyperlinkParser.d.ts +1 -1
  102. package/dist/docx/index.d.ts +1 -1
  103. package/dist/docx/listNumberingInstances.d.ts +59 -0
  104. package/dist/docx/listNumberingInstances.js +249 -0
  105. package/dist/docx/metadataPrivacy.js +24 -1
  106. package/dist/docx/normalizeBaseDirection.js +2 -1
  107. package/dist/docx/noteReferenceMark.d.ts +15 -0
  108. package/dist/docx/noteReferenceMark.js +48 -0
  109. package/dist/docx/opaqueCarrier.d.ts +7 -0
  110. package/dist/docx/opaqueCarrier.js +38 -0
  111. package/dist/docx/packageParts.js +4 -1
  112. package/dist/docx/paragraphParser.js +96 -27
  113. package/dist/docx/paragraphPropertySource.d.ts +4 -2
  114. package/dist/docx/paragraphPropertySource.js +10 -2
  115. package/dist/docx/paragraphTraversal.js +1 -0
  116. package/dist/docx/parseWarningMessage.js +4 -1
  117. package/dist/docx/parser.js +175 -22
  118. package/dist/docx/rezip.js +31 -7
  119. package/dist/docx/sdtProperties.js +1 -1
  120. package/dist/docx/sdtPropertiesPatch.js +3 -0
  121. package/dist/docx/selectiveSave.js +16 -9
  122. package/dist/docx/selectiveXmlPatch.d.ts +3 -1
  123. package/dist/docx/selectiveXmlPatch.js +186 -39
  124. package/dist/docx/serializer/blockCustomXmlSerializer.d.ts +5 -0
  125. package/dist/docx/serializer/blockCustomXmlSerializer.js +4 -0
  126. package/dist/docx/serializer/documentSerializer.js +2 -0
  127. package/dist/docx/serializer/headerFooterSerializer.js +2 -0
  128. package/dist/docx/serializer/noteSerializer.js +3 -1
  129. package/dist/docx/serializer/paragraphSerializer.js +33 -9
  130. package/dist/docx/serializer/tableSerializer.js +25 -38
  131. package/dist/docx/server/boundedArchive.d.ts +8 -13
  132. package/dist/docx/server/boundedArchive.js +70 -59
  133. package/dist/docx/server/createBilingualDocument.js +3 -3
  134. package/dist/docx/server/extractDocxText.d.ts +8 -2
  135. package/dist/docx/server/extractDocxText.js +2 -2
  136. package/dist/docx/server/validateDocxConformance.d.ts +1 -1
  137. package/dist/docx/server/validateDocxConformance.js +1 -0
  138. package/dist/docx/tableParser.d.ts +157 -1
  139. package/dist/docx/tableParser.js +89 -10
  140. package/dist/docx/textBoxParser.js +1 -1
  141. package/dist/docx/unzip.d.ts +20 -2
  142. package/dist/docx/unzip.js +136 -25
  143. package/dist/docx/wordprocessingPrefixes.d.ts +78 -0
  144. package/dist/docx/wordprocessingPrefixes.js +286 -0
  145. package/dist/fonts/embeddedFonts.js +1 -1
  146. package/dist/i18n/messages/catalogs.gen.d.ts +170 -34
  147. package/dist/i18n/messages/catalogs.gen.js +187 -51
  148. package/dist/i18n/messages/messages.gen.d.ts +10 -2
  149. package/dist/internal/compare/inline-presentation.d.ts +2 -1
  150. package/dist/internal/compare/inline-presentation.js +11 -10
  151. package/dist/internal/headlessRevisionResolutionGuard.d.ts +2 -8
  152. package/dist/internal/headlessRevisionResolutionGuard.js +2 -11
  153. package/dist/internal/indexedPositionMap.d.ts +11 -0
  154. package/dist/internal/indexedPositionMap.js +42 -0
  155. package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
  156. package/dist/internal/revisionResolutionEdits.d.ts +13 -0
  157. package/dist/internal/revisionResolutionEdits.js +19 -0
  158. package/dist/internal/revisionResolutionInline.d.ts +24 -0
  159. package/dist/internal/{headlessRevisionResolution.js → revisionResolutionInline.js} +61 -43
  160. package/dist/internal/revisionResolutionStep.d.ts +34 -0
  161. package/dist/internal/revisionResolutionStep.js +282 -0
  162. package/dist/internal/revisionResolutionTracking.d.ts +11 -0
  163. package/dist/internal/revisionResolutionTracking.js +124 -0
  164. package/dist/internal/wholeStoryRevisionResolution.d.ts +56 -0
  165. package/dist/internal/wholeStoryRevisionResolution.js +600 -0
  166. package/dist/layout-bridge/convert/markupViewFlow.d.ts +20 -0
  167. package/dist/layout-bridge/convert/markupViewFlow.js +123 -0
  168. package/dist/layout-bridge/convert/tableConversion.js +1 -1
  169. package/dist/layout-bridge/convert/toFlowBlocks.js +10 -1
  170. package/dist/layout-engine/layoutInstrumentation.d.ts +9 -1
  171. package/dist/layout-engine/layoutInstrumentation.js +4 -1
  172. package/dist/layout-engine/measure/cache.d.ts +18 -1
  173. package/dist/layout-engine/measure/cache.js +31 -1
  174. package/dist/layout-engine/measure/font-metrics.worker.js +3 -7
  175. package/dist/layout-engine/measure/measureContainer.js +7 -47
  176. package/dist/layout-engine/measure/measureHelpers.d.ts +6 -1
  177. package/dist/layout-engine/measure/measureHelpers.js +22 -2
  178. package/dist/layout-engine/measure/measureParagraph.js +2 -2
  179. package/dist/layout-engine/measure/measureWorker.js +2 -3
  180. package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +6 -7
  181. package/dist/layout-engine/measure/measureWorkerProtocol.js +1 -2
  182. package/dist/layout-engine/measure/paragraphMeasureShared.d.ts +12 -1
  183. package/dist/layout-engine/measure/paragraphMeasureShared.js +14 -1
  184. package/dist/layout-engine/types.d.ts +6 -0
  185. package/dist/layout-painter/renderPage.js +1 -0
  186. package/dist/layout-painter/renderParagraph.js +1 -1
  187. package/dist/managers/ContextMenuManager.js +5 -2
  188. package/dist/managers/types.d.ts +3 -0
  189. package/dist/markdown/escape.d.ts +2 -2
  190. package/dist/markdown/escape.js +4 -5
  191. package/dist/markdown/fromMarkdown.js +2 -1
  192. package/dist/markdown/internals.d.ts +11 -1
  193. package/dist/markdown/internals.js +24 -3
  194. package/dist/markdown/renderBlock.js +121 -25
  195. package/dist/markdown/renderParagraph.d.ts +13 -1
  196. package/dist/markdown/renderParagraph.js +85 -38
  197. package/dist/markdown/renderRuns.d.ts +10 -1
  198. package/dist/markdown/renderRuns.js +323 -69
  199. package/dist/markdown/renderTable.js +24 -12
  200. package/dist/markdown/trailers.js +2 -2
  201. package/dist/markdown/types.d.ts +29 -7
  202. package/dist/paged-layout/incrementalMeasure.d.ts +1 -2
  203. package/dist/paged-layout/incrementalMeasure.js +1 -9
  204. package/dist/paged-layout/transactionDirtyRange.d.ts +1 -3
  205. package/dist/paged-layout/transactionDirtyRange.js +29 -41
  206. package/dist/panel-layout.d.ts +83 -0
  207. package/dist/panel-layout.js +96 -0
  208. package/dist/prosemirror/anchoredTextBoxes.d.ts +37 -0
  209. package/dist/prosemirror/anchoredTextBoxes.js +156 -0
  210. package/dist/prosemirror/attrs/index.d.ts +6 -2
  211. package/dist/prosemirror/attrs/index.js +172 -1
  212. package/dist/prosemirror/clearRunColor.d.ts +6 -0
  213. package/dist/prosemirror/clearRunColor.js +46 -0
  214. package/dist/prosemirror/commands/comments.d.ts +7 -8
  215. package/dist/prosemirror/commands/comments.js +281 -212
  216. package/dist/prosemirror/commands/contentControls.d.ts +1 -1
  217. package/dist/prosemirror/commands/formatPainter.d.ts +1 -1
  218. package/dist/prosemirror/commands/formatPainter.js +1 -1
  219. package/dist/prosemirror/commands/formatting.d.ts +1 -1
  220. package/dist/prosemirror/commands/hyperlink.js +2 -1
  221. package/dist/prosemirror/commands/index.d.ts +2 -2
  222. package/dist/prosemirror/commands/index.js +2 -2
  223. package/dist/prosemirror/commands/paragraph.d.ts +7 -1
  224. package/dist/prosemirror/commands/paragraph.js +9 -1
  225. package/dist/prosemirror/commands/paragraphBookmarkJoin.d.ts +13 -0
  226. package/dist/prosemirror/commands/paragraphBookmarkJoin.js +22 -0
  227. package/dist/prosemirror/commands/pastePlainText.d.ts +1 -1
  228. package/dist/prosemirror/commands/propertyChangeScope.d.ts +3 -2
  229. package/dist/prosemirror/commands/propertyChangeScope.js +24 -3
  230. package/dist/prosemirror/commands/resolveAllTableChanges.d.ts +40 -0
  231. package/dist/prosemirror/commands/resolveAllTableChanges.js +620 -0
  232. package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.d.ts +15 -0
  233. package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.js +46 -0
  234. package/dist/prosemirror/commands/resolveParagraphProperties.d.ts +16 -0
  235. package/dist/prosemirror/commands/resolveParagraphProperties.js +73 -0
  236. package/dist/prosemirror/commands/sectionBreak.js +2 -1
  237. package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +15 -2
  238. package/dist/prosemirror/commands/tableCellMergeResolution.js +23 -7
  239. package/dist/prosemirror/containerFinalParagraph.d.ts +11 -5
  240. package/dist/prosemirror/containerFinalParagraph.js +7 -6
  241. package/dist/prosemirror/contentControlRevisions.d.ts +1 -1
  242. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
  243. package/dist/prosemirror/conversion/fromProseDoc.js +177 -605
  244. package/dist/prosemirror/conversion/toProseDoc.d.ts +4 -11
  245. package/dist/prosemirror/conversion/toProseDoc.js +70 -154
  246. package/dist/prosemirror/documentSchema.d.ts +8 -0
  247. package/dist/prosemirror/documentSchema.js +18 -0
  248. package/dist/prosemirror/emptyFieldResultRuns.d.ts +18 -0
  249. package/dist/prosemirror/emptyFieldResultRuns.js +33 -0
  250. package/dist/prosemirror/extensions/ExtensionManager.d.ts +1 -1
  251. package/dist/prosemirror/extensions/ExtensionManager.js +3 -1
  252. package/dist/prosemirror/extensions/StarterKit.js +5 -1
  253. package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
  254. package/dist/prosemirror/extensions/core/ParagraphExtension.js +116 -63
  255. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +4 -1
  256. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +24 -3
  257. package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.d.ts +20 -0
  258. package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.js +43 -0
  259. package/dist/prosemirror/extensions/features/ListExtension.js +167 -128
  260. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +19 -2
  261. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +33 -20
  262. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +31 -2
  263. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +270 -99
  264. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +3 -2
  265. package/dist/prosemirror/extensions/features/pasteCleanup.js +2 -1
  266. package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +1 -1
  267. package/dist/prosemirror/extensions/features/pastedHtmlLists.d.ts +12 -0
  268. package/dist/prosemirror/extensions/features/pastedHtmlLists.js +124 -0
  269. package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +33 -11
  270. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +8 -4
  271. package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +21 -18
  272. package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +37 -17
  273. package/dist/prosemirror/extensions/marks/StrikeExtension.js +2 -2
  274. package/dist/prosemirror/extensions/marks/SubscriptExtension.js +2 -2
  275. package/dist/prosemirror/extensions/marks/SuperscriptExtension.js +2 -2
  276. package/dist/prosemirror/extensions/marks/TextColorExtension.js +4 -3
  277. package/dist/prosemirror/extensions/marks/markUtils.d.ts +15 -8
  278. package/dist/prosemirror/extensions/marks/markUtils.js +25 -10
  279. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +12 -0
  280. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +46 -0
  281. package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.d.ts +6 -0
  282. package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.js +52 -0
  283. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +2 -2
  284. package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +3 -3
  285. package/dist/prosemirror/extensions/nodes/FieldExtension.js +50 -15
  286. package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +5 -3
  287. package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +4 -1
  288. package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
  289. package/dist/prosemirror/extensions/nodes/TableExtension.js +121 -226
  290. package/dist/prosemirror/extensions/types.d.ts +11 -1
  291. package/dist/prosemirror/findReplaceSelection.js +1 -1
  292. package/dist/prosemirror/hyperlinkRemoval.d.ts +9 -0
  293. package/dist/prosemirror/hyperlinkRemoval.js +129 -0
  294. package/dist/prosemirror/index.d.ts +5 -3
  295. package/dist/prosemirror/index.js +5 -3
  296. package/dist/prosemirror/indexedNodeLookup.d.ts +17 -0
  297. package/dist/prosemirror/indexedNodeLookup.js +103 -0
  298. package/dist/prosemirror/listAutoformatMarkers.d.ts +19 -0
  299. package/dist/prosemirror/listAutoformatMarkers.js +98 -0
  300. package/dist/prosemirror/listInstanceReferences.d.ts +12 -0
  301. package/dist/prosemirror/listInstanceReferences.js +72 -0
  302. package/dist/prosemirror/listLabels.d.ts +24 -0
  303. package/dist/prosemirror/listLabels.js +111 -0
  304. package/dist/prosemirror/listNumbering.d.ts +92 -0
  305. package/dist/prosemirror/listNumbering.js +330 -0
  306. package/dist/prosemirror/listRendering.d.ts +27 -0
  307. package/dist/prosemirror/listRendering.js +27 -0
  308. package/dist/prosemirror/listRenderingAttrs.d.ts +11 -2
  309. package/dist/prosemirror/listRenderingAttrs.js +8 -1
  310. package/dist/prosemirror/markupViewNotes.d.ts +8 -0
  311. package/dist/prosemirror/markupViewNotes.js +49 -0
  312. package/dist/prosemirror/markupViewProjection.d.ts +97 -0
  313. package/dist/prosemirror/markupViewProjection.js +88 -0
  314. package/dist/prosemirror/noteReferenceReview.d.ts +77 -0
  315. package/dist/prosemirror/noteReferenceReview.js +332 -0
  316. package/dist/prosemirror/numberingAttr.d.ts +9 -1
  317. package/dist/prosemirror/numberingAttr.js +9 -1
  318. package/dist/prosemirror/outlineLevelAttr.js +1 -1
  319. package/dist/prosemirror/paragraphIndentation.d.ts +10 -1
  320. package/dist/prosemirror/paragraphIndentation.js +32 -7
  321. package/dist/prosemirror/paragraphMarkJoin.d.ts +21 -0
  322. package/dist/prosemirror/paragraphMarkJoin.js +26 -0
  323. package/dist/prosemirror/paragraphPropertyCarry.d.ts +64 -0
  324. package/dist/prosemirror/paragraphPropertyCarry.js +158 -0
  325. package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +1 -1
  326. package/dist/prosemirror/plugins/documentNumbering.d.ts +27 -1
  327. package/dist/prosemirror/plugins/documentNumbering.js +97 -11
  328. package/dist/prosemirror/plugins/documentStyleState.d.ts +26 -0
  329. package/dist/prosemirror/plugins/documentStyleState.js +32 -0
  330. package/dist/prosemirror/plugins/documentStyles.d.ts +3 -13
  331. package/dist/prosemirror/plugins/documentStyles.js +67 -17
  332. package/dist/prosemirror/plugins/index.d.ts +2 -1
  333. package/dist/prosemirror/plugins/index.js +2 -1
  334. package/dist/prosemirror/plugins/paragraphStyleResolution.d.ts +15 -0
  335. package/dist/prosemirror/plugins/paragraphStyleResolution.js +230 -0
  336. package/dist/prosemirror/plugins/suggestionMode.d.ts +27 -3
  337. package/dist/prosemirror/plugins/suggestionMode.js +490 -63
  338. package/dist/prosemirror/plugins/templateDirectives.d.ts +1 -1
  339. package/dist/prosemirror/plugins/transactionInvariants.d.ts +32 -0
  340. package/dist/prosemirror/plugins/transactionInvariants.js +86 -0
  341. package/dist/prosemirror/positionSweep.d.ts +24 -0
  342. package/dist/prosemirror/positionSweep.js +222 -0
  343. package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +23 -3
  344. package/dist/prosemirror/rebaseParagraphRunFormatting.js +39 -13
  345. package/dist/prosemirror/rebaseParagraphRuns.d.ts +36 -0
  346. package/dist/prosemirror/rebaseParagraphRuns.js +99 -0
  347. package/dist/prosemirror/rejoinRunCarriers.d.ts +1 -1
  348. package/dist/prosemirror/replacedAnnotations.d.ts +33 -1
  349. package/dist/prosemirror/replacedAnnotations.js +170 -1
  350. package/dist/prosemirror/runFormattingFromMarks.d.ts +18 -0
  351. package/dist/prosemirror/runFormattingFromMarks.js +567 -0
  352. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +1 -1
  353. package/dist/prosemirror/runFormattingReconciliation.js +10 -9
  354. package/dist/prosemirror/schema/index.d.ts +2 -2
  355. package/dist/prosemirror/schema/index.js +3 -0
  356. package/dist/prosemirror/schema/nodes.d.ts +44 -11
  357. package/dist/prosemirror/sectionMarkEdits.d.ts +20 -0
  358. package/dist/prosemirror/sectionMarkEdits.js +59 -0
  359. package/dist/prosemirror/storyListNumbering.d.ts +17 -0
  360. package/dist/prosemirror/storyListNumbering.js +102 -0
  361. package/dist/prosemirror/styles/paragraphStyleCascade.d.ts +59 -0
  362. package/dist/prosemirror/styles/paragraphStyleCascade.js +145 -0
  363. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +21 -2
  364. package/dist/prosemirror/styles/resolvedStyleAttrs.js +38 -1
  365. package/dist/prosemirror/styles/tableStyleRegions.d.ts +31 -0
  366. package/dist/prosemirror/styles/tableStyleRegions.js +55 -0
  367. package/dist/prosemirror/tableCellPaste.d.ts +74 -0
  368. package/dist/prosemirror/tableCellPaste.js +525 -0
  369. package/dist/prosemirror/tableGridMutation.d.ts +87 -2
  370. package/dist/prosemirror/tableGridMutation.js +255 -2
  371. package/dist/prosemirror/tableRunIn.d.ts +51 -0
  372. package/dist/prosemirror/tableRunIn.js +165 -0
  373. package/dist/prosemirror/textInput.js +11 -2
  374. package/dist/prosemirror/trackedRevisionPath.d.ts +17 -0
  375. package/dist/prosemirror/trackedRevisionPath.js +32 -0
  376. package/dist/prosemirror/validation.js +5 -1
  377. package/dist/redline.js +93 -9
  378. package/dist/render-dom/BodySelectionOverlay.d.ts +4 -1
  379. package/dist/render-dom/BodySelectionOverlay.js +3 -2
  380. package/dist/server.d.ts +2 -2
  381. package/dist/utils/findReplace.js +2 -2
  382. package/dist/utils/mergeDocumentContent.js +1 -1
  383. package/dist/utils/noteReferenceLabels.d.ts +36 -0
  384. package/dist/utils/noteReferenceLabels.js +32 -0
  385. package/dist/utils/replaceText.js +1 -1
  386. package/dist/version-comparison.d.ts +1 -0
  387. package/dist/version-comparison.js +1 -0
  388. package/package.json +6 -5
  389. package/dist/internal/headlessRevisionResolution.d.ts +0 -23
@@ -0,0 +1,79 @@
1
+ import { FolioAIEditAppliedOperation, FolioAIEditApplyResult, FolioAIEditOperation, FolioAIEditSnapshot } from "./types.js";
2
+ import { FolioDocumentStoryHandle } from "./headless.js";
3
+ import { EditorState } from "prosemirror-state";
4
+ //#region src/ai-edits/pending-suggestions.d.ts
5
+ declare const FOLIO_PENDING_SUGGESTION_VERSION: 1;
6
+ /** A host-owned, JSON-serializable proposal. It is never written into the DOCX. */
7
+ type FolioPendingSuggestionRecord = {
8
+ version: typeof FOLIO_PENDING_SUGGESTION_VERSION;
9
+ suggestionId: string;
10
+ operation: FolioAIEditOperation;
11
+ story: FolioDocumentStoryHandle;
12
+ anchor: {
13
+ blockId: string;
14
+ paraId: string | null;
15
+ originalTextHash: string;
16
+ selectedTextHash?: string;
17
+ startOffset?: number;
18
+ endOffset?: number;
19
+ };
20
+ author: string;
21
+ provenance: "suggested";
22
+ sourceDocumentFingerprint: string;
23
+ commentId?: number;
24
+ };
25
+ type FolioPendingSuggestionStaleReason = "missingAnchor" | "ambiguousAnchor" | "textChanged" | "unsupportedVersion" | "documentChanged" | "invalidRecord" | "applyFailed";
26
+ type FolioPendingSuggestionLoadResult = {
27
+ status: "restaged";
28
+ suggestionId: string;
29
+ } | {
30
+ status: "stale";
31
+ suggestionId: string | null;
32
+ reason: FolioPendingSuggestionStaleReason;
33
+ };
34
+ type RecordAppliedOptions = {
35
+ snapshot: FolioAIEditSnapshot;
36
+ story: FolioDocumentStoryHandle;
37
+ operations: readonly FolioAIEditOperation[];
38
+ applied: readonly FolioAIEditAppliedOperation[];
39
+ author: string;
40
+ activeSuggestionIds: ReadonlySet<string>;
41
+ };
42
+ type ReplaceRestagedStoryOptions = {
43
+ story: FolioDocumentStoryHandle;
44
+ restaged: readonly {
45
+ snapshot: FolioAIEditSnapshot;
46
+ operation: FolioAIEditOperation;
47
+ applied: FolioAIEditAppliedOperation;
48
+ author: string;
49
+ }[];
50
+ activeSuggestionIds: ReadonlySet<string>;
51
+ };
52
+ type LoadPendingSuggestionsOptions = {
53
+ records: readonly unknown[];
54
+ snapshotForStory: (story: FolioDocumentStoryHandle) => FolioAIEditSnapshot | null;
55
+ sourceSnapshotForStory: (story: FolioDocumentStoryHandle, commentIds: ReadonlySet<number>) => FolioAIEditSnapshot | null;
56
+ apply: (record: FolioPendingSuggestionRecord, snapshot: FolioAIEditSnapshot) => FolioAIEditApplyResult;
57
+ activeSuggestionIds: () => ReadonlySet<string>;
58
+ };
59
+ type ExportPendingSuggestionsOptions = {
60
+ activeSuggestionIds: ReadonlySet<string>;
61
+ snapshotForStory: (story: FolioDocumentStoryHandle, commentIds: ReadonlySet<number>) => FolioAIEditSnapshot | null;
62
+ };
63
+ /** Drop only comments attached to proposals that have not been accepted. */
64
+ declare const withoutPendingSuggestionCommentMarks: (state: EditorState, commentIds: ReadonlySet<number>) => EditorState;
65
+ /** The saved package's story, with all pending proposals removed. */
66
+ declare const createPendingSuggestionSourceSnapshot: (state: EditorState, commentIds: ReadonlySet<number>) => FolioAIEditSnapshot;
67
+ /** Tracks only operations that successfully staged in `suggested` mode. */
68
+ declare class FolioPendingSuggestionRegistry {
69
+ private readonly records;
70
+ private readonly sourceFingerprints;
71
+ clear(): void;
72
+ recordApplied({ snapshot, story, operations, applied, author, activeSuggestionIds }: RecordAppliedOptions): void;
73
+ /** Rebase records after ordinary revisions change their source story. */
74
+ replaceRestagedStory({ story, restaged, activeSuggestionIds }: ReplaceRestagedStoryOptions): void;
75
+ exportPendingSuggestions({ activeSuggestionIds, snapshotForStory }: ExportPendingSuggestionsOptions): FolioPendingSuggestionRecord[];
76
+ loadPendingSuggestions({ records, snapshotForStory, sourceSnapshotForStory, apply, activeSuggestionIds }: LoadPendingSuggestionsOptions): FolioPendingSuggestionLoadResult[];
77
+ }
78
+ //#endregion
79
+ export { FOLIO_PENDING_SUGGESTION_VERSION, FolioPendingSuggestionLoadResult, FolioPendingSuggestionRecord, FolioPendingSuggestionRegistry, FolioPendingSuggestionStaleReason, createPendingSuggestionSourceSnapshot, withoutPendingSuggestionCommentMarks };
@@ -0,0 +1,306 @@
1
+ import { parseFolioDocumentOperationBatch } from "../document-operations.js";
2
+ import { rejectAllSuggestions } from "../prosemirror/commands/comments.js";
3
+ import { getDocumentStyleResolver } from "../prosemirror/plugins/documentStyleState.js";
4
+ import { getFolioParaIdFromBlockId } from "../types/block-id.js";
5
+ import { canonicalJson } from "../utils/canonicalJson.js";
6
+ import { createFolioAIEditSnapshotWithStyleResolver, hashFolioAIBlockText, sourceDocumentOf } from "./snapshot.js";
7
+ //#region src/ai-edits/pending-suggestions.ts
8
+ const FOLIO_PENDING_SUGGESTION_VERSION = 1;
9
+ /** Drop only comments attached to proposals that have not been accepted. */
10
+ const withoutPendingSuggestionCommentMarks = (state, commentIds) => {
11
+ if (commentIds.size === 0) return state;
12
+ let transaction = state.tr;
13
+ state.doc.descendants((node, position) => {
14
+ for (const mark of node.marks) if (mark.type.name === "comment" && commentIds.has(mark.attrs["commentId"])) transaction = transaction.removeMark(position, position + node.nodeSize, mark);
15
+ });
16
+ return transaction.docChanged ? state.apply(transaction) : state;
17
+ };
18
+ /** The saved package's story, with all pending proposals removed. */
19
+ const createPendingSuggestionSourceSnapshot = (state, commentIds) => {
20
+ let source = state;
21
+ rejectAllSuggestions()(state, (transaction) => {
22
+ source = state.apply(transaction);
23
+ });
24
+ source = withoutPendingSuggestionCommentMarks(source, commentIds);
25
+ return createFolioAIEditSnapshotWithStyleResolver(source.doc, getDocumentStyleResolver(source));
26
+ };
27
+ const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
28
+ const operationBlockId = (operation) => {
29
+ switch (operation.type) {
30
+ case "replaceRange":
31
+ case "commentOnRange":
32
+ case "formatRange": return operation.range.blockId;
33
+ default: return operation.blockId;
34
+ }
35
+ };
36
+ const storyFromUnknown = (value) => {
37
+ if (!isObject(value)) return null;
38
+ switch (value["type"]) {
39
+ case "main": return { type: "main" };
40
+ case "header":
41
+ case "footer": return typeof value["relationshipId"] === "string" ? {
42
+ type: value["type"],
43
+ relationshipId: value["relationshipId"]
44
+ } : null;
45
+ case "footnote":
46
+ case "endnote": return typeof value["noteId"] === "number" && Number.isSafeInteger(value["noteId"]) ? {
47
+ type: value["type"],
48
+ noteId: value["noteId"]
49
+ } : null;
50
+ default: return null;
51
+ }
52
+ };
53
+ const fingerprintOf = (snapshot, story) => hashFolioAIBlockText(canonicalJson([story, snapshot.blocks.map((block) => [block, snapshot.anchors[block.id]?.structuralBoundaryHash])]));
54
+ const paraIdCountsOf = (snapshot) => {
55
+ const counts = /* @__PURE__ */ new Map();
56
+ sourceDocumentOf(snapshot).descendants((node) => {
57
+ const paraId = node.attrs["paraId"];
58
+ if (node.type.name === "paragraph" && typeof paraId === "string") counts.set(paraId, (counts.get(paraId) ?? 0) + 1);
59
+ });
60
+ return counts;
61
+ };
62
+ const recordKey = (record) => canonicalJson([
63
+ record.story,
64
+ record.suggestionId,
65
+ record.operation.id
66
+ ]);
67
+ const parseRecord = (value) => {
68
+ if (!isObject(value) || !isObject(value["anchor"])) return null;
69
+ const story = storyFromUnknown(value["story"]);
70
+ const anchor = value["anchor"];
71
+ if (story === null || typeof value["suggestionId"] !== "string" || typeof value["author"] !== "string" || value["provenance"] !== "suggested" || typeof value["sourceDocumentFingerprint"] !== "string" || value["commentId"] !== void 0 && (typeof value["commentId"] !== "number" || !Number.isSafeInteger(value["commentId"])) || typeof anchor["blockId"] !== "string" || anchor["paraId"] !== null && typeof anchor["paraId"] !== "string" || typeof anchor["originalTextHash"] !== "string") return null;
72
+ let operation;
73
+ try {
74
+ const parsed = parseFolioDocumentOperationBatch({
75
+ version: 1,
76
+ operations: [value["operation"]],
77
+ mode: "suggested"
78
+ }).operations.at(0);
79
+ if (!parsed) return null;
80
+ operation = parsed;
81
+ } catch {
82
+ return null;
83
+ }
84
+ if (operationBlockId(operation) !== anchor["blockId"] || (operation.suggestionId ?? operation.id) !== value["suggestionId"] || getFolioParaIdFromBlockId(anchor["blockId"]) !== anchor["paraId"]) return null;
85
+ if (operation.type === "replaceRange" || operation.type === "formatRange") {
86
+ if (anchor["selectedTextHash"] !== operation.range.selectedTextHash || anchor["startOffset"] !== operation.range.startOffset || anchor["endOffset"] !== operation.range.endOffset) return null;
87
+ }
88
+ return {
89
+ version: 1,
90
+ suggestionId: value["suggestionId"],
91
+ operation,
92
+ story,
93
+ anchor: {
94
+ blockId: anchor["blockId"],
95
+ paraId: anchor["paraId"],
96
+ originalTextHash: anchor["originalTextHash"],
97
+ ...typeof anchor["selectedTextHash"] === "string" && { selectedTextHash: anchor["selectedTextHash"] },
98
+ ...typeof anchor["startOffset"] === "number" && { startOffset: anchor["startOffset"] },
99
+ ...typeof anchor["endOffset"] === "number" && { endOffset: anchor["endOffset"] }
100
+ },
101
+ author: value["author"],
102
+ provenance: "suggested",
103
+ sourceDocumentFingerprint: value["sourceDocumentFingerprint"],
104
+ ...typeof value["commentId"] === "number" && Number.isSafeInteger(value["commentId"]) && { commentId: value["commentId"] }
105
+ };
106
+ };
107
+ /** Tracks only operations that successfully staged in `suggested` mode. */
108
+ var FolioPendingSuggestionRegistry = class {
109
+ records = /* @__PURE__ */ new Map();
110
+ sourceFingerprints = /* @__PURE__ */ new Map();
111
+ clear() {
112
+ this.records.clear();
113
+ this.sourceFingerprints.clear();
114
+ }
115
+ recordApplied({ snapshot, story, operations, applied, author, activeSuggestionIds }) {
116
+ if (applied.length === 0) return;
117
+ const storyKey = canonicalJson(story);
118
+ for (const [key, record] of this.records) if (!activeSuggestionIds.has(record.suggestionId)) this.records.delete(key);
119
+ if (![...this.records.values()].some((record) => canonicalJson(record.story) === storyKey)) this.sourceFingerprints.delete(storyKey);
120
+ const fingerprint = this.sourceFingerprints.get(storyKey) ?? fingerprintOf(snapshot, story);
121
+ this.sourceFingerprints.set(storyKey, fingerprint);
122
+ const appliedById = new Map(applied.map((entry) => [entry.id, entry]));
123
+ for (const operation of operations) {
124
+ const outcome = appliedById.get(operation.id);
125
+ if (!outcome?.suggestionId) continue;
126
+ const blockId = operationBlockId(operation);
127
+ const anchor = snapshot.anchors[blockId];
128
+ if (!anchor) continue;
129
+ const range = operation.type === "replaceRange" || operation.type === "formatRange" ? operation.range : null;
130
+ const record = {
131
+ version: 1,
132
+ suggestionId: outcome.suggestionId,
133
+ operation: structuredClone(operation),
134
+ story: structuredClone(story),
135
+ anchor: {
136
+ blockId,
137
+ paraId: getFolioParaIdFromBlockId(blockId),
138
+ originalTextHash: anchor.textHash,
139
+ ...range !== null && {
140
+ selectedTextHash: range.selectedTextHash,
141
+ startOffset: range.startOffset,
142
+ endOffset: range.endOffset
143
+ }
144
+ },
145
+ author,
146
+ provenance: "suggested",
147
+ sourceDocumentFingerprint: fingerprint,
148
+ ...outcome.commentId !== void 0 && { commentId: outcome.commentId }
149
+ };
150
+ this.records.set(recordKey(record), record);
151
+ }
152
+ }
153
+ /** Rebase records after ordinary revisions change their source story. */
154
+ replaceRestagedStory({ story, restaged, activeSuggestionIds }) {
155
+ if (restaged.length === 0) return;
156
+ const storyKey = canonicalJson(story);
157
+ for (const [key, record] of this.records) if (canonicalJson(record.story) === storyKey) this.records.delete(key);
158
+ const first = restaged.at(0);
159
+ if (!first) return;
160
+ this.sourceFingerprints.set(storyKey, fingerprintOf(first.snapshot, story));
161
+ for (const { snapshot, operation, applied, author } of restaged) this.recordApplied({
162
+ snapshot,
163
+ story,
164
+ operations: [operation],
165
+ applied: [applied],
166
+ author,
167
+ activeSuggestionIds
168
+ });
169
+ }
170
+ exportPendingSuggestions({ activeSuggestionIds, snapshotForStory }) {
171
+ const pending = [];
172
+ const fingerprints = /* @__PURE__ */ new Map();
173
+ const commentIdsByStory = /* @__PURE__ */ new Map();
174
+ for (const record of this.records.values()) {
175
+ if (!activeSuggestionIds.has(record.suggestionId) || record.commentId === void 0) continue;
176
+ const storyKey = canonicalJson(record.story);
177
+ const commentIds = commentIdsByStory.get(storyKey) ?? /* @__PURE__ */ new Set();
178
+ commentIds.add(record.commentId);
179
+ commentIdsByStory.set(storyKey, commentIds);
180
+ }
181
+ for (const [key, record] of this.records) if (activeSuggestionIds.has(record.suggestionId)) {
182
+ const storyKey = canonicalJson(record.story);
183
+ let fingerprint = fingerprints.get(storyKey);
184
+ if (fingerprint === void 0) {
185
+ const snapshot = snapshotForStory(record.story, commentIdsByStory.get(storyKey) ?? /* @__PURE__ */ new Set());
186
+ if (!snapshot) continue;
187
+ fingerprint = fingerprintOf(snapshot, record.story);
188
+ fingerprints.set(storyKey, fingerprint);
189
+ }
190
+ const current = {
191
+ ...record,
192
+ sourceDocumentFingerprint: fingerprint
193
+ };
194
+ this.records.set(key, current);
195
+ pending.push(structuredClone(current));
196
+ } else this.records.delete(key);
197
+ for (const [storyKey, fingerprint] of fingerprints) this.sourceFingerprints.set(storyKey, fingerprint);
198
+ if (pending.length === 0) this.sourceFingerprints.clear();
199
+ return pending;
200
+ }
201
+ loadPendingSuggestions({ records, snapshotForStory, sourceSnapshotForStory, apply, activeSuggestionIds }) {
202
+ const baselines = /* @__PURE__ */ new Map();
203
+ const changedStories = /* @__PURE__ */ new Set();
204
+ return records.map((value) => {
205
+ const suggestionId = isObject(value) && typeof value["suggestionId"] === "string" ? value["suggestionId"] : null;
206
+ if (!isObject(value) || value["version"] !== 1) return {
207
+ status: "stale",
208
+ suggestionId,
209
+ reason: "unsupportedVersion"
210
+ };
211
+ const record = parseRecord(value);
212
+ if (!record) return {
213
+ status: "stale",
214
+ suggestionId,
215
+ reason: "invalidRecord"
216
+ };
217
+ const key = recordKey(record);
218
+ const existing = this.records.get(key);
219
+ if (existing && activeSuggestionIds().has(record.suggestionId)) {
220
+ const { commentId: _existingCommentId, ...existingProposal } = existing;
221
+ const { commentId: _loadedCommentId, ...loadedProposal } = record;
222
+ return canonicalJson(existingProposal) === canonicalJson(loadedProposal) ? {
223
+ status: "restaged",
224
+ suggestionId: record.suggestionId
225
+ } : {
226
+ status: "stale",
227
+ suggestionId,
228
+ reason: "invalidRecord"
229
+ };
230
+ }
231
+ const storyKey = canonicalJson(record.story);
232
+ if (!baselines.has(storyKey)) {
233
+ const snapshot = snapshotForStory(record.story);
234
+ const active = activeSuggestionIds();
235
+ const commentIds = /* @__PURE__ */ new Set();
236
+ for (const existingRecord of this.records.values()) if (canonicalJson(existingRecord.story) === storyKey && active.has(existingRecord.suggestionId) && existingRecord.commentId !== void 0) commentIds.add(existingRecord.commentId);
237
+ const source = sourceSnapshotForStory(record.story, commentIds);
238
+ baselines.set(storyKey, snapshot && source ? {
239
+ snapshot,
240
+ fingerprint: fingerprintOf(source, record.story)
241
+ } : null);
242
+ }
243
+ const baseline = baselines.get(storyKey);
244
+ if (!baseline || record.anchor.paraId === null) return {
245
+ status: "stale",
246
+ suggestionId,
247
+ reason: "missingAnchor"
248
+ };
249
+ const snapshot = changedStories.has(storyKey) ? snapshotForStory(record.story) : baseline.snapshot;
250
+ if (!snapshot) return {
251
+ status: "stale",
252
+ suggestionId,
253
+ reason: "missingAnchor"
254
+ };
255
+ const multiplicity = paraIdCountsOf(snapshot).get(record.anchor.paraId) ?? 0;
256
+ if (multiplicity === 0 || !snapshot.anchors[record.anchor.paraId]) return {
257
+ status: "stale",
258
+ suggestionId,
259
+ reason: "missingAnchor"
260
+ };
261
+ if (multiplicity > 1) return {
262
+ status: "stale",
263
+ suggestionId,
264
+ reason: "ambiguousAnchor"
265
+ };
266
+ const anchor = snapshot.anchors[record.anchor.paraId];
267
+ if (!anchor || anchor.textHash !== record.anchor.originalTextHash) return {
268
+ status: "stale",
269
+ suggestionId,
270
+ reason: "textChanged"
271
+ };
272
+ const { startOffset, endOffset, selectedTextHash } = record.anchor;
273
+ if (startOffset !== void 0 && endOffset !== void 0 && selectedTextHash !== void 0 && hashFolioAIBlockText(anchor.text.slice(startOffset, endOffset)) !== selectedTextHash) return {
274
+ status: "stale",
275
+ suggestionId,
276
+ reason: "textChanged"
277
+ };
278
+ if (baseline.fingerprint !== record.sourceDocumentFingerprint) return {
279
+ status: "stale",
280
+ suggestionId,
281
+ reason: "documentChanged"
282
+ };
283
+ const applied = apply(record, snapshot).applied.find((entry) => entry.id === record.operation.id);
284
+ if (!applied) return {
285
+ status: "stale",
286
+ suggestionId,
287
+ reason: "applyFailed"
288
+ };
289
+ this.sourceFingerprints.set(storyKey, record.sourceDocumentFingerprint);
290
+ if (!this.records.has(key)) {
291
+ const { commentId: _oldCommentId, ...rest } = record;
292
+ this.records.set(key, structuredClone({
293
+ ...rest,
294
+ ...applied.commentId !== void 0 && { commentId: applied.commentId }
295
+ }));
296
+ }
297
+ changedStories.add(storyKey);
298
+ return {
299
+ status: "restaged",
300
+ suggestionId: record.suggestionId
301
+ };
302
+ });
303
+ }
304
+ };
305
+ //#endregion
306
+ export { FOLIO_PENDING_SUGGESTION_VERSION, FolioPendingSuggestionRegistry, createPendingSuggestionSourceSnapshot, withoutPendingSuggestionCommentMarks };
@@ -62,14 +62,16 @@ type FolioCommentAnchor = {
62
62
  declare const getTrackedChangesFromSnapshot: (snapshot: FolioAIEditSnapshot) => FolioReviewChange[];
63
63
  /**
64
64
  * The tracked changes present in the body, read from inline marks and
65
- * structural node attributes. Runs of one inline revision within a block fold
66
- * into a single entry.
65
+ * structural node attributes. Adjacent runs sharing a revision wrapper path
66
+ * fold into one entry; interrupted or differently nested wrappers stay separate.
67
67
  *
68
68
  * A tracked row insertion or deletion marks the row AND every run in its
69
69
  * cells, the way Word writes it. Both halves are one change, so the run marks
70
70
  * fold into the row's entry rather than reporting a second time.
71
71
  */
72
72
  declare const getTrackedChangesFromDoc: (doc: Node) => FolioReviewChange[];
73
+ /** Physical revision ids behind an inline change split by markup. */
74
+ declare const getTrackedChangeGroupIdsFromDoc: (doc: Node, id: number) => number[];
73
75
  /** @internal Read revision statistics without paying for an unrelated block projection. */
74
76
  declare const getTrackedChangeStatsFromDoc: (doc: Node) => {
75
77
  highestId: number;
@@ -78,8 +80,8 @@ declare const getTrackedChangeStatsFromDoc: (doc: Node) => {
78
80
  /**
79
81
  * The comment anchors present in the body, read from the `comment` mark the
80
82
  * editor renders. Each entry carries the anchored text and containing block id;
81
- * runs of one comment id within the body fold into a single anchor.
83
+ * ranges for one comment id within the body fold into a single anchor.
82
84
  */
83
85
  declare const getCommentAnchorsFromDoc: (doc: Node) => FolioCommentAnchor[];
84
86
  //#endregion
85
- export { FOLIO_REVIEW_CHANGE_KINDS, FolioCommentAnchor, FolioReviewChange, FolioReviewChangeKind, getCommentAnchorsFromDoc, getTrackedChangeStatsFromDoc, getTrackedChangesFromDoc, getTrackedChangesFromSnapshot };
87
+ export { FOLIO_REVIEW_CHANGE_KINDS, FolioCommentAnchor, FolioReviewChange, FolioReviewChangeKind, getCommentAnchorsFromDoc, getTrackedChangeGroupIdsFromDoc, getTrackedChangeStatsFromDoc, getTrackedChangesFromDoc, getTrackedChangesFromSnapshot };
@@ -1,8 +1,10 @@
1
- import { expectRunPropertyChangeMarkAttrs } from "../prosemirror/attrs/index.js";
1
+ import { expectRunPropertyChangeMarkAttrs, expectTrackedChangeMarkAttrs } from "../prosemirror/attrs/index.js";
2
2
  import { getFolioNodeRevisionCarriers } from "../prosemirror/revisionCarriers.js";
3
3
  import { expandRunFormattingCarrier, runFormattingCarrierReviewText, runFormattingInlineAtomDisposition } from "../prosemirror/runFormattingInlineCarriers.js";
4
4
  import { getTableCellMergeChange } from "../prosemirror/tableCellMergeRevision.js";
5
- import { createFolioAIEditSnapshot, sourceDocumentOf } from "./snapshot.js";
5
+ import { enclosingInsertionAncestors, trackedRevisionLayerOf } from "../prosemirror/trackedRevisionPath.js";
6
+ import { readerTextOf } from "./note-references.js";
7
+ import { collectNoteReferenceLabels, createFolioAIEditSnapshot, sourceDocumentOf } from "./snapshot.js";
6
8
  //#region src/ai-edits/read.ts
7
9
  /**
8
10
  * Runtime census of every tracked-change discriminator the reviewer exposes.
@@ -50,23 +52,31 @@ const firstBlockIdWithin = ({ node, nodePos, blockStarts }) => {
50
52
  });
51
53
  return blockId;
52
54
  };
53
- /**
54
- * Whether a run's revision inside a marked row is that row's own. Folio writes
55
- * both halves under one revision id; Word mints a fresh `w:id` per element, so
56
- * an author + timestamp match counts too. A third party's edit inside the row
57
- * matches neither and keeps its own entry.
58
- */
59
55
  const belongsToRowRevision = (scope, revision) => revision.id === scope.change.id || revision.author === scope.change.author && revision.date === scope.change.date;
60
56
  /** Shared revision interpreter; a null block map omits unrelated block-id projection. */
61
- const getTrackedChangesFromProjectedDoc = (doc, blockStarts) => {
57
+ const getTrackedChangeGroupsFromProjectedDoc = (doc, blockStarts) => {
62
58
  const insertionType = doc.type.schema.marks["insertion"];
63
59
  const deletionType = doc.type.schema.marks["deletion"];
64
60
  const grouped = /* @__PURE__ */ new Map();
61
+ const inlineRanges = /* @__PURE__ */ new Map();
62
+ const lastInlineGroupByPath = /* @__PURE__ */ new Map();
63
+ const transparentInlineEnds = /* @__PURE__ */ new Map();
64
+ const transparentGap = (start, end) => {
65
+ let pos = start;
66
+ while (pos < end) {
67
+ const next = transparentInlineEnds.get(pos);
68
+ if (next === void 0) return false;
69
+ pos = next;
70
+ }
71
+ return pos === end;
72
+ };
65
73
  const structuralChangeCellPositions = /* @__PURE__ */ new Map();
66
74
  const rowRevisionScopes = [];
67
75
  const derivedFormattingRepresentationPositions = /* @__PURE__ */ new Set();
76
+ const noteReferences = collectNoteReferenceLabels(doc);
68
77
  let currentBlockId = null;
69
78
  doc.descendants((node, pos) => {
79
+ if (node.type.name === "commentReference") transparentInlineEnds.set(pos, pos + node.nodeSize);
70
80
  while (pos >= (rowRevisionScopes.at(-1)?.end ?? Number.POSITIVE_INFINITY)) rowRevisionScopes.pop();
71
81
  const nodeRevisionCarriers = getFolioNodeRevisionCarriers(node, pos);
72
82
  if (nodeRevisionCarriers.length > 0) {
@@ -207,25 +217,50 @@ const getTrackedChangesFromProjectedDoc = (doc, blockStarts) => {
207
217
  }
208
218
  }
209
219
  }
210
- const text = node.text ?? "";
211
- for (const mark of node.marks) {
212
- if (mark.type.name === "runPropertyChange") continue;
213
- if (typeof mark.attrs["revisionId"] !== "number") continue;
214
- let kind;
215
- if (mark.type === insertionType) kind = "insertion";
216
- else if (mark.type === deletionType) kind = "deletion";
217
- else continue;
218
- const revisionId = mark.attrs["revisionId"];
219
- const author = mark.attrs["author"];
220
- const date = mark.attrs["date"];
221
- const revision = {
222
- id: revisionId,
223
- author: typeof author === "string" ? author : "",
224
- date: typeof date === "string" ? date : null
225
- };
220
+ const text = readerTextOf(node, noteReferences);
221
+ const insertionMark = node.marks.find((mark) => mark.type === insertionType);
222
+ const deletionMark = node.marks.find((mark) => mark.type === deletionType);
223
+ const mark = deletionMark ?? insertionMark;
224
+ if (!mark || typeof mark.attrs["revisionId"] !== "number") return;
225
+ const attrs = expectTrackedChangeMarkAttrs(mark);
226
+ const pathLayers = [...enclosingInsertionAncestors({
227
+ insertionMark: deletionMark ? insertionMark : void 0,
228
+ ancestors: attrs._docxRevisionAncestors ?? [],
229
+ node
230
+ }), trackedRevisionLayerOf(mark, node)];
231
+ const layers = pathLayers.map((layer) => ({
232
+ kind: layer.type === "insertion" || layer.type === "moveTo" ? "insertion" : "deletion",
233
+ revision: {
234
+ id: layer.revisionId,
235
+ author: layer.author,
236
+ date: layer.date ?? null
237
+ }
238
+ }));
239
+ for (const [layerIndex, { kind: layerKind, revision }] of layers.entries()) {
226
240
  const rowScope = rowRevisionScopes.at(-1);
227
- if (rowScope?.kind === kind && belongsToRowRevision(rowScope, revision)) continue;
228
- const key = `${currentBlockId ?? ""}:${kind}:${revisionId}`;
241
+ if (rowScope?.kind === layerKind && belongsToRowRevision(rowScope, revision)) continue;
242
+ const path = `${currentBlockId ?? ""}:${JSON.stringify(pathLayers.slice(0, layerIndex + 1))}`;
243
+ const previousKey = lastInlineGroupByPath.get(path);
244
+ const previousRange = previousKey === void 0 ? void 0 : inlineRanges.get(previousKey);
245
+ const key = previousKey !== void 0 && previousRange && transparentGap(previousRange.end, pos) ? previousKey : `${path}:${pos}`;
246
+ lastInlineGroupByPath.set(path, key);
247
+ const hyperlink = node.marks.find((candidate) => candidate.type.name === "hyperlink");
248
+ const commentId = node.marks.find((candidate) => candidate.type.name === "comment")?.attrs["commentId"];
249
+ const boundary = {
250
+ hyperlink: hyperlink ? String(hyperlink.attrs["href"] ?? "") : null,
251
+ comment: typeof commentId === "number" ? commentId : null,
252
+ revisionParents: JSON.stringify(pathLayers.slice(0, layerIndex))
253
+ };
254
+ const range = inlineRanges.get(key);
255
+ if (range) {
256
+ range.end = pos + node.nodeSize;
257
+ range.lastBoundary = boundary;
258
+ } else inlineRanges.set(key, {
259
+ start: pos,
260
+ end: pos + node.nodeSize,
261
+ firstBoundary: boundary,
262
+ lastBoundary: boundary
263
+ });
229
264
  const existing = grouped.get(key);
230
265
  if (existing) {
231
266
  existing.text += text;
@@ -233,71 +268,99 @@ const getTrackedChangesFromProjectedDoc = (doc, blockStarts) => {
233
268
  }
234
269
  grouped.set(key, {
235
270
  ...revision,
236
- type: kind,
271
+ type: layerKind,
237
272
  text,
238
273
  blockId: currentBlockId
239
274
  });
240
275
  }
241
276
  });
242
- return [...grouped.values()];
277
+ const groups = [];
278
+ let previousKey = null;
279
+ for (const [key, change] of grouped) {
280
+ const range = inlineRanges.get(key);
281
+ const previous = groups.at(-1);
282
+ const previousRange = previousKey === null ? void 0 : inlineRanges.get(previousKey);
283
+ if (previous && range && previousRange && previousRange.end <= range.start && transparentGap(previousRange.end, range.start) && previousRange.lastBoundary.revisionParents === range.firstBoundary.revisionParents && (previousRange.lastBoundary.hyperlink !== range.firstBoundary.hyperlink || previousRange.lastBoundary.comment !== range.firstBoundary.comment || previousRange.end !== range.start) && (change.type === "insertion" || change.type === "deletion") && previous.change.type === change.type && previous.change.author === change.author && previous.change.date === change.date && previous.change.blockId === change.blockId) {
284
+ previous.change.text += change.text;
285
+ previous.ids.push(change.id);
286
+ previousRange.end = range.end;
287
+ previousRange.lastBoundary = range.lastBoundary;
288
+ continue;
289
+ }
290
+ groups.push({
291
+ change: { ...change },
292
+ ids: [change.id]
293
+ });
294
+ previousKey = key;
295
+ }
296
+ return groups;
243
297
  };
298
+ const getTrackedChangesFromProjectedDoc = (doc, blockStarts) => getTrackedChangeGroupsFromProjectedDoc(doc, blockStarts).map(({ change }) => change);
244
299
  /** Read revisions from the exact immutable document that produced a snapshot. */
245
300
  const getTrackedChangesFromSnapshot = (snapshot) => getTrackedChangesFromProjectedDoc(sourceDocumentOf(snapshot), blockStartIdsFromSnapshot(snapshot));
246
301
  /**
247
302
  * The tracked changes present in the body, read from inline marks and
248
- * structural node attributes. Runs of one inline revision within a block fold
249
- * into a single entry.
303
+ * structural node attributes. Adjacent runs sharing a revision wrapper path
304
+ * fold into one entry; interrupted or differently nested wrappers stay separate.
250
305
  *
251
306
  * A tracked row insertion or deletion marks the row AND every run in its
252
307
  * cells, the way Word writes it. Both halves are one change, so the run marks
253
308
  * fold into the row's entry rather than reporting a second time.
254
309
  */
255
310
  const getTrackedChangesFromDoc = (doc) => getTrackedChangesFromProjectedDoc(doc, blockStartIdsFromDoc(doc));
311
+ /** Physical revision ids behind an inline change split by markup. */
312
+ const getTrackedChangeGroupIdsFromDoc = (doc, id) => getTrackedChangeGroupsFromProjectedDoc(doc, blockStartIdsFromDoc(doc)).find(({ ids }) => ids.includes(id))?.ids ?? [id];
256
313
  /** @internal Read revision statistics without paying for an unrelated block projection. */
257
314
  const getTrackedChangeStatsFromDoc = (doc) => {
258
315
  let highestId = 0;
259
- const changes = getTrackedChangesFromProjectedDoc(doc, null);
260
- for (const change of changes) highestId = Math.max(highestId, change.id);
316
+ const groups = getTrackedChangeGroupsFromProjectedDoc(doc, null);
317
+ for (const { ids } of groups) for (const id of ids) highestId = Math.max(highestId, id);
261
318
  return {
262
319
  highestId,
263
- present: changes.length > 0
320
+ present: groups.length > 0
264
321
  };
265
322
  };
266
323
  /**
267
324
  * The comment anchors present in the body, read from the `comment` mark the
268
325
  * editor renders. Each entry carries the anchored text and containing block id;
269
- * runs of one comment id within the body fold into a single anchor.
326
+ * ranges for one comment id within the body fold into a single anchor.
270
327
  */
271
328
  const getCommentAnchorsFromDoc = (doc) => {
272
329
  const commentType = doc.type.schema.marks["comment"];
273
330
  if (!commentType) return [];
274
331
  const blockStarts = blockStartIdsFromDoc(doc);
275
- const anchors = /* @__PURE__ */ new Map();
332
+ const ranges = /* @__PURE__ */ new Map();
333
+ const noteReferences = collectNoteReferenceLabels(doc);
276
334
  let currentBlockId = null;
335
+ let bodyText = "";
277
336
  doc.descendants((node, pos) => {
278
337
  if (node.isTextblock) {
279
338
  currentBlockId = blockStarts.get(pos) ?? null;
280
339
  return true;
281
340
  }
282
341
  if (!node.isInline || node.text === void 0) return;
283
- const text = node.text;
342
+ const text = readerTextOf(node, noteReferences);
343
+ const end = bodyText.length + text.length;
284
344
  for (const mark of node.marks) {
285
345
  if (mark.type !== commentType || typeof mark.attrs["commentId"] !== "number") continue;
286
346
  const commentId = mark.attrs["commentId"];
287
- const existing = anchors.get(commentId);
288
- if (!existing) {
289
- anchors.set(commentId, {
290
- commentId,
291
- blockId: currentBlockId,
292
- quote: text
293
- });
294
- continue;
295
- }
296
- existing.quote += text;
297
- existing.blockId ??= currentBlockId;
347
+ const range = ranges.get(commentId);
348
+ if (range) {
349
+ range.end = end;
350
+ range.blockId ??= currentBlockId;
351
+ } else ranges.set(commentId, {
352
+ blockId: currentBlockId,
353
+ start: bodyText.length,
354
+ end
355
+ });
298
356
  }
357
+ bodyText += text;
299
358
  });
300
- return [...anchors.values()];
359
+ return [...ranges].map(([commentId, { blockId, start, end }]) => ({
360
+ commentId,
361
+ blockId,
362
+ quote: bodyText.slice(start, end)
363
+ }));
301
364
  };
302
365
  //#endregion
303
- export { FOLIO_REVIEW_CHANGE_KINDS, getCommentAnchorsFromDoc, getTrackedChangeStatsFromDoc, getTrackedChangesFromDoc, getTrackedChangesFromSnapshot };
366
+ export { FOLIO_REVIEW_CHANGE_KINDS, getCommentAnchorsFromDoc, getTrackedChangeGroupIdsFromDoc, getTrackedChangeStatsFromDoc, getTrackedChangesFromDoc, getTrackedChangesFromSnapshot };