@stll/folio-core 0.46.0 → 0.47.1

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 (370) hide show
  1. package/dist/ai-edits/apply.d.ts +17 -1
  2. package/dist/ai-edits/apply.js +31 -27
  3. package/dist/ai-edits/headless.d.ts +9 -2
  4. package/dist/ai-edits/headless.js +5 -3
  5. package/dist/ai-edits/read.d.ts +1 -0
  6. package/dist/ai-edits/read.js +1 -0
  7. package/dist/ai-edits/snapshot.js +32 -27
  8. package/dist/ai-edits/table-cell-mutations.js +15 -7
  9. package/dist/ai-edits/table-geometry.js +21 -18
  10. package/dist/ai-edits/table-template.js +2 -2
  11. package/dist/compare/compare.js +2 -1
  12. package/dist/compare/content-alignment.js +192 -46
  13. package/dist/compare/content-types.d.ts +8 -2
  14. package/dist/compare/content.js +2 -11
  15. package/dist/compare/plan.js +7 -4
  16. package/dist/compare/section-boundary-properties.js +1 -2
  17. package/dist/content-controls/checkboxDisplay.d.ts +8 -2
  18. package/dist/content-controls/checkboxDisplay.js +11 -5
  19. package/dist/content-controls/mutateContentControls.js +41 -42
  20. package/dist/controller/layoutPipeline.js +8 -3
  21. package/dist/display-list/build/buildDisplayList.js +7 -7
  22. package/dist/display-list/build/imagePrimitives.d.ts +4 -4
  23. package/dist/display-list/build/imagePrimitives.js +38 -20
  24. package/dist/display-list/build/pageBorderPrimitives.js +2 -1
  25. package/dist/display-list/build/paragraphPrimitives.js +93 -13
  26. package/dist/display-list/build/previewPrimitives.d.ts +10 -0
  27. package/dist/display-list/build/previewPrimitives.js +89 -0
  28. package/dist/display-list/build/strokes.d.ts +177 -8
  29. package/dist/display-list/build/strokes.js +167 -47
  30. package/dist/display-list/build/tablePrimitives.js +4 -2
  31. package/dist/display-list/build/textBoxPrimitives.js +6 -4
  32. package/dist/display-list/build/textDecorations.d.ts +15 -1
  33. package/dist/display-list/build/textDecorations.js +15 -1
  34. package/dist/display-list/dom/renderDisplayListToDom.js +1 -19
  35. package/dist/display-list/primitives.d.ts +13 -2
  36. package/dist/display-list/primitives.js +36 -1
  37. package/dist/document-operations.d.ts +9 -2
  38. package/dist/document-operations.js +5 -3
  39. package/dist/docx/attributeRemainder.d.ts +34 -1
  40. package/dist/docx/attributeRemainder.js +49 -3
  41. package/dist/docx/blockContentParser.d.ts +2 -0
  42. package/dist/docx/blockContentParser.js +39 -67
  43. package/dist/docx/blockPlainText.js +3 -1
  44. package/dist/docx/borderParser.js +26 -11
  45. package/dist/docx/builtInStyles.d.ts +8 -16
  46. package/dist/docx/builtInStyles.js +54 -17
  47. package/dist/docx/commentAnchorIndex.js +1 -1
  48. package/dist/docx/commentParser.js +3 -3
  49. package/dist/docx/commentRangeIntegrity.js +1 -1
  50. package/dist/docx/commentRangeJoin.js +1 -1
  51. package/dist/docx/commentReferenceNormalization.js +3 -2
  52. package/dist/docx/commentReplyMarkers.js +1 -1
  53. package/dist/docx/compatibility.js +56 -42
  54. package/dist/docx/containerChildren.d.ts +110 -13
  55. package/dist/docx/containerChildren.gen.d.ts +16 -1
  56. package/dist/docx/containerChildren.gen.js +18 -1
  57. package/dist/docx/containerChildren.js +63 -13
  58. package/dist/docx/diagramPreview.d.ts +14 -2
  59. package/dist/docx/diagramPreview.js +81 -169
  60. package/dist/docx/documentParser.js +4 -1
  61. package/dist/docx/drawingAnchor.d.ts +87 -0
  62. package/dist/docx/drawingAnchor.js +201 -0
  63. package/dist/docx/drawingUtils.d.ts +43 -38
  64. package/dist/docx/drawingUtils.js +205 -118
  65. package/dist/docx/fontTableParser.js +102 -41
  66. package/dist/docx/footnoteParser.js +10 -6
  67. package/dist/docx/groupDrawingParser.js +4 -3
  68. package/dist/docx/headerFooterReferenceNormalization.js +1 -1
  69. package/dist/docx/hyperlinkParser.d.ts +45 -7
  70. package/dist/docx/hyperlinkParser.js +126 -57
  71. package/dist/docx/imageParser.js +127 -107
  72. package/dist/docx/index.d.ts +2 -1
  73. package/dist/docx/index.js +2 -1
  74. package/dist/docx/inlineContentRemovals.d.ts +28 -0
  75. package/dist/docx/inlineContentRemovals.js +46 -0
  76. package/dist/docx/inlineWrapperContent.d.ts +84 -3
  77. package/dist/docx/inlineWrapperContent.js +85 -4
  78. package/dist/docx/inlineWrapperParser.d.ts +11 -0
  79. package/dist/docx/inlineWrapperParser.js +60 -0
  80. package/dist/docx/nonVisualDrawingProps.d.ts +5 -13
  81. package/dist/docx/normalizeBaseDirection.js +4 -2
  82. package/dist/docx/numberingParser.d.ts +25 -2
  83. package/dist/docx/numberingParser.js +264 -361
  84. package/dist/docx/numberingReference.d.ts +9 -16
  85. package/dist/docx/numberingReference.js +17 -16
  86. package/dist/docx/numberingReferenceNormalization.js +7 -7
  87. package/dist/docx/ooxmlCounterFormatter.d.ts +1 -1
  88. package/dist/docx/ooxmlCounterFormatter.js +4 -1
  89. package/dist/docx/paraIdAttribute.d.ts +91 -1
  90. package/dist/docx/paraIdAttribute.js +79 -1
  91. package/dist/docx/paragraphParser.d.ts +9 -24
  92. package/dist/docx/paragraphParser.js +212 -396
  93. package/dist/docx/paragraphProperties.d.ts +23 -0
  94. package/dist/docx/paragraphProperties.js +279 -0
  95. package/dist/docx/paragraphPropertySource.js +2 -0
  96. package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
  97. package/dist/docx/paragraphTextBoxEnrichment.js +14 -7
  98. package/dist/docx/paragraphTraversal.d.ts +14 -10
  99. package/dist/docx/paragraphTraversal.js +47 -49
  100. package/dist/docx/parseWarningMessage.js +3 -0
  101. package/dist/docx/parserEnums.d.ts +6 -8
  102. package/dist/docx/parserEnums.js +4 -6
  103. package/dist/docx/preservedRunContent.js +16 -6
  104. package/dist/docx/previewBudget.d.ts +44 -23
  105. package/dist/docx/previewBudget.js +61 -30
  106. package/dist/docx/propertyElementAttributes.d.ts +178 -0
  107. package/dist/docx/propertyElementAttributes.js +114 -0
  108. package/dist/docx/renderedPageBreakNormalization.js +2 -2
  109. package/dist/docx/rezip.d.ts +28 -2
  110. package/dist/docx/rezip.js +78 -9
  111. package/dist/docx/runConsolidator.d.ts +42 -2
  112. package/dist/docx/runConsolidator.js +60 -6
  113. package/dist/docx/runParser.d.ts +54 -18
  114. package/dist/docx/runParser.js +379 -295
  115. package/dist/docx/runPayload.d.ts +5 -0
  116. package/dist/docx/runPayload.js +4 -0
  117. package/dist/docx/sdtProperties.d.ts +39 -5
  118. package/dist/docx/sdtProperties.js +205 -84
  119. package/dist/docx/sdtPropertiesPatch.d.ts +5 -9
  120. package/dist/docx/sdtPropertiesPatch.js +68 -112
  121. package/dist/docx/sectionParser.d.ts +1 -2
  122. package/dist/docx/sectionParser.js +236 -240
  123. package/dist/docx/selectiveSave.js +3 -2
  124. package/dist/docx/selectiveXmlPatch.d.ts +21 -2
  125. package/dist/docx/selectiveXmlPatch.js +195 -99
  126. package/dist/docx/serializer/blockSdtSerializer.js +2 -96
  127. package/dist/docx/serializer/borderSerializer.d.ts +5 -5
  128. package/dist/docx/serializer/borderSerializer.js +10 -8
  129. package/dist/docx/serializer/documentSerializer.js +3 -0
  130. package/dist/docx/serializer/fontTableSerializer.js +31 -3
  131. package/dist/docx/serializer/headerFooterSerializer.js +3 -0
  132. package/dist/docx/serializer/markupRangeAttributes.d.ts +9 -1
  133. package/dist/docx/serializer/markupRangeAttributes.js +9 -1
  134. package/dist/docx/serializer/noteSerializer.js +3 -0
  135. package/dist/docx/serializer/numberingSerializer.d.ts +1 -6
  136. package/dist/docx/serializer/numberingSerializer.js +81 -79
  137. package/dist/docx/serializer/paragraphSerializer.d.ts +1 -9
  138. package/dist/docx/serializer/paragraphSerializer.js +88 -188
  139. package/dist/docx/serializer/runSerializer.d.ts +1 -5
  140. package/dist/docx/serializer/runSerializer.js +109 -59
  141. package/dist/docx/serializer/sdtPropertiesSerializer.d.ts +26 -0
  142. package/dist/docx/serializer/sdtPropertiesSerializer.js +111 -0
  143. package/dist/docx/serializer/sectionPropertiesSerializer.js +34 -45
  144. package/dist/docx/serializer/settingsSerializer.js +6 -4
  145. package/dist/docx/serializer/stylesSerializer.js +8 -11
  146. package/dist/docx/serializer/tableSerializer.js +268 -100
  147. package/dist/docx/serializer/textFormattingSerializer.d.ts +28 -4
  148. package/dist/docx/serializer/textFormattingSerializer.js +111 -101
  149. package/dist/docx/serializer/xmlUtils.d.ts +1 -1
  150. package/dist/docx/serializer/xmlUtils.js +1 -1
  151. package/dist/docx/server/createBilingualDocument.js +18 -16
  152. package/dist/docx/server/migrateYjsAttrSchema.js +3 -3
  153. package/dist/docx/settingsParser.js +7 -4
  154. package/dist/docx/shadingParser.d.ts +2 -1
  155. package/dist/docx/shadingParser.js +43 -7
  156. package/dist/docx/shapeParser.js +8 -3
  157. package/dist/docx/strictNames.d.ts +11 -0
  158. package/dist/docx/strictNames.gen.d.ts +45 -0
  159. package/dist/docx/strictNames.gen.js +50 -0
  160. package/dist/docx/strictNames.js +43 -0
  161. package/dist/docx/strictValueEncodings.gen.js +133 -131
  162. package/dist/docx/styleParser.js +17 -349
  163. package/dist/docx/tableParser.d.ts +10 -1
  164. package/dist/docx/tableParser.js +505 -181
  165. package/dist/docx/textBoxParser.d.ts +3 -1
  166. package/dist/docx/textBoxParser.js +18 -8
  167. package/dist/docx/themeColorAttribute.d.ts +13 -0
  168. package/dist/docx/themeColorAttribute.js +24 -0
  169. package/dist/docx/trackedMoveRangeNormalization.js +2 -1
  170. package/dist/docx/vmlImageParser.d.ts +13 -4
  171. package/dist/docx/vmlImageParser.js +74 -31
  172. package/dist/docx/vmlPreview.js +2 -2
  173. package/dist/docx/wrapPolygon.d.ts +30 -0
  174. package/dist/docx/wrapPolygon.js +70 -0
  175. package/dist/docx/xmlParser.d.ts +14 -1
  176. package/dist/docx/xmlParser.js +18 -2
  177. package/dist/fonts/embeddedFonts.js +3 -3
  178. package/dist/headless-layout.js +2 -0
  179. package/dist/i18n/messages/catalogs.gen.d.ts +68 -0
  180. package/dist/i18n/messages/catalogs.gen.js +102 -34
  181. package/dist/i18n/messages/messages.gen.d.ts +4 -0
  182. package/dist/internal/headlessRevisionResolution.js +9 -0
  183. package/dist/internal/pageBreakRunSourceDescendantIndex.js +3 -1
  184. package/dist/internal/paragraphFormattingSerialization.d.ts +20 -9
  185. package/dist/internal/paragraphFormattingSerialization.js +118 -83
  186. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  187. package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
  188. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  189. package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
  190. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +17 -12
  191. package/dist/layout-bridge/convert/toFlowBlocks.js +177 -101
  192. package/dist/layout-engine/index.d.ts +2 -2
  193. package/dist/layout-engine/index.js +53 -17
  194. package/dist/layout-engine/measure/measureBlocks.d.ts +3 -0
  195. package/dist/layout-engine/measure/measureBlocks.js +6 -10
  196. package/dist/layout-engine/measure/tableCellGrid.js +2 -1
  197. package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +2 -1
  198. package/dist/layout-engine/measure/tableInlinePlacement.js +2 -5
  199. package/dist/layout-engine/paragraphSequence.js +3 -2
  200. package/dist/layout-engine/renderedBreakReconciliation.js +2 -1
  201. package/dist/layout-engine/section-breaks.d.ts +49 -2
  202. package/dist/layout-engine/section-breaks.js +55 -4
  203. package/dist/layout-engine/types.d.ts +47 -17
  204. package/dist/layout-engine/types.js +16 -1
  205. package/dist/layout-painter/borderStroke.d.ts +18 -4
  206. package/dist/layout-painter/renderPage.js +6 -4
  207. package/dist/layout-painter/renderParagraph.d.ts +2 -1
  208. package/dist/layout-painter/renderParagraph.js +13 -26
  209. package/dist/layout-painter/renderTable.d.ts +4 -1
  210. package/dist/layout-painter/renderTable.js +22 -22
  211. package/dist/layout-painter/renderTextBox.js +5 -3
  212. package/dist/markdown/renderBlock.js +3 -1
  213. package/dist/markdown/renderRuns.js +7 -2
  214. package/dist/markdown/renderTable.js +2 -1
  215. package/dist/model.d.ts +3 -3
  216. package/dist/model.js +2 -2
  217. package/dist/paged-layout/sectionBlockWidths.d.ts +3 -0
  218. package/dist/paged-layout/sectionBlockWidths.js +26 -4
  219. package/dist/prosemirror/attrs/index.d.ts +22 -4
  220. package/dist/prosemirror/attrs/index.js +498 -60
  221. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +9 -1
  222. package/dist/prosemirror/bookmarkBoundaryAttrs.js +22 -3
  223. package/dist/prosemirror/commands/comments.js +68 -53
  224. package/dist/prosemirror/commands/contentControls.js +24 -19
  225. package/dist/prosemirror/commands/image.d.ts +1 -1
  226. package/dist/prosemirror/commands/image.js +4 -1
  227. package/dist/prosemirror/commands/paragraph.d.ts +2 -1
  228. package/dist/prosemirror/commands/propertyChangeScope.d.ts +12 -4
  229. package/dist/prosemirror/commands/propertyChangeScope.js +22 -4
  230. package/dist/prosemirror/commands/sectionBreak.d.ts +33 -1
  231. package/dist/prosemirror/commands/sectionBreak.js +187 -11
  232. package/dist/prosemirror/conversion/fromProseDoc.d.ts +18 -2
  233. package/dist/prosemirror/conversion/fromProseDoc.js +330 -183
  234. package/dist/prosemirror/conversion/index.d.ts +2 -2
  235. package/dist/prosemirror/conversion/preservedSinkCarriers.d.ts +39 -0
  236. package/dist/prosemirror/conversion/preservedSinkCarriers.js +19 -0
  237. package/dist/prosemirror/conversion/runShadingMark.js +14 -1
  238. package/dist/prosemirror/conversion/sdtAttrs.d.ts +10 -1
  239. package/dist/prosemirror/conversion/sdtAttrs.js +19 -5
  240. package/dist/prosemirror/conversion/toProseDoc.js +371 -141
  241. package/dist/prosemirror/emptyRangeAnchor.d.ts +53 -0
  242. package/dist/prosemirror/emptyRangeAnchor.js +158 -0
  243. package/dist/prosemirror/extensions/StarterKit.js +8 -2
  244. package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
  245. package/dist/prosemirror/extensions/core/ParagraphExtension.js +19 -15
  246. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +3 -2
  247. package/dist/prosemirror/extensions/features/ListExtension.js +43 -24
  248. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +4 -3
  249. package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +3 -3
  250. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +5 -5
  251. package/dist/prosemirror/extensions/features/pasteCleanup.d.ts +3 -1
  252. package/dist/prosemirror/extensions/features/pasteCleanup.js +56 -2
  253. package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +5 -4
  254. package/dist/prosemirror/extensions/markRegistry.d.ts +26 -2
  255. package/dist/prosemirror/extensions/markRegistry.js +73 -10
  256. package/dist/prosemirror/extensions/marks/InlineWrapperExtension.js +17 -3
  257. package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +26 -0
  258. package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +134 -0
  259. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -1
  260. package/dist/prosemirror/extensions/marks/UnderlineExtension.js +12 -18
  261. package/dist/prosemirror/extensions/marks/markUtils.js +2 -1
  262. package/dist/prosemirror/extensions/nodes/BlockBookmarkBoundaryExtension.d.ts +29 -0
  263. package/dist/prosemirror/extensions/nodes/BlockBookmarkBoundaryExtension.js +46 -0
  264. package/dist/prosemirror/extensions/nodes/BlockSdtExtension.d.ts +4 -3
  265. package/dist/prosemirror/extensions/nodes/BlockSdtExtension.js +18 -13
  266. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +28 -53
  267. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +10 -0
  268. package/dist/prosemirror/extensions/nodes/ImageExtension.js +8 -1
  269. package/dist/prosemirror/extensions/nodes/MoveRangeBoundaryExtension.d.ts +11 -0
  270. package/dist/prosemirror/extensions/nodes/MoveRangeBoundaryExtension.js +43 -0
  271. package/dist/prosemirror/extensions/nodes/RangeAnchorExtension.d.ts +13 -0
  272. package/dist/prosemirror/extensions/nodes/RangeAnchorExtension.js +65 -0
  273. package/dist/prosemirror/extensions/nodes/SdtExtension.d.ts +3 -1
  274. package/dist/prosemirror/extensions/nodes/SdtExtension.js +22 -16
  275. package/dist/prosemirror/extensions/nodes/ShapeExtension.js +4 -0
  276. package/dist/prosemirror/extensions/nodes/TableExtension.js +141 -123
  277. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +4 -0
  278. package/dist/prosemirror/extensions/nodes/bookmarkBoundaryDom.d.ts +23 -0
  279. package/dist/prosemirror/extensions/nodes/bookmarkBoundaryDom.js +57 -0
  280. package/dist/prosemirror/extensions/types.d.ts +12 -3
  281. package/dist/prosemirror/index.d.ts +4 -2
  282. package/dist/prosemirror/index.js +2 -1
  283. package/dist/prosemirror/inlineWrapperStack.js +20 -3
  284. package/dist/prosemirror/listMarker.d.ts +2 -2
  285. package/dist/prosemirror/listMarker.js +7 -8
  286. package/dist/prosemirror/listRenderingAttrs.js +11 -1
  287. package/dist/prosemirror/listState.d.ts +62 -0
  288. package/dist/prosemirror/listState.js +49 -0
  289. package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +13 -0
  290. package/dist/prosemirror/moveRangeBoundaryAttrs.js +114 -0
  291. package/dist/prosemirror/numberedRefFields.js +4 -4
  292. package/dist/prosemirror/numberingAttr.d.ts +55 -0
  293. package/dist/prosemirror/numberingAttr.js +74 -0
  294. package/dist/prosemirror/outlineLevelAttr.d.ts +29 -0
  295. package/dist/prosemirror/outlineLevelAttr.js +42 -0
  296. package/dist/prosemirror/paragraphFormattingProvenance.d.ts +9 -0
  297. package/dist/prosemirror/paragraphFormattingProvenance.js +4 -1
  298. package/dist/prosemirror/plugins/selectionTracker.d.ts +3 -6
  299. package/dist/prosemirror/plugins/selectionTracker.js +3 -10
  300. package/dist/prosemirror/rangeAnchorAttrs.d.ts +14 -0
  301. package/dist/prosemirror/rangeAnchorAttrs.js +101 -0
  302. package/dist/prosemirror/replacedAnnotations.d.ts +1 -1
  303. package/dist/prosemirror/replacedAnnotations.js +24 -6
  304. package/dist/prosemirror/revisionCarriers.d.ts +86 -2
  305. package/dist/prosemirror/revisionCarriers.js +86 -60
  306. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -0
  307. package/dist/prosemirror/runFormattingInlineCarriers.js +2 -0
  308. package/dist/prosemirror/runIdentity.d.ts +28 -0
  309. package/dist/prosemirror/runIdentity.js +36 -0
  310. package/dist/prosemirror/runStyleFormatting.js +1 -1
  311. package/dist/prosemirror/schema/index.d.ts +2 -2
  312. package/dist/prosemirror/schema/marks.d.ts +23 -4
  313. package/dist/prosemirror/schema/nodes.d.ts +220 -24
  314. package/dist/prosemirror/sectionCarrier.d.ts +37 -0
  315. package/dist/prosemirror/sectionCarrier.js +40 -0
  316. package/dist/prosemirror/selectionState.d.ts +3 -0
  317. package/dist/prosemirror/selectionState.js +4 -1
  318. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +5 -4
  319. package/dist/prosemirror/styles/resolvedStyleAttrs.js +15 -13
  320. package/dist/prosemirror/tableResize.js +5 -6
  321. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +2 -0
  322. package/dist/prosemirror/trackedRunInlineAtoms.js +2 -0
  323. package/dist/prosemirror/utils/extractTrackedChanges.d.ts +10 -11
  324. package/dist/prosemirror/utils/extractTrackedChanges.js +109 -92
  325. package/dist/prosemirror/validation.js +17 -6
  326. package/dist/prosemirror/yjsDocumentMetadata.d.ts +2 -2
  327. package/dist/prosemirror/yjsDocumentMetadata.js +428 -7
  328. package/dist/prosemirror/zeroWidthAnchors.js +4 -0
  329. package/dist/style-sets/extract.js +4 -4
  330. package/dist/style-sets/stellaStyle.js +36 -23
  331. package/dist/types/colors.d.ts +2 -2
  332. package/dist/types/content.d.ts +2 -2
  333. package/dist/types/documentEnumValues.d.ts +53 -26
  334. package/dist/types/documentEnumValues.js +72 -174
  335. package/dist/types/formatting.d.ts +2 -2
  336. package/dist/types/index.d.ts +9 -2
  337. package/dist/utils/borderCss.d.ts +246 -0
  338. package/dist/utils/borderCss.js +325 -0
  339. package/dist/utils/colorResolver.d.ts +4 -3
  340. package/dist/utils/colorResolver.js +45 -76
  341. package/dist/utils/createDocument.js +24 -6
  342. package/dist/utils/findReplace.js +52 -10
  343. package/dist/utils/formatToStyle.d.ts +84 -2
  344. package/dist/utils/formatToStyle.js +133 -52
  345. package/dist/utils/headingCollector.js +3 -2
  346. package/dist/utils/mergeDocumentContent.js +5 -3
  347. package/dist/utils/paragraphFormattingMerge.js +27 -6
  348. package/dist/utils/replaceText.js +1 -1
  349. package/dist/utils/tableOperations.d.ts +5 -3
  350. package/dist/utils/tableOperations.js +14 -1
  351. package/dist/utils/tablePlacement.d.ts +7 -0
  352. package/dist/utils/tablePlacement.js +14 -0
  353. package/dist/utils/textDirectionFlow.d.ts +15 -0
  354. package/dist/utils/textDirectionFlow.js +38 -0
  355. package/dist/utils/textFormattingMerge.js +16 -4
  356. package/package.json +10 -10
  357. package/dist/ai-edits/__fixtures__/paragraphs.d.ts +0 -17
  358. package/dist/ai-edits/__fixtures__/paragraphs.js +0 -33
  359. package/dist/compare/__fixtures__/body-sequence.d.ts +0 -119
  360. package/dist/compare/__fixtures__/body-sequence.js +0 -225
  361. package/dist/compare/__fixtures__/nested-table.d.ts +0 -16
  362. package/dist/compare/__fixtures__/nested-table.js +0 -50
  363. package/dist/compare/__fixtures__/numbered-list.d.ts +0 -34
  364. package/dist/compare/__fixtures__/numbered-list.js +0 -85
  365. package/dist/docx/bookmarkPlacement.d.ts +0 -9
  366. package/dist/docx/bookmarkPlacement.js +0 -52
  367. package/dist/fonts/embeddedFontTable.d.ts +0 -45
  368. package/dist/fonts/embeddedFontTable.js +0 -80
  369. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.d.ts +0 -13
  370. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.js +0 -39
