@stll/folio-core 0.46.0 → 0.47.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 (366) hide show
  1. package/dist/ai-edits/apply.js +26 -24
  2. package/dist/ai-edits/headless.js +1 -1
  3. package/dist/ai-edits/read.d.ts +1 -0
  4. package/dist/ai-edits/read.js +1 -0
  5. package/dist/ai-edits/snapshot.js +32 -27
  6. package/dist/ai-edits/table-cell-mutations.js +15 -7
  7. package/dist/ai-edits/table-geometry.js +21 -18
  8. package/dist/ai-edits/table-template.js +2 -2
  9. package/dist/compare/content-alignment.js +108 -12
  10. package/dist/compare/content-types.d.ts +8 -2
  11. package/dist/compare/content.js +2 -11
  12. package/dist/compare/plan.js +7 -4
  13. package/dist/compare/section-boundary-properties.js +1 -2
  14. package/dist/content-controls/checkboxDisplay.d.ts +8 -2
  15. package/dist/content-controls/checkboxDisplay.js +11 -5
  16. package/dist/content-controls/mutateContentControls.js +41 -42
  17. package/dist/controller/layoutPipeline.js +8 -3
  18. package/dist/display-list/build/buildDisplayList.js +7 -7
  19. package/dist/display-list/build/imagePrimitives.d.ts +4 -4
  20. package/dist/display-list/build/imagePrimitives.js +38 -20
  21. package/dist/display-list/build/pageBorderPrimitives.js +2 -1
  22. package/dist/display-list/build/paragraphPrimitives.js +93 -13
  23. package/dist/display-list/build/previewPrimitives.d.ts +10 -0
  24. package/dist/display-list/build/previewPrimitives.js +89 -0
  25. package/dist/display-list/build/strokes.d.ts +177 -8
  26. package/dist/display-list/build/strokes.js +167 -47
  27. package/dist/display-list/build/tablePrimitives.js +4 -2
  28. package/dist/display-list/build/textBoxPrimitives.js +6 -4
  29. package/dist/display-list/build/textDecorations.d.ts +15 -1
  30. package/dist/display-list/build/textDecorations.js +15 -1
  31. package/dist/display-list/dom/renderDisplayListToDom.js +1 -19
  32. package/dist/display-list/primitives.d.ts +13 -2
  33. package/dist/display-list/primitives.js +36 -1
  34. package/dist/document-operations.js +2 -1
  35. package/dist/docx/attributeRemainder.d.ts +34 -1
  36. package/dist/docx/attributeRemainder.js +49 -3
  37. package/dist/docx/blockContentParser.d.ts +2 -0
  38. package/dist/docx/blockContentParser.js +39 -67
  39. package/dist/docx/blockPlainText.js +3 -1
  40. package/dist/docx/borderParser.js +26 -11
  41. package/dist/docx/builtInStyles.d.ts +8 -16
  42. package/dist/docx/builtInStyles.js +54 -17
  43. package/dist/docx/commentAnchorIndex.js +1 -1
  44. package/dist/docx/commentParser.js +3 -3
  45. package/dist/docx/commentRangeIntegrity.js +1 -1
  46. package/dist/docx/commentRangeJoin.js +1 -1
  47. package/dist/docx/commentReferenceNormalization.js +3 -2
  48. package/dist/docx/commentReplyMarkers.js +1 -1
  49. package/dist/docx/compatibility.js +56 -42
  50. package/dist/docx/containerChildren.d.ts +110 -13
  51. package/dist/docx/containerChildren.gen.d.ts +16 -1
  52. package/dist/docx/containerChildren.gen.js +18 -1
  53. package/dist/docx/containerChildren.js +63 -13
  54. package/dist/docx/diagramPreview.d.ts +14 -2
  55. package/dist/docx/diagramPreview.js +81 -169
  56. package/dist/docx/documentParser.js +4 -1
  57. package/dist/docx/drawingAnchor.d.ts +87 -0
  58. package/dist/docx/drawingAnchor.js +201 -0
  59. package/dist/docx/drawingUtils.d.ts +43 -38
  60. package/dist/docx/drawingUtils.js +205 -118
  61. package/dist/docx/fontTableParser.js +102 -41
  62. package/dist/docx/footnoteParser.js +10 -6
  63. package/dist/docx/groupDrawingParser.js +4 -3
  64. package/dist/docx/headerFooterReferenceNormalization.js +1 -1
  65. package/dist/docx/hyperlinkParser.d.ts +45 -7
  66. package/dist/docx/hyperlinkParser.js +126 -57
  67. package/dist/docx/imageParser.js +127 -107
  68. package/dist/docx/index.d.ts +2 -1
  69. package/dist/docx/index.js +2 -1
  70. package/dist/docx/inlineContentRemovals.d.ts +28 -0
  71. package/dist/docx/inlineContentRemovals.js +46 -0
  72. package/dist/docx/inlineWrapperContent.d.ts +84 -3
  73. package/dist/docx/inlineWrapperContent.js +85 -4
  74. package/dist/docx/inlineWrapperParser.d.ts +11 -0
  75. package/dist/docx/inlineWrapperParser.js +60 -0
  76. package/dist/docx/nonVisualDrawingProps.d.ts +5 -13
  77. package/dist/docx/normalizeBaseDirection.js +4 -2
  78. package/dist/docx/numberingParser.d.ts +25 -2
  79. package/dist/docx/numberingParser.js +264 -361
  80. package/dist/docx/numberingReference.d.ts +9 -16
  81. package/dist/docx/numberingReference.js +17 -16
  82. package/dist/docx/numberingReferenceNormalization.js +7 -7
  83. package/dist/docx/ooxmlCounterFormatter.d.ts +1 -1
  84. package/dist/docx/ooxmlCounterFormatter.js +4 -1
  85. package/dist/docx/paraIdAttribute.d.ts +91 -1
  86. package/dist/docx/paraIdAttribute.js +79 -1
  87. package/dist/docx/paragraphParser.d.ts +9 -24
  88. package/dist/docx/paragraphParser.js +212 -396
  89. package/dist/docx/paragraphProperties.d.ts +23 -0
  90. package/dist/docx/paragraphProperties.js +279 -0
  91. package/dist/docx/paragraphPropertySource.js +2 -0
  92. package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
  93. package/dist/docx/paragraphTextBoxEnrichment.js +14 -7
  94. package/dist/docx/paragraphTraversal.d.ts +14 -10
  95. package/dist/docx/paragraphTraversal.js +47 -49
  96. package/dist/docx/parseWarningMessage.js +3 -0
  97. package/dist/docx/parserEnums.d.ts +6 -8
  98. package/dist/docx/parserEnums.js +4 -6
  99. package/dist/docx/preservedRunContent.js +16 -6
  100. package/dist/docx/previewBudget.d.ts +44 -23
  101. package/dist/docx/previewBudget.js +61 -30
  102. package/dist/docx/propertyElementAttributes.d.ts +178 -0
  103. package/dist/docx/propertyElementAttributes.js +114 -0
  104. package/dist/docx/renderedPageBreakNormalization.js +2 -2
  105. package/dist/docx/rezip.d.ts +28 -2
  106. package/dist/docx/rezip.js +78 -9
  107. package/dist/docx/runConsolidator.d.ts +42 -2
  108. package/dist/docx/runConsolidator.js +60 -6
  109. package/dist/docx/runParser.d.ts +54 -18
  110. package/dist/docx/runParser.js +379 -295
  111. package/dist/docx/runPayload.d.ts +5 -0
  112. package/dist/docx/runPayload.js +4 -0
  113. package/dist/docx/sdtProperties.d.ts +39 -5
  114. package/dist/docx/sdtProperties.js +205 -84
  115. package/dist/docx/sdtPropertiesPatch.d.ts +5 -9
  116. package/dist/docx/sdtPropertiesPatch.js +68 -112
  117. package/dist/docx/sectionParser.d.ts +1 -2
  118. package/dist/docx/sectionParser.js +236 -240
  119. package/dist/docx/selectiveSave.js +3 -2
  120. package/dist/docx/selectiveXmlPatch.d.ts +21 -2
  121. package/dist/docx/selectiveXmlPatch.js +195 -99
  122. package/dist/docx/serializer/blockSdtSerializer.js +2 -96
  123. package/dist/docx/serializer/borderSerializer.d.ts +5 -5
  124. package/dist/docx/serializer/borderSerializer.js +10 -8
  125. package/dist/docx/serializer/documentSerializer.js +3 -0
  126. package/dist/docx/serializer/fontTableSerializer.js +31 -3
  127. package/dist/docx/serializer/headerFooterSerializer.js +3 -0
  128. package/dist/docx/serializer/markupRangeAttributes.d.ts +9 -1
  129. package/dist/docx/serializer/markupRangeAttributes.js +9 -1
  130. package/dist/docx/serializer/noteSerializer.js +3 -0
  131. package/dist/docx/serializer/numberingSerializer.d.ts +1 -6
  132. package/dist/docx/serializer/numberingSerializer.js +81 -79
  133. package/dist/docx/serializer/paragraphSerializer.d.ts +1 -9
  134. package/dist/docx/serializer/paragraphSerializer.js +88 -188
  135. package/dist/docx/serializer/runSerializer.d.ts +1 -5
  136. package/dist/docx/serializer/runSerializer.js +109 -59
  137. package/dist/docx/serializer/sdtPropertiesSerializer.d.ts +26 -0
  138. package/dist/docx/serializer/sdtPropertiesSerializer.js +111 -0
  139. package/dist/docx/serializer/sectionPropertiesSerializer.js +34 -45
  140. package/dist/docx/serializer/settingsSerializer.js +6 -4
  141. package/dist/docx/serializer/stylesSerializer.js +8 -11
  142. package/dist/docx/serializer/tableSerializer.js +268 -100
  143. package/dist/docx/serializer/textFormattingSerializer.d.ts +28 -4
  144. package/dist/docx/serializer/textFormattingSerializer.js +111 -101
  145. package/dist/docx/serializer/xmlUtils.d.ts +1 -1
  146. package/dist/docx/serializer/xmlUtils.js +1 -1
  147. package/dist/docx/server/createBilingualDocument.js +18 -16
  148. package/dist/docx/server/migrateYjsAttrSchema.js +3 -3
  149. package/dist/docx/settingsParser.js +7 -4
  150. package/dist/docx/shadingParser.d.ts +2 -1
  151. package/dist/docx/shadingParser.js +43 -7
  152. package/dist/docx/shapeParser.js +8 -3
  153. package/dist/docx/strictNames.d.ts +11 -0
  154. package/dist/docx/strictNames.gen.d.ts +45 -0
  155. package/dist/docx/strictNames.gen.js +50 -0
  156. package/dist/docx/strictNames.js +43 -0
  157. package/dist/docx/strictValueEncodings.gen.js +133 -131
  158. package/dist/docx/styleParser.js +17 -349
  159. package/dist/docx/tableParser.d.ts +10 -1
  160. package/dist/docx/tableParser.js +505 -181
  161. package/dist/docx/textBoxParser.d.ts +3 -1
  162. package/dist/docx/textBoxParser.js +18 -8
  163. package/dist/docx/themeColorAttribute.d.ts +13 -0
  164. package/dist/docx/themeColorAttribute.js +24 -0
  165. package/dist/docx/trackedMoveRangeNormalization.js +2 -1
  166. package/dist/docx/vmlImageParser.d.ts +13 -4
  167. package/dist/docx/vmlImageParser.js +74 -31
  168. package/dist/docx/vmlPreview.js +2 -2
  169. package/dist/docx/wrapPolygon.d.ts +30 -0
  170. package/dist/docx/wrapPolygon.js +70 -0
  171. package/dist/docx/xmlParser.d.ts +14 -1
  172. package/dist/docx/xmlParser.js +18 -2
  173. package/dist/fonts/embeddedFonts.js +3 -3
  174. package/dist/headless-layout.js +2 -0
  175. package/dist/i18n/messages/catalogs.gen.d.ts +68 -0
  176. package/dist/i18n/messages/catalogs.gen.js +102 -34
  177. package/dist/i18n/messages/messages.gen.d.ts +4 -0
  178. package/dist/internal/headlessRevisionResolution.js +9 -0
  179. package/dist/internal/pageBreakRunSourceDescendantIndex.js +3 -1
  180. package/dist/internal/paragraphFormattingSerialization.d.ts +20 -9
  181. package/dist/internal/paragraphFormattingSerialization.js +118 -83
  182. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  183. package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
  184. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  185. package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
  186. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +17 -12
  187. package/dist/layout-bridge/convert/toFlowBlocks.js +177 -101
  188. package/dist/layout-engine/index.d.ts +2 -2
  189. package/dist/layout-engine/index.js +53 -17
  190. package/dist/layout-engine/measure/measureBlocks.d.ts +3 -0
  191. package/dist/layout-engine/measure/measureBlocks.js +6 -10
  192. package/dist/layout-engine/measure/tableCellGrid.js +2 -1
  193. package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +2 -1
  194. package/dist/layout-engine/measure/tableInlinePlacement.js +2 -5
  195. package/dist/layout-engine/paragraphSequence.js +3 -2
  196. package/dist/layout-engine/renderedBreakReconciliation.js +2 -1
  197. package/dist/layout-engine/section-breaks.d.ts +49 -2
  198. package/dist/layout-engine/section-breaks.js +55 -4
  199. package/dist/layout-engine/types.d.ts +47 -17
  200. package/dist/layout-engine/types.js +16 -1
  201. package/dist/layout-painter/borderStroke.d.ts +18 -4
  202. package/dist/layout-painter/renderPage.js +6 -4
  203. package/dist/layout-painter/renderParagraph.d.ts +2 -1
  204. package/dist/layout-painter/renderParagraph.js +13 -26
  205. package/dist/layout-painter/renderTable.d.ts +4 -1
  206. package/dist/layout-painter/renderTable.js +22 -22
  207. package/dist/layout-painter/renderTextBox.js +5 -3
  208. package/dist/markdown/renderBlock.js +3 -1
  209. package/dist/markdown/renderRuns.js +7 -2
  210. package/dist/markdown/renderTable.js +2 -1
  211. package/dist/model.d.ts +3 -3
  212. package/dist/model.js +2 -2
  213. package/dist/paged-layout/sectionBlockWidths.d.ts +3 -0
  214. package/dist/paged-layout/sectionBlockWidths.js +26 -4
  215. package/dist/prosemirror/attrs/index.d.ts +22 -4
  216. package/dist/prosemirror/attrs/index.js +498 -60
  217. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +9 -1
  218. package/dist/prosemirror/bookmarkBoundaryAttrs.js +22 -3
  219. package/dist/prosemirror/commands/comments.js +68 -53
  220. package/dist/prosemirror/commands/contentControls.js +24 -19
  221. package/dist/prosemirror/commands/image.d.ts +1 -1
  222. package/dist/prosemirror/commands/image.js +4 -1
  223. package/dist/prosemirror/commands/paragraph.d.ts +2 -1
  224. package/dist/prosemirror/commands/propertyChangeScope.d.ts +12 -4
  225. package/dist/prosemirror/commands/propertyChangeScope.js +22 -4
  226. package/dist/prosemirror/commands/sectionBreak.d.ts +33 -1
  227. package/dist/prosemirror/commands/sectionBreak.js +187 -11
  228. package/dist/prosemirror/conversion/fromProseDoc.d.ts +18 -2
  229. package/dist/prosemirror/conversion/fromProseDoc.js +330 -183
  230. package/dist/prosemirror/conversion/index.d.ts +2 -2
  231. package/dist/prosemirror/conversion/preservedSinkCarriers.d.ts +39 -0
  232. package/dist/prosemirror/conversion/preservedSinkCarriers.js +19 -0
  233. package/dist/prosemirror/conversion/runShadingMark.js +14 -1
  234. package/dist/prosemirror/conversion/sdtAttrs.d.ts +10 -1
  235. package/dist/prosemirror/conversion/sdtAttrs.js +19 -5
  236. package/dist/prosemirror/conversion/toProseDoc.js +371 -141
  237. package/dist/prosemirror/emptyRangeAnchor.d.ts +53 -0
  238. package/dist/prosemirror/emptyRangeAnchor.js +158 -0
  239. package/dist/prosemirror/extensions/StarterKit.js +8 -2
  240. package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
  241. package/dist/prosemirror/extensions/core/ParagraphExtension.js +19 -15
  242. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +3 -2
  243. package/dist/prosemirror/extensions/features/ListExtension.js +43 -24
  244. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +4 -3
  245. package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +3 -3
  246. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +5 -5
  247. package/dist/prosemirror/extensions/features/pasteCleanup.d.ts +3 -1
  248. package/dist/prosemirror/extensions/features/pasteCleanup.js +56 -2
  249. package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +5 -4
  250. package/dist/prosemirror/extensions/markRegistry.d.ts +26 -2
  251. package/dist/prosemirror/extensions/markRegistry.js +73 -10
  252. package/dist/prosemirror/extensions/marks/InlineWrapperExtension.js +17 -3
  253. package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +26 -0
  254. package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +134 -0
  255. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -1
  256. package/dist/prosemirror/extensions/marks/UnderlineExtension.js +12 -18
  257. package/dist/prosemirror/extensions/marks/markUtils.js +2 -1
  258. package/dist/prosemirror/extensions/nodes/BlockBookmarkBoundaryExtension.d.ts +29 -0
  259. package/dist/prosemirror/extensions/nodes/BlockBookmarkBoundaryExtension.js +46 -0
  260. package/dist/prosemirror/extensions/nodes/BlockSdtExtension.d.ts +4 -3
  261. package/dist/prosemirror/extensions/nodes/BlockSdtExtension.js +18 -13
  262. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +28 -53
  263. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +10 -0
  264. package/dist/prosemirror/extensions/nodes/ImageExtension.js +8 -1
  265. package/dist/prosemirror/extensions/nodes/MoveRangeBoundaryExtension.d.ts +11 -0
  266. package/dist/prosemirror/extensions/nodes/MoveRangeBoundaryExtension.js +43 -0
  267. package/dist/prosemirror/extensions/nodes/RangeAnchorExtension.d.ts +13 -0
  268. package/dist/prosemirror/extensions/nodes/RangeAnchorExtension.js +65 -0
  269. package/dist/prosemirror/extensions/nodes/SdtExtension.d.ts +3 -1
  270. package/dist/prosemirror/extensions/nodes/SdtExtension.js +22 -16
  271. package/dist/prosemirror/extensions/nodes/ShapeExtension.js +4 -0
  272. package/dist/prosemirror/extensions/nodes/TableExtension.js +141 -123
  273. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +4 -0
  274. package/dist/prosemirror/extensions/nodes/bookmarkBoundaryDom.d.ts +23 -0
  275. package/dist/prosemirror/extensions/nodes/bookmarkBoundaryDom.js +57 -0
  276. package/dist/prosemirror/extensions/types.d.ts +12 -3
  277. package/dist/prosemirror/index.d.ts +4 -2
  278. package/dist/prosemirror/index.js +2 -1
  279. package/dist/prosemirror/inlineWrapperStack.js +20 -3
  280. package/dist/prosemirror/listMarker.d.ts +2 -2
  281. package/dist/prosemirror/listMarker.js +7 -8
  282. package/dist/prosemirror/listRenderingAttrs.js +11 -1
  283. package/dist/prosemirror/listState.d.ts +62 -0
  284. package/dist/prosemirror/listState.js +49 -0
  285. package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +13 -0
  286. package/dist/prosemirror/moveRangeBoundaryAttrs.js +114 -0
  287. package/dist/prosemirror/numberedRefFields.js +4 -4
  288. package/dist/prosemirror/numberingAttr.d.ts +55 -0
  289. package/dist/prosemirror/numberingAttr.js +74 -0
  290. package/dist/prosemirror/outlineLevelAttr.d.ts +29 -0
  291. package/dist/prosemirror/outlineLevelAttr.js +42 -0
  292. package/dist/prosemirror/paragraphFormattingProvenance.d.ts +9 -0
  293. package/dist/prosemirror/paragraphFormattingProvenance.js +4 -1
  294. package/dist/prosemirror/plugins/selectionTracker.d.ts +3 -6
  295. package/dist/prosemirror/plugins/selectionTracker.js +3 -10
  296. package/dist/prosemirror/rangeAnchorAttrs.d.ts +14 -0
  297. package/dist/prosemirror/rangeAnchorAttrs.js +101 -0
  298. package/dist/prosemirror/replacedAnnotations.d.ts +1 -1
  299. package/dist/prosemirror/replacedAnnotations.js +24 -6
  300. package/dist/prosemirror/revisionCarriers.d.ts +86 -2
  301. package/dist/prosemirror/revisionCarriers.js +86 -60
  302. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -0
  303. package/dist/prosemirror/runFormattingInlineCarriers.js +2 -0
  304. package/dist/prosemirror/runIdentity.d.ts +28 -0
  305. package/dist/prosemirror/runIdentity.js +36 -0
  306. package/dist/prosemirror/runStyleFormatting.js +1 -1
  307. package/dist/prosemirror/schema/index.d.ts +2 -2
  308. package/dist/prosemirror/schema/marks.d.ts +23 -4
  309. package/dist/prosemirror/schema/nodes.d.ts +220 -24
  310. package/dist/prosemirror/sectionCarrier.d.ts +37 -0
  311. package/dist/prosemirror/sectionCarrier.js +40 -0
  312. package/dist/prosemirror/selectionState.d.ts +3 -0
  313. package/dist/prosemirror/selectionState.js +4 -1
  314. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +5 -4
  315. package/dist/prosemirror/styles/resolvedStyleAttrs.js +15 -13
  316. package/dist/prosemirror/tableResize.js +5 -6
  317. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +2 -0
  318. package/dist/prosemirror/trackedRunInlineAtoms.js +2 -0
  319. package/dist/prosemirror/utils/extractTrackedChanges.d.ts +10 -11
  320. package/dist/prosemirror/utils/extractTrackedChanges.js +109 -92
  321. package/dist/prosemirror/validation.js +17 -6
  322. package/dist/prosemirror/yjsDocumentMetadata.d.ts +2 -2
  323. package/dist/prosemirror/yjsDocumentMetadata.js +428 -7
  324. package/dist/prosemirror/zeroWidthAnchors.js +4 -0
  325. package/dist/style-sets/extract.js +4 -4
  326. package/dist/style-sets/stellaStyle.js +36 -23
  327. package/dist/types/colors.d.ts +2 -2
  328. package/dist/types/content.d.ts +2 -2
  329. package/dist/types/documentEnumValues.d.ts +53 -26
  330. package/dist/types/documentEnumValues.js +72 -174
  331. package/dist/types/formatting.d.ts +2 -2
  332. package/dist/types/index.d.ts +9 -2
  333. package/dist/utils/borderCss.d.ts +246 -0
  334. package/dist/utils/borderCss.js +325 -0
  335. package/dist/utils/colorResolver.d.ts +4 -3
  336. package/dist/utils/colorResolver.js +45 -76
  337. package/dist/utils/createDocument.js +24 -6
  338. package/dist/utils/findReplace.js +52 -10
  339. package/dist/utils/formatToStyle.d.ts +84 -2
  340. package/dist/utils/formatToStyle.js +133 -52
  341. package/dist/utils/headingCollector.js +3 -2
  342. package/dist/utils/mergeDocumentContent.js +5 -3
  343. package/dist/utils/paragraphFormattingMerge.js +27 -6
  344. package/dist/utils/replaceText.js +1 -1
  345. package/dist/utils/tableOperations.d.ts +5 -3
  346. package/dist/utils/tableOperations.js +14 -1
  347. package/dist/utils/tablePlacement.d.ts +7 -0
  348. package/dist/utils/tablePlacement.js +14 -0
  349. package/dist/utils/textDirectionFlow.d.ts +15 -0
  350. package/dist/utils/textDirectionFlow.js +38 -0
  351. package/dist/utils/textFormattingMerge.js +16 -4
  352. package/package.json +10 -10
  353. package/dist/ai-edits/__fixtures__/paragraphs.d.ts +0 -17
  354. package/dist/ai-edits/__fixtures__/paragraphs.js +0 -33
  355. package/dist/compare/__fixtures__/body-sequence.d.ts +0 -119
  356. package/dist/compare/__fixtures__/body-sequence.js +0 -225
  357. package/dist/compare/__fixtures__/nested-table.d.ts +0 -16
  358. package/dist/compare/__fixtures__/nested-table.js +0 -50
  359. package/dist/compare/__fixtures__/numbered-list.d.ts +0 -34
  360. package/dist/compare/__fixtures__/numbered-list.js +0 -85
  361. package/dist/docx/bookmarkPlacement.d.ts +0 -9
  362. package/dist/docx/bookmarkPlacement.js +0 -52
  363. package/dist/fonts/embeddedFontTable.d.ts +0 -45
  364. package/dist/fonts/embeddedFontTable.js +0 -80
  365. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.d.ts +0 -13
  366. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.js +0 -39
@@ -1,3 +1,4 @@
1
+ import { paragraphNumberingReference, paragraphNumberingReferenceId } from "../docx/numberingReference.js";
1
2
  import { formattingEquals } from "../docx/runConsolidator.js";
2
3
  import { expectParagraphAttrs, expectRunPropertyChangeMarkAttrs } from "../prosemirror/attrs/index.js";
3
4
  import { hasSerializableParagraphPropertyChange, paragraphPropertiesSnapshot } from "../prosemirror/commands/propertyChangeScope.js";
@@ -5,6 +6,7 @@ import { addedBreakCarrierBefore, finalParagraphsOf, paragraphEndsItsContainer }
5
6
  import { requestDeterministicParaIds } from "../prosemirror/extensions/features/ParaIdAllocatorExtension.js";
6
7
  import { markStructuralChange } from "../prosemirror/extensions/features/ParagraphChangeTrackerExtension.js";
7
8
  import { CLEARED_LIST_RENDERING_ATTRS } from "../prosemirror/listMarker.js";
9
+ import { paragraphNumberingAttr, readParagraphNumberingAttr } from "../prosemirror/numberingAttr.js";
8
10
  import { directParagraphAlignment } from "../prosemirror/paragraphAlignment.js";
9
11
  import { directParagraphIndentation, paragraphIndentationAttrPatch, paragraphIndentationEqual, paragraphIndentationFromFormatting, withDirectParagraphIndentation } from "../prosemirror/paragraphIndentation.js";