@@ -0,0 +1,114 @@
1
+ //#region src/docx/propertyElementAttributes.ts
2
+ /**
3
+ * `w:ind`. `hangingIndent` is the sign of `indentFirstLine` rather than a
4
+ * value of its own, so both name the attribute pair that carries it.
5
+ */
6
+ const INDENTATION_ATTRIBUTES = {
7
+ indentLeft: ["left", "start"],
8
+ indentRight: ["right", "end"],
9
+ indentFirstLine: ["firstLine", "hanging"],
10
+ hangingIndent: "hanging"
11
+ };
12
+ /**
13
+ * `w:spacing`. `spacingExplicit` records which of the two sides the paragraph
14
+ * stated itself; it is derived from them and reads no attribute of its own.
15
+ */
16
+ const SPACING_ATTRIBUTES = {
17
+ spaceBefore: "before",
18
+ spaceAfter: "after",
19
+ lineSpacing: "line",
20
+ lineSpacingRule: "lineRule",
21
+ beforeAutospacing: "beforeAutospacing",
22
+ afterAutospacing: "afterAutospacing",
23
+ spacingExplicit: []
24
+ };
25
+ const FRAME_ATTRIBUTES = {
26
+ dropCap: "dropCap",
27
+ lines: "lines",
28
+ width: "w",
29
+ height: "h",
30
+ hSpace: "hSpace",
31
+ vSpace: "vSpace",
32
+ hAnchor: "hAnchor",
33
+ vAnchor: "vAnchor",
34
+ x: "x",
35
+ y: "y",
36
+ xAlign: "xAlign",
37
+ yAlign: "yAlign",
38
+ wrap: "wrap"
39
+ };
40
+ const TAB_STOP_ATTRIBUTES = {
41
+ position: "pos",
42
+ alignment: "val",
43
+ leader: "leader"
44
+ };
45
+ /**
46
+ * `CT_Border`. The five art relationship ids are in the relationships
47
+ * namespace; the remainder decides on the local name, so naming them here
48
+ * keeps a `r:topLeft` out of it.
49
+ */
50
+ const BORDER_ATTRIBUTES = {
51
+ style: "val",
52
+ color: [
53
+ "color",
54
+ "themeColor",
55
+ "themeTint",
56
+ "themeShade"
57
+ ],
58
+ size: "sz",
59
+ space: "space",
60
+ shadow: "shadow",
61
+ frame: "frame",
62
+ artRelationshipId: "id",
63
+ topLeftArtRelationshipId: "topLeft",
64
+ topRightArtRelationshipId: "topRight",
65
+ bottomLeftArtRelationshipId: "bottomLeft",
66
+ bottomRightArtRelationshipId: "bottomRight"
67
+ };
68
+ /** `CT_Shd`: direct, theme, modifier, and pattern attributes all have model fields. */
69
+ const SHADING_ATTRIBUTES = {
70
+ color: [
71
+ "color",
72
+ "themeColor",
73
+ "themeTint",
74
+ "themeShade"
75
+ ],
76
+ fill: [
77
+ "fill",
78
+ "themeFill",
79
+ "themeFillTint",
80
+ "themeFillShade"
81
+ ],
82
+ pattern: "val"
83
+ };
84
+ /**
85
+ * The same tables by the complex type whose attributes they answer for, in
86
+ * the order the model declares the fields.
87
+ *
88
+ * The census reads this: to catch a whole-or-nothing reader it has to state
89
+ * the subject attribute *beside* one the element models, and which one that
90
+ * is has to come from the model rather than from a list in the census. The
91
+ * first entry is the one it picks.
92
+ */
93
+ const PROPERTY_ELEMENT_ATTRIBUTES = {
94
+ CT_Ind: INDENTATION_ATTRIBUTES,
95
+ CT_Spacing: SPACING_ATTRIBUTES,
96
+ CT_FramePr: FRAME_ATTRIBUTES,
97
+ CT_TabStop: TAB_STOP_ATTRIBUTES,
98
+ CT_Border: BORDER_ATTRIBUTES,
99
+ CT_Shd: SHADING_ATTRIBUTES
100
+ };
101
+ /** Every attribute local name a table names, flattened, in field order. */
102
+ const modelledAttributeNames = (modelled) => {
103
+ const names = [];
104
+ for (const declared of Object.values(modelled)) {
105
+ if (typeof declared === "string") {
106
+ names.push(declared);
107
+ continue;
108
+ }
109
+ names.push(...declared);
110
+ }
111
+ return names;
112
+ };
113
+ //#endregion
114
+ export { BORDER_ATTRIBUTES, FRAME_ATTRIBUTES, INDENTATION_ATTRIBUTES, PROPERTY_ELEMENT_ATTRIBUTES, SHADING_ATTRIBUTES, SPACING_ATTRIBUTES, TAB_STOP_ATTRIBUTES, modelledAttributeNames };
@@ -30,8 +30,8 @@ const scanRun = (run, scan) => {
30
30
  };
31
31
  const scanHyperlink = (hyperlink, scan) => {
32
32
  for (const child of hyperlink.children) {
33
- if (child.type !== "run") continue;
34
- const result = scanRun(child, scan);
33
+ if (child.type !== "run" && child.type !== "inlineWrapper") continue;
34
+ const result = child.type === "run" ? scanRun(child, scan) : scanParagraphContent(child, scan);
35
35
  if (result !== void 0) return result;
36
36
  }
37
37
  };
@@ -3,9 +3,35 @@ import { BlockContent, Hyperlink } from "../types/content.js";
3
3
  import { RawDocxContent } from "./unzip.js";
4
4
  import JSZip from "jszip";
5
5
  //#region src/docx/rezip.d.ts
6
- declare class DocxPackageFidelityError extends Error {
6
+ declare const DocxPackageFidelityError_base: import("better-result").TaggedErrorClass<"DocxPackageFidelityError">;
7
+ declare class DocxPackageFidelityError extends DocxPackageFidelityError_base<{
8
+ message: string;
9
+ }> {
7
10
  constructor(message: string);
8
11
  }
12
+ /**
13
+ * Raised when a save would write a section the editor never authored.
14
+ *
15
+ * Two paragraphs holding the *same* `SectionProperties` object are one
16
+ * section's two halves, not two sections: ProseMirror copies a node's attrs
17
+ * when a command splits it, and the object is passed through by reference and
18
+ * never cloned, so identity is what tells a copy from a second authored break.
19
+ * The paragraph is named because the count alone does not say which of them the
20
+ * save invented.
21
+ */
22
+ declare class DocxDuplicateSectionCarrierError extends DocxPackageFidelityError {
23
+ /** The `w:paraId` of the duplicate carrier, when the package gave it one. */
24
+ readonly paraId: string | null;
25
+ /** Its position among the paragraph-level carriers, in document order. */
26
+ readonly carrierIndex: number;
27
+ /** The position of the carrier it duplicates. */
28
+ readonly duplicatesCarrierIndex: number;
29
+ constructor(options: {
30
+ paraId: string | null;
31
+ carrierIndex: number;
32
+ duplicatesCarrierIndex: number;
33
+ });
34
+ }
9
35
  /**
10
36
  * Find the highest rId number in a relationships XML string.
11
37
  */
@@ -216,4 +242,4 @@ declare function createEmptyDocx(properties?: DocumentPropertiesOptions): Promis
216
242
  */
217
243
  declare function createDocx(doc: document_d_exports.Document, properties?: DocumentPropertiesOptions): Promise<ArrayBuffer>;
218
244
  //#endregion
219
- export { COMMENTS_CONTENT_TYPE, COMMENTS_EXTENDED_CONTENT_TYPE, COMMENTS_EXTENDED_PART, COMMENTS_EXTENDED_PART_LOWER, DocumentPropertiesOptions, DocxPackageFidelityError, RepackOptions, addCommentsExtendedOverride, addCommentsExtendedRelationship, addMedia, addRelationship, applyUpdatesToZip, collectHeaderFooterUpdates, collectHyperlinksWithoutRId, createDocx, createEmptyDocx, findMaxRId, hasModelDrivenPictureWatermark, hasUnmaterializedHeaderFooter, hasUnmaterializedInlineResources, isDocxBuffer, notePartRelsPath, removeCommentsExtendedOverride, removeCommentsExtendedRelationship, repackDocx, repackDocxFromRaw, updateCoreProperties, updateDocumentXml, updateMultipleFiles, updateXmlFile, validateDocx, withoutAttachedTemplate };
245
+ export { COMMENTS_CONTENT_TYPE, COMMENTS_EXTENDED_CONTENT_TYPE, COMMENTS_EXTENDED_PART, COMMENTS_EXTENDED_PART_LOWER, DocumentPropertiesOptions, DocxDuplicateSectionCarrierError, DocxPackageFidelityError, RepackOptions, addCommentsExtendedOverride, addCommentsExtendedRelationship, addMedia, addRelationship, applyUpdatesToZip, collectHeaderFooterUpdates, collectHyperlinksWithoutRId, createDocx, createEmptyDocx, findMaxRId, hasModelDrivenPictureWatermark, hasUnmaterializedHeaderFooter, hasUnmaterializedInlineResources, isDocxBuffer, notePartRelsPath, removeCommentsExtendedOverride, removeCommentsExtendedRelationship, repackDocx, repackDocxFromRaw, updateCoreProperties, updateDocumentXml, updateMultipleFiles, updateXmlFile, validateDocx, withoutAttachedTemplate };
@@ -12,9 +12,10 @@ import { assertValidFolioDocumentModel } from "./modelValidation.js";
12
12
  import { isNewDataUrlDrawing } from "./newImage.js";
13
13
  import { missingNoteReferenceStyles, noteReferenceNeeds } from "./noteReferenceStyles.js";
14
14
  import { parseNumbering } from "./numberingParser.js";
15
- import { isNumberingReference } from "./numberingReference.js";
15
+ import { paragraphNumberingReferenceId as paragraphNumberingReferenceId$1 } from "./numberingReference.js";
16
16
  import { isUnsafePackagePath, reconcilePackageReferences, removeUnsafeEntries } from "./packageParts.js";
17
17
  import { normalizeParaIdRangeInXmlParts } from "./paraIdRangeNormalization.js";
18
+ import { BLOCK_TREE_DESCENT, visitBlockTreeRecords } from "./paragraphTraversal.js";
18
19
  import { RELATIONSHIP_TYPES, parseRelationships, resolveRelativePath } from "./relsParser.js";
19
20
  import { removeResolvedHeaderFooterParts } from "./removeHeaderFooterParts.js";
20
21
  import { normalizeRevisionIdsInXmlParts } from "./revisionIdNormalization.js";
@@ -31,8 +32,9 @@ import { serializeStyle, serializeStylesXml } from "./serializer/stylesSerialize
31
32
  import { serializeThemeXml } from "./serializer/themeSerializer.js";
32
33
  import { OFFICE_RELATIONSHIP_NAMESPACE_URIS, WORDPROCESSINGML_NAMESPACE_URIS, findChild, findChildByNamespaceUri, findChildrenByNamespaceUri, getAttribute, getAttributeByNamespaceUri, getChildElements, getLocalName, getNamespaceUri, matchesName, parseXml, parseXmlDocument } from "./xmlParser.js";
33
34
  import { assertXmlResourceLimits } from "./xmlResourceLimits.js";
34
- import { panic } from "better-result";
35
+ import { TaggedError, panic } from "better-result";
35
36
  import { escapeXmlAttribute, escapeXmlText, validateDocxPackage } from "@stll/docx-core";
37
+ import { mintRelationshipId } from "@stll/docx-core/model";
36
38
  import JSZip from "jszip";
37
39
  //#region src/docx/rezip.ts
38
40
  /**
@@ -65,10 +67,34 @@ import JSZip from "jszip";
65
67
  * - word/_rels/document.xml.rels - Document relationships (preserved)
66
68
  * - docProps/* - Document properties (preserved)
67
69
  */
68
- var DocxPackageFidelityError = class extends Error {
70
+ var DocxPackageFidelityError = class extends TaggedError("DocxPackageFidelityError") {
69
71
  constructor(message) {
70
- super(message);
71
- this.name = "DocxPackageFidelityError";
72
+ super({ message });
73
+ }
74
+ };
75
+ /**
76
+ * Raised when a save would write a section the editor never authored.
77
+ *
78
+ * Two paragraphs holding the *same* `SectionProperties` object are one
79
+ * section's two halves, not two sections: ProseMirror copies a node's attrs
80
+ * when a command splits it, and the object is passed through by reference and
81
+ * never cloned, so identity is what tells a copy from a second authored break.
82
+ * The paragraph is named because the count alone does not say which of them the
83
+ * save invented.
84
+ */
85
+ var DocxDuplicateSectionCarrierError = class extends DocxPackageFidelityError {
86
+ /** The `w:paraId` of the duplicate carrier, when the package gave it one. */
87
+ paraId;
88
+ /** Its position among the paragraph-level carriers, in document order. */
89
+ carrierIndex;
90
+ /** The position of the carrier it duplicates. */
91
+ duplicatesCarrierIndex;
92
+ constructor(options) {
93
+ super(`Full DOCX repack would add a section: paragraph-level w:sectPr carrier ${options.carrierIndex}${options.paraId === null ? "" : ` (w:paraId ${options.paraId})`} holds the same section record as carrier ${options.duplicatesCarrierIndex}.`);
94
+ this.name = "DocxDuplicateSectionCarrierError";
95
+ this.paraId = options.paraId;
96
+ this.carrierIndex = options.carrierIndex;
97
+ this.duplicatesCarrierIndex = options.duplicatesCarrierIndex;
72
98
  }
73
99
  };
74
100
  /**
@@ -136,12 +162,55 @@ const consumeReferenceCount = (counts, key) => {
136
162
  counts.set(key, count - 1);
137
163
  return true;
138
164
  };
165
+ /** Every paragraph the model says a section ends at, in document order. */
166
+ const sectionCarrierParagraphs = (doc) => {
167
+ const carriers = [];
168
+ visitBlockTreeRecords(doc.package.document.content, (record) => {
169
+ if (record.type === "paragraph" && record.sectionProperties !== void 0) carriers.push(record);
170
+ return BLOCK_TREE_DESCENT.descend;
171
+ });
172
+ return carriers;
173
+ };
174
+ /**
175
+ * Every serialized section has exactly one model record, and vice versa.
176
+ *
177
+ * A split paragraph's duplicated `w:sectPr` is a section nobody added,
178
+ * repeating the real one's `w:rsidSect` and claiming its revision history too.
179
+ * Two carriers over one record are therefore invalid regardless of whether a
180
+ * separate deletion makes the total section count rise, fall, or stay equal.
181
+ *
182
+ * The count is a separate invariant: `serializeSectionProperties` fails closed
183
+ * to `""` for a record holding settings it cannot write, so carrier uniqueness
184
+ * alone does not prove the package states the sections the model holds.
185
+ */
186
+ const assertSectionCarriersMatchModel = ({ doc, serializedSectionCount }) => {
187
+ const carriers = sectionCarrierParagraphs(doc);
188
+ const firstHolder = /* @__PURE__ */ new Map();
189
+ for (const [index, paragraph] of carriers.entries()) {
190
+ const record = paragraph.sectionProperties;
191
+ const duplicates = firstHolder.get(record);
192
+ if (duplicates !== void 0) throw new DocxDuplicateSectionCarrierError({
193
+ paraId: paragraph.paraId ?? null,
194
+ carrierIndex: index,
195
+ duplicatesCarrierIndex: duplicates
196
+ });
197
+ firstHolder.set(record, index);
198
+ }
199
+ const finalSectionProperties = doc.package.document.finalSectionProperties;
200
+ if (finalSectionProperties !== void 0 && firstHolder.has(finalSectionProperties)) throw new DocxPackageFidelityError("Full DOCX repack would write the final section record from a paragraph carrier twice.");
201
+ const modelSectionCount = carriers.length + (finalSectionProperties === void 0 ? 0 : 1);
202
+ if (serializedSectionCount !== modelSectionCount) throw new DocxPackageFidelityError(`Full DOCX repack would write ${serializedSectionCount} sections where the editor holds ${modelSectionCount}.`);
203
+ };
139
204
  function assertDocumentPackageFidelity({ originalDocumentXml, serializedDocumentXml, doc, sectionEndpointRemoval, sectionReferenceRemovals = [] }) {
140
205
  const originalSectionCount = countDocumentSections(originalDocumentXml);
141
206
  const serializedSectionCount = countDocumentSections(serializedDocumentXml);
142
207
  const trackedRemovedSectionCount = sectionEndpointRemoval ? sectionEndpointRemoval.sourceParagraphEndpointCount - sectionEndpointRemoval.expectedParagraphEndpointCount : 0;
143
208
  const exactTrackedSectionRemoval = trackedRemovedSectionCount > 0 && originalSectionCount - trackedRemovedSectionCount === serializedSectionCount && serializedSectionCount < originalSectionCount;
144
209
  if (serializedSectionCount < originalSectionCount && !exactTrackedSectionRemoval) throw new DocxPackageFidelityError("Full DOCX repack would drop section properties. Use selective patching instead.");
210
+ assertSectionCarriersMatchModel({
211
+ doc,
212
+ serializedSectionCount
213
+ });
145
214
  const serializedReferenceCounts = /* @__PURE__ */ new Map();
146
215
  for (const reference of extractHeaderFooterReferences(serializedDocumentXml)) incrementReferenceCount(serializedReferenceCounts, headerFooterReferenceKey(reference));
147
216
  const removedReferenceCounts = /* @__PURE__ */ new Map();
@@ -390,7 +459,7 @@ async function processNewImages(parts, zip, compressionLevel) {
390
459
  maxImageNum++;
391
460
  maxId++;
392
461
  const mediaPath = `word/media/${`image${maxImageNum}.${extension}`}`;
393
- const newRId = `rId${maxId}`;
462
+ const newRId = mintRelationshipId(maxId);
394
463
  zip.file(mediaPath, data, {
395
464
  compression: "DEFLATE",
396
465
  compressionOptions: { level: compressionLevel }
@@ -1797,8 +1866,8 @@ const overrideXml = (partName, contentType) => `<Override PartName="${partName}"
1797
1866
  const assertStyleNumberingReferences = (doc) => {
1798
1867
  const referenced = /* @__PURE__ */ new Set();
1799
1868
  for (const style of doc.package.styles?.styles ?? []) {
1800
- const numId = style.pPr?.numPr?.numId;
1801
- if (isNumberingReference(numId)) referenced.add(numId);
1869
+ const numId = paragraphNumberingReferenceId$1(style.pPr?.numPr);
1870
+ if (numId !== void 0) referenced.add(numId);
1802
1871
  }
1803
1872
  if (referenced.size === 0) return;
1804
1873
  const available = new Map(doc.package.numbering?.nums.map((numbering) => [numbering.numId, numbering]) ?? []);
@@ -1810,4 +1879,4 @@ const assertStyleNumberingReferences = (doc) => {
1810
1879
  }
1811
1880
  };
1812
1881
  //#endregion
1813
- export { COMMENTS_CONTENT_TYPE, COMMENTS_EXTENDED_CONTENT_TYPE, COMMENTS_EXTENDED_PART, COMMENTS_EXTENDED_PART_LOWER, DocxPackageFidelityError, addCommentsExtendedOverride, addCommentsExtendedRelationship, addMedia, addRelationship, applyUpdatesToZip, collectHeaderFooterUpdates, collectHyperlinksWithoutRId, createDocx, createEmptyDocx, findMaxRId, hasModelDrivenPictureWatermark, hasUnmaterializedHeaderFooter, hasUnmaterializedInlineResources, isDocxBuffer, notePartRelsPath, removeCommentsExtendedOverride, removeCommentsExtendedRelationship, repackDocx, repackDocxFromRaw, updateCoreProperties, updateDocumentXml, updateMultipleFiles, updateXmlFile, validateDocx, withoutAttachedTemplate };
1882
+ export { COMMENTS_CONTENT_TYPE, COMMENTS_EXTENDED_CONTENT_TYPE, COMMENTS_EXTENDED_PART, COMMENTS_EXTENDED_PART_LOWER, DocxDuplicateSectionCarrierError, DocxPackageFidelityError, addCommentsExtendedOverride, addCommentsExtendedRelationship, addMedia, addRelationship, applyUpdatesToZip, collectHeaderFooterUpdates, collectHyperlinksWithoutRId, createDocx, createEmptyDocx, findMaxRId, hasModelDrivenPictureWatermark, hasUnmaterializedHeaderFooter, hasUnmaterializedInlineResources, isDocxBuffer, notePartRelsPath, removeCommentsExtendedOverride, removeCommentsExtendedRelationship, repackDocx, repackDocxFromRaw, updateCoreProperties, updateDocumentXml, updateMultipleFiles, updateXmlFile, validateDocx, withoutAttachedTemplate };
@@ -1,12 +1,21 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  //#region src/docx/runConsolidator.d.ts
3
+ /**
4
+ * Every `TextFormatting` field, named so the comparison below is total.
5
+ *
6
+ * A field this comparison forgets is a field one of two merged runs loses,
7
+ * silently and at parse time. Naming them turns a field added to the model
8
+ * without a comparison into a compile error rather than a fidelity defect.
9
+ */
10
+ type ComparedTextFormattingField = "bold" | "boldCs" | "italic" | "italicCs" | "underline" | "strike" | "doubleStrike" | "vertAlign" | "smallCaps" | "allCaps" | "hidden" | "noProof" | "color" | "highlight" | "shading" | "fontSize" | "fontSizeCs" | "fontFamily" | "language" | "spacing" | "position" | "scale" | "kerning" | "effect" | "emphasisMark" | "emboss" | "imprint" | "outline" | "shadow" | "rtl" | "cs" | "styleId" | "preserved";
11
+ type ComparedTextFormatting = document_d_exports.ExhaustiveFields<document_d_exports.TextFormatting, ComparedTextFormattingField>;
3
12
  /**
4
13
  * Check if two TextFormatting objects are equivalent
5
14
  *
6
15
  * Uses deep comparison of all properties to determine if runs
7
16
  * can be merged without losing formatting information.
8
17
  */
9
- declare function formattingEquals(a: document_d_exports.TextFormatting | undefined, b: document_d_exports.TextFormatting | undefined): boolean;
18
+ declare function formattingEquals(a: ComparedTextFormatting | undefined, b: ComparedTextFormatting | undefined): boolean;
10
19
  /**
11
20
  * Check if a run contains only text content
12
21
  * (runs with special content like images, fields, etc. should not be merged)
@@ -17,6 +26,37 @@ declare function isTextOnlyRun(run: document_d_exports.Run): boolean;
17
26
  * Runs with breaks, tabs, images, fields, etc. act as merge boundaries
18
27
  */
19
28
  declare function canMergeRun(run: document_d_exports.Run): boolean;
29
+ /**
30
+ * Every `Run` field, named by what a merge does with it.
31
+ *
32
+ * The merged run is the survivor spread whole, so a field added to the model
33
+ * is carried over from one side by default. Naming each one here forces the
34
+ * next field to state whether that default is right before it can compile.
35
+ */
36
+ type MergeDecidedRunField =
37
+ /** Identical for every run. */
38
+ "type" |
39
+ /** Concatenated; see {@link mergeRunContent}. */
40
+ "content" |
41
+ /** Must be equal, and the survivor keeps it. */
42
+ "formatting" |
43
+ /** Must be equal, and the survivor keeps it. */
44
+ "preservedAttributes" |
45
+ /** Refuses the merge outright; see {@link canMergeRun}. */
46
+ "propertyChanges";
47
+ type MergeDecidedRun = document_d_exports.ExhaustiveFields<document_d_exports.Run, MergeDecidedRunField>;
48
+ /**
49
+ * May two adjacent runs become one?
50
+ *
51
+ * Every consolidation site asks this one question, because a merge that any
52
+ * one site decides differently is a merge the next parse undoes. A run holds
53
+ * three records a merged run can hold only one of: its typed formatting, the
54
+ * attributes `w:r` carried that the model has no field for, and the `w:rPr`
55
+ * children no reader took a value from. Merging two runs that disagree on any
56
+ * of them discards the loser's copy, which is how both runs' `w:rsid*` used to
57
+ * vanish at parse time — before the editor, before any gate could see it.
58
+ */
59
+ declare function runsMergeable(a: MergeDecidedRun, b: MergeDecidedRun): boolean;
20
60
  /**
21
61
  * Consolidate an array of runs by merging consecutive runs with identical formatting
22
62
  *
@@ -53,4 +93,4 @@ declare function getConsolidationStats(originalParagraphs: document_d_exports.Pa
53
93
  reductionPercentage: number;
54
94
  };
55
95
  //#endregion
56
- export { canMergeRun, consolidateParagraph, consolidateParagraphContent, consolidateRuns, countRuns, formattingEquals, getConsolidationStats, isTextOnlyRun };
96
+ export { canMergeRun, consolidateParagraph, consolidateParagraphContent, consolidateRuns, countRuns, formattingEquals, getConsolidationStats, isTextOnlyRun, runsMergeable };
@@ -1,4 +1,5 @@
1
1
  import { cloneParagraphWithPropertySource } from "./paragraphPropertySource.js";
2
+ import { runHoldsPayload } from "./runPayload.js";
2
3
  //#region src/docx/runConsolidator.ts
3
4
  /**
4
5
  * Check if two TextFormatting objects are equivalent
@@ -18,6 +19,7 @@ function formattingEquals(a, b) {
18
19
  if (a.smallCaps !== b.smallCaps) return false;
19
20
  if (a.allCaps !== b.allCaps) return false;
20
21
  if (a.hidden !== b.hidden) return false;
22
+ if (a.noProof !== b.noProof) return false;
21
23
  if (a.emboss !== b.emboss) return false;
22
24
  if (a.imprint !== b.imprint) return false;
23
25
  if (a.outline !== b.outline) return false;
@@ -40,8 +42,46 @@ function formattingEquals(a, b) {
40
42
  if (!shadingEquals(a.shading, b.shading)) return false;
41
43
  if (!fontFamilyEquals(a.fontFamily, b.fontFamily)) return false;
42
44
  if (!languageEquals(a.language, b.language)) return false;
45
+ if (!preservedMarkupEquals(a.preserved, b.preserved)) return false;
43
46
  return true;
44
47
  }
48
+ /**
49
+ * Compare two verbatim sinks position by position.
50
+ *
51
+ * The sink is ordered — by `index`, then by source order within an index — and
52
+ * the order is what puts the markup back between the same modelled siblings,
53
+ * so equality is by sequence, not by set.
54
+ */
55
+ function preservedMarkupEquals(a, b) {
56
+ const left = a?.children ?? [];
57
+ const right = b?.children ?? [];
58
+ if (left.length !== right.length) return false;
59
+ return left.every(({ index, xml }, position) => {
60
+ const other = right[position];
61
+ return other !== void 0 && other.index === index && other.xml === xml;
62
+ });
63
+ }
64
+ /**
65
+ * Compare two attribute remainders as sets.
66
+ *
67
+ * An element cannot carry one expanded name twice, so (namespace, name) orders
68
+ * a remainder totally and the sorted keys compare exactly. Order is a set
69
+ * comparison rather than a sequence one because attribute order in XML says
70
+ * nothing: two runs that spelled the same attributes in a different order
71
+ * carry the same remainder and may still become one run.
72
+ */
73
+ function preservedAttributesEqual(a, b) {
74
+ const left = canonicalRemainderKeys(a);
75
+ const right = canonicalRemainderKeys(b);
76
+ return left.length === right.length && left.every((key, index) => key === right[index]);
77
+ }
78
+ /** `\u0000` cannot appear in an XML name, namespace URI or attribute value. */
79
+ const REMAINDER_KEY_SEPARATOR = "\0";
80
+ const canonicalRemainderKeys = (attributes) => (attributes ?? []).map(({ namespace, name, value }) => [
81
+ namespace ?? "",
82
+ name,
83
+ value
84
+ ].join(REMAINDER_KEY_SEPARATOR)).sort();
45
85
  function languageEquals(a, b) {
46
86
  return a?.val === b?.val && a?.eastAsia === b?.eastAsia && a?.bidi === b?.bidi;
47
87
  }
@@ -100,10 +140,24 @@ function isMergeableContent(content) {
100
140
  */
101
141
  function canMergeRun(run) {
102
142
  if (run.propertyChanges && run.propertyChanges.length > 0) return false;
103
- if (run.content.length === 0) return true;
143
+ if (!runHoldsPayload(run)) return false;
104
144
  return run.content.every(isMergeableContent);
105
145
  }
106
146
  /**
147
+ * May two adjacent runs become one?
148
+ *
149
+ * Every consolidation site asks this one question, because a merge that any
150
+ * one site decides differently is a merge the next parse undoes. A run holds
151
+ * three records a merged run can hold only one of: its typed formatting, the
152
+ * attributes `w:r` carried that the model has no field for, and the `w:rPr`
153
+ * children no reader took a value from. Merging two runs that disagree on any
154
+ * of them discards the loser's copy, which is how both runs' `w:rsid*` used to
155
+ * vanish at parse time — before the editor, before any gate could see it.
156
+ */
157
+ function runsMergeable(a, b) {
158
+ return canMergeRun(a) && canMergeRun(b) && formattingEquals(a.formatting, b.formatting) && preservedAttributesEqual(a.preservedAttributes, b.preservedAttributes);
159
+ }
160
+ /**
107
161
  * Merge the content of two runs into a single content array
108
162
  */
109
163
  function mergeRunContent(content1, content2) {
@@ -131,11 +185,12 @@ function consolidateRuns(runs) {
131
185
  const result = [];
132
186
  let current = null;
133
187
  for (const run of runs) {
134
- if (run.content.length === 0) {
188
+ if (!runHoldsPayload(run)) {
135
189
  if (current !== null) {
136
190
  result.push(current);
137
191
  current = null;
138
192
  }
193
+ result.push(run);
139
194
  continue;
140
195
  }
141
196
  if (current === null) {
@@ -145,9 +200,8 @@ function consolidateRuns(runs) {
145
200
  };
146
201
  continue;
147
202
  }
148
- if (canMergeRun(current) && canMergeRun(run) && formattingEquals(current.formatting, run.formatting)) current = {
149
- type: "run",
150
- ...current.formatting !== void 0 ? { formatting: current.formatting } : {},
203
+ if (runsMergeable(current, run)) current = {
204
+ ...current,
151
205
  content: mergeRunContent(current.content, run.content)
152
206
  };
153
207
  else {
@@ -222,4 +276,4 @@ function getConsolidationStats(originalParagraphs, consolidatedParagraphs) {
222
276
  };
223
277
  }
224
278
  //#endregion
225
- export { canMergeRun, consolidateParagraph, consolidateParagraphContent, consolidateRuns, countRuns, formattingEquals, getConsolidationStats, isTextOnlyRun };
279
+ export { canMergeRun, consolidateParagraph, consolidateParagraphContent, consolidateRuns, countRuns, formattingEquals, getConsolidationStats, isTextOnlyRun, runsMergeable };
@@ -2,6 +2,32 @@ import { document_d_exports } from "../types/document.js";
2
2
  import { XmlElement } from "./xmlParser.js";
3
3
  import { StyleMap } from "./styleParser.js";
4
4
  //#region src/docx/runParser.d.ts
5
+ /**
6
+ * Which record beside this `w:rPr` reads children out of it.
7
+ *
8
+ * The four owners of a run property set share one handler map, because they
9
+ * share one content model: `CT_RPr` is `EG_RPrBase` plus `w:rPrChange`, and
10
+ * `CT_ParaRPr` opens that with `EG_ParaRPrTrackChanges`. They differ only in
11
+ * which children a *sibling* record has already claimed, and a child claimed
12
+ * twice is written twice. Naming the owner states that once, at the call site
13
+ * that knows it, instead of leaving it to whichever reader ran first.
14
+ */
15
+ declare const RUN_PROPERTY_OWNERS: {
16
+ /** A `w:r`'s own properties: `Run.propertyChanges` reads the `w:rPrChange`. */
17
+ readonly run: "run";
18
+ /**
19
+ * `w:pPr/w:rPr`. The paragraph's record reads the mark's revision
20
+ * (`ParagraphMarkChange`) and its `w:specVanish`
21
+ * (`ParagraphFormatting.runInWithNext`).
22
+ */
23
+ readonly paragraphMark: "paragraphMark";
24
+ /**
25
+ * A style, a numbering level, a comment's reference mark, the snapshot
26
+ * inside a `w:rPrChange`: nothing beside it reads any of its children.
27
+ */
28
+ readonly standalone: "standalone";
29
+ };
30
+ type RunPropertyOwner = (typeof RUN_PROPERTY_OWNERS)[keyof typeof RUN_PROPERTY_OWNERS];
5
31
  /**
6
32
  * `w:vertAlign` `baseline` is the reserved value that means "no vertical
7
33
  * offset", not a third offset beside `superscript` and `subscript`. It is
@@ -10,34 +36,44 @@ import { StyleMap } from "./styleParser.js";
10
36
  */
11
37
  declare const isBaselineVertAlign: (vertAlign: document_d_exports.TextFormatting["vertAlign"]) => boolean;
12
38
  /**
13
- * Parse run formatting properties (w:rPr)
39
+ * The one reader of a run property set (`w:rPr`).
40
+ *
41
+ * Every owner reads through here — a run, the paragraph mark, a style, a
42
+ * numbering level, a comment's reference mark and the snapshot inside either
43
+ * kind of `w:rPrChange` — so none of them can grow its own idea of which
44
+ * children exist, which values it admits, or which of two statements of one
45
+ * property wins. The style parser used to keep a copy of this function, and
46
+ * the copies had drifted on all three.
47
+ *
48
+ * Every child the content model declares carries a decision: a handler that
49
+ * reads it into {@link TextFormatting}, `ownedElsewhere` when the owner's
50
+ * sibling record reads it, or `CAPTURE` for markup folio models nothing for.
51
+ * A handler that looked and took nothing answers `CAPTURE` as well — `<w:sz/>`
52
+ * states no size and `<w:highlight w:val="chartreuse"/>` states a value the
53
+ * reader's enumeration does not admit, and neither can be decided by the
54
+ * child's name. What no reader took goes to `TextFormatting.preserved` at its
55
+ * schema ordinal, so a rebuild puts it back between the same two siblings.
56
+ *
57
+ * A property stated twice resolves to the last statement; see
58
+ * {@link readLastOccurrenceOnly} for the evidence and for why the statements
59
+ * it beat are not kept.
14
60
  *
15
- * Handles ALL rPr properties:
16
- * - w:b (bold), w:i (italic), w:u (underline with style)
17
- * - w:strike (strikethrough), w:dstrike (double strike)
18
- * - w:vertAlign (superscript/subscript)
19
- * - w:smallCaps, w:caps (capitalization)
20
- * - w:highlight (text highlight color)
21
- * - w:shd (character shading)
22
- * - w:color (text color with theme resolution)
23
- * - w:sz (font size in half-points)
24
- * - w:rFonts (font family with theme resolution)
25
- * - w:spacing (character spacing)
26
- * - w:effect (text effects)
27
- * - And more...
61
+ * An element that states nothing at all still yields a record: `undefined` here
62
+ * means the owner carried no `w:rPr`, never that the one it carried was empty.
28
63
  */
29
- declare function parseRunProperties(rPr: XmlElement | null, theme: document_d_exports.Theme | null, _styles?: StyleMap): document_d_exports.TextFormatting | undefined;
64
+ declare function parseRunProperties(rPr: XmlElement | null, theme: document_d_exports.Theme | null, owner: RunPropertyOwner): document_d_exports.TextFormatting | undefined;
30
65
  /**
31
66
  * Parse a run element (w:r)
32
67
  *
33
68
  * @param node - The w:r XML element
34
- * @param styles - Style map for resolving style references
69
+ * @param _styles - Unread: a run's properties are parsed as the source wrote
70
+ * them, and style resolution happens above this parser
35
71
  * @param theme - Theme for resolving theme colors/fonts
36
72
  * @param rels - Relationship map for resolving image references
37
73
  * @param media - Media files map for image data
38
74
  * @returns Parsed Run object
39
75
  */
40
- declare function parseRun(node: XmlElement, styles: StyleMap | null, theme: document_d_exports.Theme | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null, rootXmlns?: Record<string, string>): document_d_exports.Run;
76
+ declare function parseRun(node: XmlElement, _styles: StyleMap | null, theme: document_d_exports.Theme | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null, rootXmlns?: Record<string, string>): document_d_exports.Run;
41
77
  /**
42
78
  * Get plain text from a run
43
79
  *
@@ -81,4 +117,4 @@ declare function hasFieldChar(run: document_d_exports.Run): boolean;
81
117
  */
82
118
  declare function getFieldCharType(run: document_d_exports.Run): "begin" | "separate" | "end" | null;
83
119
  //#endregion
84
- export { getFieldCharType, getImages, getRunText, hasContent, hasFieldChar, hasImage, isBaselineVertAlign, parseRun, parseRunProperties };
120
+ export { RUN_PROPERTY_OWNERS, RunPropertyOwner, getFieldCharType, getImages, getRunText, hasContent, hasFieldChar, hasImage, isBaselineVertAlign, parseRun, parseRunProperties };