10
12
  import { directParagraphSpacing, paragraphSpacingAttrPatch, paragraphSpacingEqual, paragraphSpacingFromFormatting, withDirectParagraphSpacing } from "../prosemirror/paragraphSpacing.js";
@@ -188,26 +190,25 @@ const paragraphPropertiesPatch = ({ node, properties, resolvedFormattingFromStyl
188
190
  ilvl: properties.numbering.level
189
191
  }, numbering));
190
192
  if (properties.listLevel === null) {
191
- patch["numPr"] = { numId: properties.numbering.numId };
193
+ patch["numPr"] = paragraphNumberingAttr(paragraphNumberingReference({ numId: properties.numbering.numId }));
192
194
  patch["numPrFromStyle"] = null;
193
195
  }
194
196
  }
195
- else if (properties.listLevel !== void 0) {
196
- const numPr = node.attrs["numPr"];
197
- if (properties.listLevel === null) {
198
- patch["numPr"] = null;
199
- Object.assign(patch, CLEARED_LIST_RENDERING_ATTRS);
200
- } else {
201
- const numId = typeof numPr === "object" && numPr !== null && "numId" in numPr ? numPr.numId : void 0;
202
- if (typeof numId === "number") Object.assign(patch, listLevelAttrPatch(attrs, {
203
- numId,
197
+ else if (properties.listLevel !== void 0) if (properties.listLevel === null) {
198
+ patch["numPr"] = null;
199
+ Object.assign(patch, CLEARED_LIST_RENDERING_ATTRS);
200
+ } else {
201
+ const numId = paragraphNumberingReferenceId(readParagraphNumberingAttr(node.attrs["numPr"]) ?? void 0);
202
+ if (numId === void 0) {
203
+ patch["numPr"] = paragraphNumberingAttr({
204
+ kind: "levelOnly",
204
205
  ilvl: properties.listLevel
205
- }, numbering));
206
- else {
207
- patch["numPr"] = { ilvl: properties.listLevel };
208
- Object.assign(patch, CLEARED_LIST_RENDERING_ATTRS);
209
- }
210
- }
206
+ });
207
+ Object.assign(patch, CLEARED_LIST_RENDERING_ATTRS);
208
+ } else Object.assign(patch, listLevelAttrPatch(attrs, {
209
+ numId,
210
+ ilvl: properties.listLevel
211
+ }, numbering));
211
212
  }
212
213
  if (properties.alignment !== void 0 && (styleChanged || (currentDirectAlignment ?? null) !== properties.alignment)) {
213
214
  originalFormatting ??= {};
@@ -1152,23 +1153,24 @@ const buildInsertedParagraphs = ({ item, schema, formattingFromStyle, mode, auth
1152
1153
  ilvl: explicitNumbering.level
1153
1154
  }, numbering));
1154
1155
  if (listLevel === null) {
1155
- attrs["numPr"] = { numId: explicitNumbering.numId };
1156
+ attrs["numPr"] = paragraphNumberingAttr(paragraphNumberingReference({ numId: explicitNumbering.numId }));
1156
1157
  attrs["numPrFromStyle"] = null;
1157
1158
  }
1158
1159
  } else if (listLevel === null) {
1159
1160
  attrs["numPr"] = null;
1160
1161
  Object.assign(attrs, CLEARED_LIST_RENDERING_ATTRS);
1161
1162
  } else if (typeof listLevel === "number") {
1162
- const anchorNumPr = Reflect.get(baseAttrs, "numPr");
1163
- const numId = typeof anchorNumPr === "object" && anchorNumPr !== null && "numId" in anchorNumPr ? anchorNumPr.numId : void 0;
1164
- if (typeof numId === "number") Object.assign(attrs, listLevelAttrPatch(operation.inheritFormatting === false ? {} : expectParagraphAttrs(item.blockNode), {
1163
+ const numId = paragraphNumberingReferenceId(readParagraphNumberingAttr(Reflect.get(baseAttrs, "numPr")) ?? void 0);
1164
+ if (numId === void 0) {
1165
+ attrs["numPr"] = paragraphNumberingAttr({
1166
+ kind: "levelOnly",
1167
+ ilvl: listLevel
1168
+ });
1169
+ Object.assign(attrs, CLEARED_LIST_RENDERING_ATTRS);
1170
+ } else Object.assign(attrs, listLevelAttrPatch(operation.inheritFormatting === false ? {} : expectParagraphAttrs(item.blockNode), {
1165
1171
  numId,
1166
1172
  ilvl: listLevel
1167
1173
  }, numbering));
1168
- else {
1169
- attrs["numPr"] = { ilvl: listLevel };
1170
- Object.assign(attrs, CLEARED_LIST_RENDERING_ATTRS);
1171
- }
1172
1174
  }
1173
1175
  }
1174
1176
  if (formatsParagraph && operation.styleId !== void 0) {
@@ -35,9 +35,9 @@ import { createFolioAIEditSnapshotWithStyleResolver, detachFolioAIEditSnapshotEx
35
35
  import { matchTableGeometry } from "./table-geometry.js";
36
36
  import { tableTemplateCanCrossPackageLosslessly } from "./table-template.js";
37
37
  import { TaggedError, panic } from "better-result";
38
+ import { REVIEW_CARRIERS } from "@stll/docx-core/model";
38
39
  import { Fragment } from "prosemirror-model";
39
40
  import { EditorState } from "prosemirror-state";
40
- import { REVIEW_CARRIERS } from "@stll/docx-core/model";
41
41
  import JSZip from "jszip";
42
42
  //#region src/ai-edits/headless.ts
43
43
  /**
@@ -25,6 +25,7 @@ declare const FOLIO_REVIEW_CHANGE_KINDS: Readonly<{
25
25
  readonly paragraphPropertiesChanged: "paragraphPropertiesChanged";
26
26
  readonly sectionPropertiesChanged: "sectionPropertiesChanged";
27
27
  readonly tablePropertiesChanged: "tablePropertiesChanged";
28
+ readonly tablePropertyExceptionsChanged: "tablePropertyExceptionsChanged";
28
29
  readonly rowPropertiesChanged: "rowPropertiesChanged";
29
30
  readonly cellPropertiesChanged: "cellPropertiesChanged";
30
31
  }>;
@@ -26,6 +26,7 @@ const FOLIO_REVIEW_CHANGE_KINDS = Object.freeze({
26
26
  paragraphPropertiesChanged: "paragraphPropertiesChanged",
27
27
  sectionPropertiesChanged: "sectionPropertiesChanged",
28
28
  tablePropertiesChanged: "tablePropertiesChanged",
29
+ tablePropertyExceptionsChanged: "tablePropertyExceptionsChanged",
29
30
  rowPropertiesChanged: "rowPropertiesChanged",
30
31
  cellPropertiesChanged: "cellPropertiesChanged"
31
32
  });
@@ -1,7 +1,10 @@
1
1
  import { EMPTY_BUILT_IN_STYLE_INDEX, resolveHeadingLevel } from "../docx/builtInStyles.js";
2
+ import { resolveParagraphNumbering } from "../docx/numberingReference.js";
2
3
  import { recreateProseNodeWithParagraphPropertySource } from "../docx/paragraphPropertySource.js";
3
4
  import { expectCharacterStyleMarkAttrs, expectHyperlinkMarkAttrs, expectParagraphAttrs, expectRunFormattingOverrideMarkAttrs } from "../prosemirror/attrs/index.js";
4
5
  import { marksToTextFormatting } from "../prosemirror/conversion/fromProseDoc.js";
6
+ import { paragraphNumberingAttr, readParagraphNumberingAttr } from "../prosemirror/numberingAttr.js";
7
+ import { readOutlineLevelAttr } from "../prosemirror/outlineLevelAttr.js";
5
8
  import { directParagraphAlignment } from "../prosemirror/paragraphAlignment.js";
6
9
  import { directParagraphIndentation } from "../prosemirror/paragraphIndentation.js";
7
10
  import { directParagraphSpacing } from "../prosemirror/paragraphSpacing.js";
@@ -34,18 +37,16 @@ const remapFolioAIEditSnapshotNumberingReferences = (snapshot, numIdMap) => {
34
37
  if (numIdMap.size === 0) return snapshot;
35
38
  const metadata = metadataOf(snapshot);
36
39
  const remapNode = (node) => {
37
- const numPr = node.attrs["numPr"];
38
- if (typeof numPr !== "object" || numPr === null || !("numId" in numPr)) return node;
39
- const numId = numPr.numId;
40
- if (typeof numId !== "number") return node;
41
- const remappedNumId = numIdMap.get(numId);
40
+ const numPr = readParagraphNumberingAttr(node.attrs["numPr"]);
41
+ if (numPr?.kind !== "reference") return node;
42
+ const remappedNumId = numIdMap.get(numPr.numId);
42
43
  if (remappedNumId === void 0) return node;
43
44
  return recreateProseNodeWithParagraphPropertySource(node, { attrs: {
44
45
  ...node.attrs,
45
- numPr: {
46
+ numPr: paragraphNumberingAttr({
46
47
  ...numPr,
47
48
  numId: remappedNumId
48
- }
49
+ })
49
50
  } });
50
51
  };
51
52
  const remapped = remapDocument(metadata.sourceDocument, remapNode);
@@ -481,10 +482,9 @@ const getBlockKind = (node, headingLevel) => {
481
482
  };
482
483
  /** The block's 1-based heading level, as {@link resolveHeadingLevel} classifies it. */
483
484
  const getHeadingLevel = (node, styles) => {
484
- const outlineLevel = node.attrs["outlineLevel"];
485
485
  const styleId = node.attrs["styleId"];
486
486
  const level = resolveHeadingLevel({
487
- outlineLevel: typeof outlineLevel === "number" ? outlineLevel : null,
487
+ outlineLevel: readOutlineLevelAttr(node.attrs["outlineLevel"]),
488
488
  styleId: typeof styleId === "string" ? styleId : null
489
489
  }, styles);
490
490
  return level === void 0 ? void 0 : level + 1;
@@ -495,30 +495,35 @@ const getDisplayLabel = (node, isHeading) => {
495
495
  const styleId = node.attrs["styleId"];
496
496
  if (isHeading && typeof styleId === "string") return styleId;
497
497
  };
498
+ /**
499
+ * The level the paragraph's `<w:numPr>` states, and only that. An absent
500
+ * `w:ilvl` renders as level zero but is not a stated zero, and a caller that
501
+ * writes it back would turn an untouched paragraph into one stating a level
502
+ * its source never did.
503
+ */
498
504
  const getListLevel = (node) => {
499
- const numPr = node.attrs["numPr"];
500
- if (typeof numPr !== "object" || numPr === null || !("ilvl" in numPr)) return;
501
- const { ilvl } = numPr;
502
- return typeof ilvl === "number" && Number.isInteger(ilvl) && ilvl >= 0 ? ilvl : void 0;
505
+ const numPr = readParagraphNumberingAttr(node.attrs["numPr"]);
506
+ return numPr === null || numPr.kind === "none" ? void 0 : numPr.ilvl;
503
507
  };
508
+ /**
509
+ * The numbering a paragraph attr states, read through the model's own reader.
510
+ *
511
+ * The two functions below used to test the reserved id relationally
512
+ * (`numId > 0`, `numId <= 0`), which is the one spelling that disagreed with
513
+ * the other four: a malformed package's negative id is a dangling reference
514
+ * everywhere else and "not numbered" here.
515
+ */
516
+ const statedNumbering = (node) => resolveParagraphNumbering(readParagraphNumberingAttr(node.attrs["numPr"]) ?? void 0);
504
517
  const getListReference = (node) => {
505
- const numPr = node.attrs["numPr"];
506
- if (typeof numPr !== "object" || numPr === null || !("numId" in numPr)) return void 0;
507
- const { numId } = numPr;
508
- const level = "ilvl" in numPr ? numPr.ilvl : 0;
509
- return typeof numId === "number" && Number.isInteger(numId) && numId > 0 && typeof level === "number" && Number.isInteger(level) && level >= 0 ? {
510
- numId,
511
- level
518
+ const numbering = statedNumbering(node);
519
+ return numbering.kind === "reference" ? {
520
+ numId: numbering.numId,
521
+ level: numbering.ilvl
512
522
  } : void 0;
513
523
  };
514
524
  const getNumberingReferenceKey = (node) => {
515
- const numPr = node.attrs["numPr"];
516
- if (typeof numPr !== "object" || numPr === null || !("numId" in numPr)) return null;
517
- const { numId } = numPr;
518
- if (typeof numId !== "number" || !Number.isInteger(numId) || numId <= 0) return null;
519
- const level = "ilvl" in numPr ? numPr.ilvl : void 0;
520
- if (level !== void 0 && (typeof level !== "number" || !Number.isInteger(level) || level < 0)) return null;
521
- return `${String(numId)}:${String(level ?? 0)}`;
525
+ const numbering = statedNumbering(node);
526
+ return numbering.kind === "reference" ? `${String(numbering.numId)}:${String(numbering.ilvl)}` : null;
522
527
  };
523
528
  const getStyleId = (node) => {
524
529
  const styleId = node.attrs["styleId"];
@@ -51,7 +51,11 @@ const mergeTableRectangle = ({ tr, tablePosition, table, rectangle }) => {
51
51
  rowspan: rectangle.bottom - rectangle.top,
52
52
  colwidth: nextColwidth,
53
53
  width: preferredWidth.type === "value" ? preferredWidth.width : null,
54
- widthType: preferredWidth.type === "value" ? preferredWidth.widthType : null
54
+ widthType: preferredWidth.type === "value" ? preferredWidth.widthType : null,
55
+ _authoredWidth: preferredWidth.type === "value" ? {
56
+ value: preferredWidth.width,
57
+ type: preferredWidth.widthType
58
+ } : null
55
59
  });
56
60
  if (appendedContent.size > 0) {
57
61
  const contentEnd = absoluteMergedPosition + 1 + merged.cell.content.size;
@@ -74,16 +78,20 @@ const mergeTopRowColwidths = (cells, mergedColspan) => {
74
78
  * preferred widths; retaining only the first cell's width makes a 50%+50%
75
79
  * bilingual row serialize as a 50%-wide spanning cell. Mixed/implicit units
76
80
  * cannot be composed safely, so clear the preference and let the table grid
77
- * define the merged width. */
81
+ * define the merged width.
82
+ *
83
+ * The summands are `_authoredWidth`, not the rendered `width`: a cell that
84
+ * states no preferred width still renders at the width the table grid
85
+ * resolved, and summing those would give the merged cell a `w:tcW` no source
86
+ * cell wrote. */
78
87
  const mergeTopRowPreferredWidths = (cells) => {
79
88
  let width = 0;
80
89
  let widthType;
81
90
  for (const cell of cells) {
82
- const candidateWidth = cell.attrs["width"];
83
- const candidateType = cell.attrs["widthType"];
84
- if (typeof candidateWidth !== "number" || !Number.isFinite(candidateWidth) || candidateType !== "dxa" && candidateType !== "pct" || widthType !== void 0 && candidateType !== widthType) return { type: "absent" };
85
- width += candidateWidth;
86
- widthType = candidateType;
91
+ const stated = expectTableCellAttrs(cell)._authoredWidth;
92
+ if (stated === void 0 || !Number.isFinite(stated.value) || stated.type !== "dxa" && stated.type !== "pct" || widthType !== void 0 && stated.type !== widthType) return { type: "absent" };
93
+ width += stated.value;
94
+ widthType = stated.type;
87
95
  }
88
96
  return widthType === void 0 ? { type: "absent" } : {
89
97
  type: "value",
@@ -80,21 +80,24 @@ const TABLE_SCOPE = {
80
80
  changeAttr: "tblPrChange",
81
81
  changeType: "tablePropertyChange"
82
82
  };
83
- const ROW_SCOPE = {
84
- keys: ROW_SCOPED_ATTRS,
85
- signatureOf: (node) => scopedValues(node.attrs, ROW_SCOPED_ATTRS),
86
- formattingOf: (node) => tableRowAttrsToFormatting(node.attrs),
87
- rejectPatch: (previousFormatting) => tableRowRejectAttrPatch(previousFormatting),
88
- changeAttr: "trPrChange",
89
- changeType: "tableRowPropertyChange"
90
- };
91
- const CELL_SCOPE = {
92
- keys: CELL_SCOPED_ATTRS,
93
- signatureOf: (node) => scopedValues(node.attrs, CELL_SCOPED_ATTRS),
94
- formattingOf: (node) => tableCellAttrsToFormatting(cellAttrsOf(node)),
95
- rejectPatch: (previousFormatting, liveFormatting) => tableCellRejectAttrPatch(previousFormatting, liveFormatting),
96
- changeAttr: "tcPrChange",
97
- changeType: "tableCellPropertyChange"
83
+ const GEOMETRY_SCOPES = {
84
+ tablePropertyChange: TABLE_SCOPE,
85
+ tableRowPropertyChange: {
86
+ keys: ROW_SCOPED_ATTRS,
87
+ signatureOf: (node) => scopedValues(node.attrs, ROW_SCOPED_ATTRS),
88
+ formattingOf: (node) => tableRowAttrsToFormatting(node.attrs),
89
+ rejectPatch: (previousFormatting) => tableRowRejectAttrPatch(previousFormatting),
90
+ changeAttr: "trPrChange",
91
+ changeType: "tableRowPropertyChange"
92
+ },
93
+ tableCellPropertyChange: {
94
+ keys: CELL_SCOPED_ATTRS,
95
+ signatureOf: (node) => scopedValues(node.attrs, CELL_SCOPED_ATTRS),
96
+ formattingOf: (node) => tableCellAttrsToFormatting(cellAttrsOf(node)),
97
+ rejectPatch: (previousFormatting, liveFormatting) => tableCellRejectAttrPatch(previousFormatting, liveFormatting),
98
+ changeAttr: "tcPrChange",
99
+ changeType: "tableCellPropertyChange"
100
+ }
98
101
  };
99
102
  const scopedValues = (attrs, keys) => canonicalJson(scopedAttrs(attrs, keys));
100
103
  /**
@@ -200,9 +203,9 @@ const matchTableGeometry = ({ tr, baseTables, targetTables, pairings, revision }
200
203
  const targetCell = targetRow.maybeChild(target.cellIndex);
201
204
  const cellPosition = childPositions(baseRow, rowPosition)[base.cellIndex];
202
205
  if (!baseCell || !targetCell || cellPosition === void 0) continue;
203
- consider(baseTable.node, targetTable, baseTable.start, TABLE_SCOPE);
204
- consider(baseRow, targetRow, rowPosition, ROW_SCOPE);
205
- consider(baseCell, targetCell, cellPosition, CELL_SCOPE);
206
+ consider(baseTable.node, targetTable, baseTable.start, GEOMETRY_SCOPES.tablePropertyChange);
207
+ consider(baseRow, targetRow, rowPosition, GEOMETRY_SCOPES.tableRowPropertyChange);
208
+ consider(baseCell, targetCell, cellPosition, GEOMETRY_SCOPES.tableCellPropertyChange);
206
209
  }
207
210
  let revisionId = revision.idSeed;
208
211
  for (const target of targets) {
@@ -70,7 +70,6 @@ const CLEARED_PARAGRAPH_ATTRS = [
70
70
  "pPrMark",
71
71
  "_suggestedInsert",
72
72
  "_sectionProperties",
73
- "sectionBreakType",
74
73
  "renderedPageBreakBefore"
75
74
  ];
76
75
  /** Table, row and cell attrs that record the other document's revisions. */
@@ -78,7 +77,8 @@ const CLEARED_TABLE_ATTRS = ["tblPrChange", "_suggestedInsert"];
78
77
  const CLEARED_ROW_ATTRS = [
79
78
  "trIns",
80
79
  "trDel",
81
- "trPrChange"
80
+ "trPrChange",
81
+ "tblPrExChange"
82
82
  ];
83
83
  const CLEARED_CELL_ATTRS = ["cellMarker", "tcPrChange"];
84
84
  const hasAuthoredValue = (value) => {
@@ -1,3 +1,4 @@
1
+ import { alignParagraphOrdinals } from "../docx/paraIdAttribute.js";
1
2
  import { alignTableColumns } from "./column-alignment.js";
2
3
  import { panic } from "better-result";
3
4
  //#region src/compare/content-alignment.ts
@@ -273,6 +274,44 @@ const pairsInAnchorGaps = ({ baseLength, revisedLength, anchors, pairGap }) => {
273
274
  }
274
275
  return pairs;
275
276
  };
277
+ /**
278
+ * Blocks the anchor passes left unpaired whose exact text stands, also
279
+ * unpaired, on the other side.
280
+ *
281
+ * Anchoring is monotone, so content that moved past other content leaves one
282
+ * of its two correspondences unanchored by construction: two paragraphs that
283
+ * swap places produce two exact candidates that cross, and only one survives
284
+ * the increasing subsequence. What is left over is both ends of that crossing.
285
+ * It is not a paragraph rewritten into another, so the positional fallback
286
+ * must not fuse them: a relocation would come back as a replacement neither
287
+ * document contains, and the move pass would never see the removal and the
288
+ * arrival it is there to pair.
289
+ */
290
+ const crossedExactTextBlocks = ({ base, revised, anchors, canPair }) => {
291
+ const uniqueUnanchoredByText = (blocks, anchored) => {
292
+ const blocksByText = /* @__PURE__ */ new Map();
293
+ for (const block of blocks) {
294
+ if (anchored.has(block.index) || !NON_WHITESPACE.test(block.block.text)) continue;
295
+ const { text } = block.block;
296
+ blocksByText.set(text, blocksByText.has(text) ? null : block);
297
+ }
298
+ return blocksByText;
299
+ };
300
+ const baseByText = uniqueUnanchoredByText(base, new Set(anchors.map(({ baseIndex }) => baseIndex)));
301
+ const revisedByText = uniqueUnanchoredByText(revised, new Set(anchors.map(({ revisedIndex }) => revisedIndex)));
302
+ const crossedBase = /* @__PURE__ */ new Set();
303
+ const crossedRevised = /* @__PURE__ */ new Set();
304
+ for (const [text, baseBlock] of baseByText) {
305
+ const revisedBlock = revisedByText.get(text);
306
+ if (!baseBlock || !revisedBlock || !canPair(baseBlock, revisedBlock)) continue;
307
+ crossedBase.add(baseBlock.index);
308
+ crossedRevised.add(revisedBlock.index);
309
+ }
310
+ return {
311
+ base: crossedBase,
312
+ revised: crossedRevised
313
+ };
314
+ };
276
315
  const alignFolioContentBlocksInScope = (baseBlocks, revisedBlocks, options) => {
277
316
  const stableIdMismatch = options.stableIdMismatch ?? "separate";
278
317
  const idStability = options.idStability ?? folioContentIdStability;
@@ -322,13 +361,19 @@ const alignFolioContentBlocksInScope = (baseBlocks, revisedBlocks, options) => {
322
361
  })
323
362
  });
324
363
  const anchors = [...exactAndStableAnchors, ...continuityAnchors].toSorted((left, right) => left.baseIndex - right.baseIndex || left.revisedIndex - right.revisedIndex);
364
+ const crossed = crossedExactTextBlocks({
365
+ base: prepared.base,
366
+ revised: prepared.revised,
367
+ anchors,
368
+ canPair
369
+ });
325
370
  const events = [];
326
371
  const emitPositionalGap = (baseFrom, baseTo, revisedFrom, revisedTo) => {
327
372
  const pairedCount = Math.min(baseTo - baseFrom, revisedTo - revisedFrom);
328
373
  for (let offset = 0; offset < pairedCount; offset++) {
329
374
  const baseBlock = prepared.base[baseFrom + offset];
330
375
  const revisedBlock = prepared.revised[revisedFrom + offset];
331
- if (baseBlock && revisedBlock) if (!canPair(baseBlock, revisedBlock)) {
376
+ if (baseBlock && revisedBlock) if (baseBlock.block.text !== revisedBlock.block.text && crossed.base.has(baseBlock.index) && crossed.revised.has(revisedBlock.index) || !canPair(baseBlock, revisedBlock)) {
332
377
  events.push({
333
378
  type: "baseOnly",
334
379
  block: baseBlock.block
@@ -644,15 +689,64 @@ const stableContentSequencePairs = (base, revised) => {
644
689
  }
645
690
  return pairs;
646
691
  };
647
- const contentContainerIdentityTransition = (base, revised) => {
648
- if (base === null || revised === null || base.status !== "available" || revised.status !== "available" || base.blockIds.length === 0 || base.blockIds.length !== revised.blockIds.length) return false;
649
- let hasStabilityTransition = false;
650
- for (let index = 0; index < base.blockIds.length; index++) {
651
- if (base.blockIds[index] !== revised.blockIds[index]) return false;
652
- hasStabilityTransition ||= base.idStabilities[index] !== revised.idStabilities[index];
653
- }
654
- return hasStabilityTransition;
692
+ /**
693
+ * A container's blocks as the paragraph identities the save reasons about: a
694
+ * stable id is one the package wrote, a positional id one folio minted for a
695
+ * paragraph that arrived without one.
696
+ */
697
+ const containerParagraphIdentities = (profile) => profile.blockIds.map((paraId, ordinal) => profile.idStabilities[ordinal] === "stable" ? {
698
+ type: "authored",
699
+ paraId,
700
+ ordinal
701
+ } : {
702
+ type: "minted",
703
+ paraId,
704
+ ordinal
705
+ });
706
+ /**
707
+ * Whether two containers are the same container, read from the paragraph ids
708
+ * their blocks carry.
709
+ *
710
+ * This used to ask for a positional-to-stable *transition* with identical ids
711
+ * at every index, which is the shape a save produced when it stamped folio's
712
+ * minted ids into the package it wrote. That made the comparison depend on a
713
+ * side effect of the save rather than on the documents in front of it: once a
714
+ * save stopped persisting a minted id, both sides read positional, the
715
+ * transition never fired, and an edited row was reported deleted and inserted
716
+ * instead of edited.
717
+ *
718
+ * The question is the one {@link alignParagraphOrdinals} answers, and it is
719
+ * asked through the owner the save asks it through, so the two cannot come to
720
+ * disagree about which paragraph is which. A comparison sees two different
721
+ * documents, so absence of contradiction is not enough on its own: most of the
722
+ * container has to actively confirm the ordinals, or every container of equal
723
+ * size would pair with every other on the strength of saying nothing. A
724
+ * positional id is derived from the paragraph's own text and position, so an
725
+ * unedited block keeps it across the edit and supplies that confirmation, while
726
+ * an edited block's id changes with its text. A majority is therefore "the
727
+ * blocks this edit did not touch", and it is what separates a row with an edit
728
+ * in it from a row replaced by a different row, which shares no id at all.
729
+ *
730
+ * This signal only has to carry the containers similarity cannot reach: a pair
731
+ * it declines is still weighed on content, so a two-block container with one
732
+ * block edited pairs on the half it kept rather than on a bare majority.
733
+ */
734
+ const contentContainersShareIdentity = (base, revised) => {
735
+ if (base === null || revised === null || base.status !== "available" || revised.status !== "available" || base.blockIds.length === 0) return false;
736
+ const alignment = alignParagraphOrdinals(containerParagraphIdentities(base), containerParagraphIdentities(revised));
737
+ return alignment.consistent && alignment.sharedOrdinals * 2 > base.blockIds.length;
655
738
  };
739
+ /**
740
+ * Whether two containers carry the same block ids in the same order, over
741
+ * their whole length.
742
+ *
743
+ * Stricter than {@link contentContainersShareIdentity}, which answers which
744
+ * container this is while blocks come and go. This answers whether there is
745
+ * anything left to decide: nothing moved within either container, so paired
746
+ * with equal content they are one container seen twice. An identity a cap
747
+ * withheld is unknown, never equal.
748
+ */
749
+ const contentContainerIdsAreEqual = (base, revised) => base !== null && revised !== null && base.status === "available" && revised.status === "available" && base.blockIds.length > 0 && base.blockIds.length === revised.blockIds.length && base.blockIds.every((id, index) => id === revised.blockIds[index]);
656
750
  const uniqueExactContentSequencePairs = ({ baseKeys, revisedKeys }) => {
657
751
  const uniqueIndexes = (keys) => {
658
752
  const indexes = /* @__PURE__ */ new Map();
@@ -723,7 +817,7 @@ const persistedContentSequencePairs = ({ base, revised, anchors, canPair }) => {
723
817
  baseIndex,
724
818
  revisedIndex
725
819
  };
726
- if (revisedItem && canPair(baseItem, revisedItem) && contentContainerIdentityTransition(baseItem.profile.containerIdentity, revisedItem.profile.containerIdentity) && pairIsCompatibleWithAnchors(pair, anchors)) candidates.push(pair);
820
+ if (revisedItem && canPair(baseItem, revisedItem) && contentContainersShareIdentity(baseItem.profile.containerIdentity, revisedItem.profile.containerIdentity) && pairIsCompatibleWithAnchors(pair, anchors)) candidates.push(pair);
727
821
  }
728
822
  return new Set(monotoneContentSequencePairs(candidates).map(({ baseIndex, revisedIndex }) => baseIndex * revised.length + revisedIndex));
729
823
  };
@@ -742,7 +836,7 @@ const alignProfiledContentSequence = ({ base, revised, workSession, canPair = ()
742
836
  const revisedProfile = revised[index]?.profile;
743
837
  if (!baseProfile || !revisedProfile) continue;
744
838
  const hasContainerIdentity = baseProfile.containerIdentity !== null || revisedProfile.containerIdentity !== null;
745
- let hasProvenanceTransition = contentContainerIdentityTransition(baseProfile.containerIdentity, revisedProfile.containerIdentity);
839
+ let hasProvenanceTransition = contentContainersShareIdentity(baseProfile.containerIdentity, revisedProfile.containerIdentity);
746
840
  if (!hasContainerIdentity) {
747
841
  const revisedIds = new Set(revisedProfile.blockIds);
748
842
  const baseStableIds = new Set(baseProfile.stableIds);
@@ -861,6 +955,7 @@ const alignProfiledContentSequence = ({ base, revised, workSession, canPair = ()
861
955
  let revisedIndex = 0;
862
956
  let pairCount = 0;
863
957
  let solePairIsShifted = false;
958
+ let solePairIsIdentity = false;
864
959
  let hasBaseOnly = false;
865
960
  let hasRevisedOnly = false;
866
961
  while (baseIndex < base.length && revisedIndex < revised.length) {
@@ -875,6 +970,7 @@ const alignProfiledContentSequence = ({ base, revised, workSession, canPair = ()
875
970
  });
876
971
  pairCount += 1;
877
972
  solePairIsShifted = baseIndex !== revisedIndex;
973
+ solePairIsIdentity = baseExactSignatureKeys[baseIndex] === revisedExactSignatureKeys[revisedIndex] && contentContainerIdsAreEqual(base[baseIndex]?.profile.containerIdentity ?? null, revised[revisedIndex]?.profile.containerIdentity ?? null);
878
974
  baseIndex += 1;
879
975
  revisedIndex += 1;
880
976
  } else if (direction === ALIGNMENT_DIRECTION.revisedOnly && revisedItem !== void 0) {
@@ -907,7 +1003,7 @@ const alignProfiledContentSequence = ({ base, revised, workSession, canPair = ()
907
1003
  });
908
1004
  hasRevisedOnly = true;
909
1005
  }
910
- if ((soleShiftedPairResiduePolicy === "conservative" || base.length === revised.length) && pairCount === 1 && solePairIsShifted && hasBaseOnly && hasRevisedOnly) return aligned.flatMap((entry) => entry.type === "pair" ? [{
1006
+ if (!solePairIsIdentity && (soleShiftedPairResiduePolicy === "conservative" || base.length === revised.length) && pairCount === 1 && solePairIsShifted && hasBaseOnly && hasRevisedOnly) return aligned.flatMap((entry) => entry.type === "pair" ? [{
911
1007
  type: "baseOnly",
912
1008
  item: entry.base
913
1009
  }, {
@@ -1,3 +1,4 @@
1
+ import { document_d_exports } from "../types/document.js";
1
2
  //#region src/compare/content-types.d.ts
2
3
  /** How callers expect a block identifier to behave across document revisions. */
3
4
  type FolioContentIdStability = "stable" | "positional";
@@ -74,8 +75,13 @@ type FolioContentTableLocation = {
74
75
  rowSpan: number;
75
76
  paragraphIndex: number;
76
77
  };
77
- /** Direct paragraph alignment understood by the neutral comparison model. */
78
- type FolioContentParagraphAlignment = "left" | "center" | "right" | "both" | "distribute" | "mediumKashida" | "highKashida" | "lowKashida" | "thaiDistribute";
78
+ /**
79
+ * Direct paragraph alignment understood by the neutral comparison model.
80
+ *
81
+ * The model's own `ST_Jc` union: a copy spelled here would refuse an alignment
82
+ * a parsed document carries.
83
+ */
84
+ type FolioContentParagraphAlignment = document_d_exports.ParagraphAlignment;
79
85
  /** Line-height interpretation understood by the neutral comparison model. */
80
86
  type FolioContentLineSpacingRule = "auto" | "exact" | "atLeast";
81
87
  /** The complete modeled attribute set of direct paragraph indentation. */
@@ -1,5 +1,6 @@
1
1
  import { WORD_DIFF_GRANULARITIES, createWordDiffSession } from "../ai-edits/word-diff.js";
2
2
  import { paragraphIndentationEqual } from "../prosemirror/paragraphIndentation.js";
3
+ import { PARAGRAPH_ALIGNMENT_VALUES } from "../types/documentEnumValues.js";
3
4
  import { alignFolioContentStructure, contentBlocksShareContainer, createFolioContentAlignmentWorkSession } from "./content-alignment.js";
4
5
  import { inlineFormattingSegments } from "./formatting.js";
5
6
  import { Result, TaggedError, panic } from "better-result";
@@ -67,17 +68,7 @@ const isFiniteInteger = (value) => typeof value === "number" && Number.isSafeInt
67
68
  const isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
68
69
  const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
69
70
  const hasRecordShape = (value) => isRecord(value);
70
- const PARAGRAPH_ALIGNMENTS = /* @__PURE__ */ new Set([
71
- "left",
72
- "center",
73
- "right",
74
- "both",
75
- "distribute",
76
- "mediumKashida",
77
- "highKashida",
78
- "lowKashida",
79
- "thaiDistribute"
80
- ]);
71
+ const PARAGRAPH_ALIGNMENTS = new Set(PARAGRAPH_ALIGNMENT_VALUES);
81
72
  const validateRunFormatting = (block, side, blockIndex) => {
82
73
  for (const [runIndex, run] of (block.previewRuns ?? []).entries()) {
83
74
  if (run.directFormatting !== void 0 && !isRecord(run.directFormatting)) return invalidInput(side, `blocks[${String(blockIndex)}].previewRuns[${String(runIndex)}].directFormatting`, "Direct inline formatting must be an object.", blockIndex);
@@ -178,16 +178,19 @@ const terminalCarrierIsStranded = (steps, baseBlocks) => {
178
178
  * back over the next paragraph. The applier rotates instead — the paragraph
179
179
  * the run was appended after takes the inserted mark, and the last one takes
180
180
  * the free mark — and that rotation reaches only across paragraphs. A table
181
- * among them stops it, and the words the target ends with have to be written
182
- * into the base's own last paragraph instead.
181
+ * among them stops it, and so does removing the paragraph the rotation turns
182
+ * on: a run appended after a paragraph that is itself deleted has no mark to
183
+ * take. Either way the words the target ends with have to be written into the
184
+ * base's own last paragraph instead.
183
185
  */
184
186
  const addedTerminalCarrierIsStranded = (steps, baseBlocks, targetBlocks) => {
185
187
  const baseLast = baseBlocks.at(-1);
186
188
  const targetLast = targetBlocks.at(-1);
187
189
  if (baseLast === void 0 || targetLast === void 0) return false;
188
190
  if (!steps.some((step) => step.type === "targetOnly" && step.block.id === targetLast.id)) return false;
189
- const baseLastStep = steps.findIndex((step) => step.type === "pair" && step.baseBlock.id === baseLast.id || step.type === "baseOnly" && step.block.id === baseLast.id);
190
- return baseLastStep === -1 || steps.slice(baseLastStep + 1).some((step) => step.type !== "targetOnly");
191
+ const baseLastStepIndex = steps.findIndex((step) => step.type === "pair" && step.baseBlock.id === baseLast.id || step.type === "baseOnly" && step.block.id === baseLast.id);
192
+ const baseLastStep = steps[baseLastStepIndex];
193
+ return baseLastStep === void 0 || baseLastStep.type === "baseOnly" || steps.slice(baseLastStepIndex + 1).some((step) => step.type !== "targetOnly");
191
194
  };
192
195
  const buildSteps = ({ baseSnapshot, targetSnapshot, wholeTableReplacement, workSession }) => {
193
196
  const baseBlocks = baseSnapshot.blocks;
@@ -220,8 +220,7 @@ const stageSectionBoundaryProperties = ({ state, target, originalRevisionIdSeed,
220
220
  _sectionProperties: {
221
221
  ...update.target,
222
222
  ...propertyChanges === void 0 ? {} : { propertyChanges }
223
- },
224
- sectionBreakType: update.target.sectionStart ?? null
223
+ }
225
224
  });
226
225
  }
227
226
  return {
@@ -5,7 +5,13 @@ type CheckboxDisplayContent = Extract<document_d_exports.RunContent, {
5
5
  } | {
6
6
  type: "text";
7
7
  }>;
8
- /** Resolve the authored checkbox state into the run payload Word expects. */
9
- declare const checkboxDisplayContent: (rawPropertiesXml: string | undefined, checked: boolean) => CheckboxDisplayContent;
8
+ /**
9
+ * Resolve the authored checkbox state into the run payload Word expects.
10
+ *
11
+ * @param checkboxXml the preserved `w14:checkbox` element, from
12
+ * `SdtProperties.preserved`. A control that carries none — one built in
13
+ * code, or one whose author wrote no glyphs — gets Word's own defaults.
14
+ */
15
+ declare const checkboxDisplayContent: (checkboxXml: string | undefined, checked: boolean) => CheckboxDisplayContent;
10
16
  //#endregion
11
17
  export { checkboxDisplayContent };