@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,47 +1,54 @@
1
1
  import { joinCommentRangesAcrossParagraphs } from "../../docx/commentRangeJoin.js";
2
2
  import { completeCommentReferences } from "../../docx/commentReferenceCompletion.js";
3
3
  import { EDITED_PREVIEW_FINGERPRINT, imageRawXmlFingerprint } from "../../docx/imageRawXml.js";
4
- import { isInlineSdtContent } from "../../docx/inlineWrapperContent.js";
5
- import { isNumberingReference } from "../../docx/numberingReference.js";
4
+ import { isInlineSdtContent, isSimpleFieldContent } from "../../docx/inlineWrapperContent.js";
5
+ import { paragraphNumberingReferenceId as paragraphNumberingReferenceId$1, sameStatedParagraphNumbering as sameStatedParagraphNumbering$1 } from "../../docx/numberingReference.js";
6
6
  import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, ParagraphPropertySourceValidationError, copyDocumentParagraphPropertySourceContract, copyDocumentParagraphPropertySources, copyParagraphPropertyCapture, copyParagraphPropertySource, decodeTableCellParagraphSourcePayload, getDocumentParagraphPropertySourceContract, getParagraphPropertySource, getParagraphPropertySourceCandidate, getParagraphPropertySourceToken, getParagraphPropertySourceTransferId, getProseDocumentParagraphPropertySourceContract, getProseParagraphPropertySourceToken, isParagraphPropertySourceToken, linkParagraphPropertySourceCandidate, paragraphPropertySourceBelongsToDocument, paragraphPropertySourceTokenMatchesContract, recreateProseNodeWithParagraphPropertySource, restoreTableCellsWithParagraphPropertySources, visitDocumentStoryParagraphs, visitTableCellParagraphPropertySourceBindings } from "../../docx/paragraphPropertySource.js";
7
- import { visitDocxParagraphs } from "../../docx/paragraphTraversal.js";
8
- import { ShapeOutlineStyleSchema, narrowEnum } from "../../docx/parserEnums.js";
7
+ import { BLOCK_TREE_DESCENT, visitBlockTreeRecords, visitDocxParagraphs } from "../../docx/paragraphTraversal.js";
9
8
  import { DATE_UTC_ATTRIBUTE } from "../../docx/trackedChangeInfo.js";
10
- import { isStyleSourcedParagraphNumbering, modelParagraphFormattingEmission, sameAuthoredParagraphNumberingReference } from "../../internal/paragraphFormattingSerialization.js";
9
+ import { copiedWrapPolygon } from "../../docx/wrapPolygon.js";
10
+ import { isStyleSourcedParagraphNumbering, modelParagraphFormattingEmission } from "../../internal/paragraphFormattingSerialization.js";
11
11
  import { createStyleEngine } from "../../style-engine/styleEngine.js";
12
- import { OUTLINE_STYLE_CSS_ALIASES, normalizeShapeTextAnchor } from "../../types/documentEnumValues.js";
12
+ import { normalizeShapeTextAnchor, presetDashForOutlineAttr } from "../../types/documentEnumValues.js";
13
+ import { presetDashForCssBorderStyle } from "../../utils/borderCss.js";
13
14
  import { canonicalJson } from "../../utils/canonicalJson.js";
14
15
  import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
15
16
  import { mergeTextFormatting } from "../../utils/textFormattingMerge.js";
16
17
  import { emuToPixels, emuToStrokePixels, pixelsToEmu } from "../../utils/units.js";
17
- import { expectBlockSdtAttrs, expectCharacterSpacingMarkAttrs, expectCharacterStyleMarkAttrs, expectCommentMarkAttrs, expectEmphasisMarkAttrs, expectFieldAttrs, expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectFootnoteRefMarkAttrs, expectHardBreakAttrs, expectHighlightMarkAttrs, expectHyperlinkMarkAttrs, expectImageAttrs, expectInlineWrapperMarkAttrs, expectLanguageMarkAttrs, expectMathAttrs, expectPageBreakRunAttrs, expectPageBreakRunOwnerMarkAttrs, expectParagraphAttrs, expectPreservedBlockAttrs, expectPreservedXmlAttrs, expectRunFormattingOverrideMarkAttrs, expectRunPropertyChangeMarkAttrs, expectRunShadingMarkAttrs, expectSdtAttrs, expectShapeAttrs, expectStrikeMarkAttrs, expectSymbolAttrs, expectTabAttrs, expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, expectTextBoxAttrs, expectTextColorMarkAttrs, expectTextEffectMarkAttrs, expectTrackedChangeMarkAttrs, expectUnderlineMarkAttrs } from "../attrs/index.js";
18
+ import { expectBlockSdtAttrs, expectCharacterSpacingMarkAttrs, expectCharacterStyleMarkAttrs, expectCommentMarkAttrs, expectEmphasisMarkAttrs, expectFieldAttrs, expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectFootnoteRefMarkAttrs, expectHardBreakAttrs, expectHighlightMarkAttrs, expectHyperlinkMarkAttrs, expectImageAttrs, expectInlineWrapperMarkAttrs, expectLanguageMarkAttrs, expectMathAttrs, expectPageBreakRunAttrs, expectParagraphAttrs, expectPreservedBlockAttrs, expectPreservedXmlAttrs, expectRunFormattingOverrideMarkAttrs, expectRunIdentityMarkAttrs, expectRunPropertyChangeMarkAttrs, expectRunShadingMarkAttrs, expectSdtAttrs, expectShapeAttrs, expectStrikeMarkAttrs, expectSymbolAttrs, expectTabAttrs, expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, expectTextBoxAttrs, expectTextColorMarkAttrs, expectTextEffectMarkAttrs, expectTrackedChangeMarkAttrs, expectUnderlineMarkAttrs } from "../attrs/index.js";
18
19
  import { readAuthoredTransform } from "../authoredTransformAttrs.js";
19
20
  import { autospacingMatchesBase, hasAutospacingBaseSide } from "../autospacingBase.js";
20
- import { bookmarkBoundaryDisplacement, expectBookmarkBoundaryAttrs } from "../bookmarkBoundaryAttrs.js";
21
+ import { bookmarkMarkerFromAttrs, expectBookmarkBoundaryAttrs } from "../bookmarkBoundaryAttrs.js";
21
22
  import { paragraphRejectAttrPatch, paragraphRejectOriginalFormatting, removeParagraphPropertyChanges } from "../commands/propertyChangeScope.js";
22
23
  import { expectCommentReferenceAttrs } from "../commentReferenceAttrs.js";
23
24
  import { INLINE_WRAPPER_MARK_NAME } from "../extensions/marks/InlineWrapperExtension.js";
24
25
  import { applyRunFormattingOverrideAttrs, buildRunFormattingOverrideAttrs } from "../extensions/marks/RunFormattingOverrideExtension.js";
25
26
  import { textFormattingToMarks } from "../extensions/marks/markUtils.js";
27
+ import "../extensions/nodes/MoveRangeBoundaryExtension.js";
28
+ import "../extensions/nodes/RangeAnchorExtension.js";
26
29
  import { inlineWrapperMember, inlineWrapperStackKey } from "../inlineWrapperStack.js";
27
30
  import { listRenderingFromAttrs as listRenderingFromAttrs$1 } from "../listRenderingAttrs.js";
31
+ import { expectMoveRangeBoundaryAttrs } from "../moveRangeBoundaryAttrs.js";
28
32
  import { resolveNumberedRefFields } from "../numberedRefFields.js";
29
33
  import { directParagraphAlignment } from "../paragraphAlignment.js";
30
34
  import { directionToBidi } from "../paragraphDirection.js";
31
35
  import { directParagraphSpacing } from "../paragraphSpacing.js";
36
+ import { expectRangeAnchorAttrs } from "../rangeAnchorAttrs.js";
32
37
  import { RUN_FORMATTING_MARK_NAMES } from "../runFormattingMarkNames.js";
33
38
  import { authoredRunFormattingFromAttrs, hasAuthoredRunFormattingProvenance } from "../runFormattingProvenance.js";
39
+ import { RUN_IDENTITY_MARK_NAME } from "../runIdentity.js";
34
40
  import { paragraphFormattingForRun, paragraphRunStyleContext, resolveEffectiveRunStyleFormatting, suppressParagraphMarkFormatting } from "../runStyleFormatting.js";
35
41
  import { schema } from "../schema/index.js";
36
42
  import { PRESERVED_XML_LEVELS } from "../schema/nodes.js";
37
43
  import { parseShapeGeometryAdjustments } from "../shapeGeometryAdjustments.js";
38
44
  import { expectTextBoxAnchorAttrs } from "../textBoxAnchorAttrs.js";
39
45
  import { assertValidProseMirrorDocument } from "../validation.js";
46
+ import { hasSinkChildren } from "./preservedSinkCarriers.js";
40
47
  import { runShadingAttrsToShading, shadingToRunShadingAttrs } from "./runShadingMark.js";
41
48
  import { decodeSdtListItems, sdtPropertiesFromAttrs, sdtPropertiesMatchAttrs } from "./sdtAttrs.js";
42
49
  import { panic } from "better-result";
50
+ import { DRAWING_RAW_XML_MODES, relationshipIdOf } from "@stll/docx-core/model";
43
51
  import { Fragment } from "prosemirror-model";
44
- import { DRAWING_RAW_XML_MODES } from "@stll/docx-core/model";
45
52
  //#region src/prosemirror/conversion/fromProseDoc.ts
46
53
  /**
47
54
  * ProseMirror to Document Conversion
@@ -54,10 +61,16 @@ import { DRAWING_RAW_XML_MODES } from "@stll/docx-core/model";
54
61
  * - Preserve paragraph attributes (paraId, textId, formatting)
55
62
  * - Handle marks -> TextFormatting conversion
56
63
  */
57
- function normalizeShapeOutlineStyle(style) {
58
- if (!style) return;
59
- if (style in OUTLINE_STYLE_CSS_ALIASES) return OUTLINE_STYLE_CSS_ALIASES[style];
60
- return narrowEnum(style, ShapeOutlineStyleSchema);
64
+ /**
65
+ * The dash an `outlineStyle` attribute names.
66
+ *
67
+ * `"none"` is the explicit no-outline sentinel rather than a dash, so it
68
+ * returns undefined here: the serializer's no-outline guard drops the `<a:ln>`
69
+ * before this is called.
70
+ */
71
+ function normalizeShapeOutlineDash(style) {
72
+ const dash = presetDashForOutlineAttr(style);
73
+ return dash === void 0 || dash === "none" ? void 0 : dash;
61
74
  }
62
75
  function imagePositionFromAttrs(attrs) {
63
76
  const horizontalPosition = attrs?.horizontal;
@@ -88,8 +101,9 @@ const emuFromPixels = (px, key, authored, project) => {
88
101
  return emu !== void 0 && project(emu) === px ? emu : pixelsToEmu(px);
89
102
  };
90
103
  /**
91
- * Copy the wrap insets onto a wrap. Shared by the image, shape and text-box
92
- * paths so one rule decides when an inset keeps its authored EMU.
104
+ * Copy the wrap insets, the slot each was authored on, and the wrap polygon
105
+ * onto a wrap. Shared by the image, shape and text-box paths so one rule
106
+ * decides when an inset keeps its authored EMU.
93
107
  */
94
108
  const assignWrapDistances = (wrap, attrs) => {
95
109
  const authored = attrs._docxAuthoredEmu;
@@ -97,6 +111,22 @@ const assignWrapDistances = (wrap, attrs) => {
97
111
  if (attrs.distBottom !== void 0) wrap.distB = emuFromPixels(attrs.distBottom, "distBottom", authored, emuToPixels);
98
112
  if (attrs.distLeft !== void 0) wrap.distL = emuFromPixels(attrs.distLeft, "distLeft", authored, emuToPixels);
99
113
  if (attrs.distRight !== void 0) wrap.distR = emuFromPixels(attrs.distRight, "distRight", authored, emuToPixels);
114
+ const slots = copiedWrapDistanceSlots(attrs.wrapDistanceSlots);
115
+ if (slots !== void 0) wrap.distanceSlots = slots;
116
+ const extents = copiedEffectExtentSlots(attrs.wrapEffectExtentSlots);
117
+ if (extents !== void 0) wrap.effectExtentSlots = extents;
118
+ const polygon = copiedWrapPolygon(attrs.wrapPolygon);
119
+ if (polygon !== void 0) wrap.polygon = polygon;
120
+ };
121
+ /** A copy, so the model cannot share a slot record with a ProseMirror attr. */
122
+ const copiedWrapDistanceSlots = (slots) => slots === void 0 ? void 0 : {
123
+ ...slots.drawing === void 0 ? {} : { drawing: { ...slots.drawing } },
124
+ ...slots.wrapChild === void 0 ? {} : { wrapChild: { ...slots.wrapChild } }
125
+ };
126
+ /** The same copy, one carrier over. */
127
+ const copiedEffectExtentSlots = (slots) => slots === void 0 ? void 0 : {
128
+ ...slots.drawing === void 0 ? {} : { drawing: { ...slots.drawing } },
129
+ ...slots.wrapChild === void 0 ? {} : { wrapChild: { ...slots.wrapChild } }
100
130
  };
101
131
  function textBoxWrapFromAttrs(attrs) {
102
132
  if (!(attrs.wrapType !== void 0 && attrs.wrapType !== "inline" || attrs.wrapText !== void 0 || attrs.distTop !== void 0 || attrs.distBottom !== void 0 || attrs.distLeft !== void 0 || attrs.distRight !== void 0)) return;
@@ -223,7 +253,12 @@ const restoreLinkedParagraphPropertySources = (content) => {
223
253
  };
224
254
  };
225
255
  /** Convert a ProseMirror document to the document model. */
226
- function fromProseDoc(pmDoc, baseDocument) {
256
+ function fromProseDoc(pmDoc, baseDocument, { reuse = "none" } = {}) {
257
+ switch (reuse) {
258
+ case "none": break;
259
+ case "matched": panic("fromProseDoc: reuse \"matched\" is not implemented");
260
+ default: panic(`fromProseDoc: unhandled reuse ${String(reuse)}`);
261
+ }
227
262
  assertValidProseMirrorDocument(pmDoc, "Cannot convert invalid ProseMirror document to DOCX model");
228
263
  const baseContract = baseDocument ? getDocumentParagraphPropertySourceContract(baseDocument) : void 0;
229
264
  const proseContractAttribute = pmDoc.attrs[PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR];
@@ -502,60 +537,107 @@ function extractBlocks(inputDoc, refResolution = "resolve", styleResolver = null
502
537
  xml: expectPreservedBlockAttrs(node).xml
503
538
  });
504
539
  previousStandaloneTextBox = null;
540
+ } else if (node.type.name === "blockBookmarkBoundary") {
541
+ blocks.push(blockBookmarkMarker(node));
542
+ previousStandaloneTextBox = null;
505
543
  }
506
544
  });
507
545
  if (pendingPageBreaks > 0 && !appendPendingPageBreaksToPreviousParagraph()) flushPendingPageBreaks();
508
546
  removeUnresolvedTextBoxAnchors(blocks, textBoxAnchorMarkers);
509
- keepOneAttributeRemainderPerRecord(blocks);
547
+ keepOneRecordCarriedByIdentity(blocks);
548
+ keepTheSectionBreakOnTheLastParagraphThatCarriesIt(blocks);
510
549
  return blocks;
511
550
  }
512
551
  /**
513
- * The attribute remainder follows the record it was authored on, and only it.
552
+ * What an authored element carried follows its record, and only it.
514
553
  *
515
- * ProseMirror copies a node's attrs when a command splits it, so pressing
554
+ * Two things ride a node's attrs by reference rather than by value: the
555
+ * attribute remainder (`w:rsidR` and its family) and the ordered verbatim sink
556
+ * (the markup a container held beside its modelled children). ProseMirror
557
+ * copies a node's attrs when a command splits or duplicates it, so pressing
516
558
  * Enter in the middle of a paragraph produces two nodes holding the *same*
517
- * remainder array. Writing it back on both would give the new half a
518
- * revision-session id nobody assigned to it: `w:rsidR` says which editing
519
- * session wrote this paragraph, and a copy of it is a claim about history the
520
- * author did not make. The rule is that the half that comes first in document
521
- * order keeps the authored identity, and the other half is a new record with
522
- * no remainder — the same answer a paragraph the editor created from scratch
523
- * gets, which is none.
559
+ * remainder array, and copying a table produces two tables holding the same
560
+ * sink. Writing either back on both is a claim the author did not make:
561
+ * `w:rsidR` says which editing session wrote this paragraph, and a second copy
562
+ * of a `w:bookmarkEnd` is a bookmark boundary nobody wrote. The rule is that
563
+ * the record that comes first in document order keeps what was authored, and
564
+ * the other is a new record with none — the same answer a record the editor
565
+ * created from scratch gets.
524
566
  *
525
567
  * Reference identity is what tells the two cases apart, and it is exact: two
526
- * records that each parsed their own attributes hold different arrays however
527
- * equal their contents, and only a copy made by the editor shares one.
568
+ * records that each parsed their own children and attributes hold different
569
+ * objects however equal their contents, and only a copy made by the editor
570
+ * shares one.
571
+ *
572
+ * The rule holds per block container or it does not hold: a walk that reaches
573
+ * the body, a cell and an `w:sdt` but not a text box leaves the records inside
574
+ * one free to claim an authored revision session each. `visitBlockTreeRecords`
575
+ * is the one traversal, and it is exhaustive over the block union.
528
576
  */
529
- const keepOneAttributeRemainderPerRecord = (blocks) => {
577
+ const keepOneRecordCarriedByIdentity = (blocks) => {
530
578
  const seen = /* @__PURE__ */ new WeakSet();
579
+ /** Whether this object is the authored one rather than a copy's reference. */
580
+ const isAuthored = (value) => {
581
+ if (value === void 0) return true;
582
+ if (seen.has(value)) return false;
583
+ seen.add(value);
584
+ return true;
585
+ };
531
586
  const keepFirst = (record) => {
532
- const remainder = record.preservedAttributes;
533
- if (remainder === void 0) return;
534
- if (seen.has(remainder)) {
535
- delete record.preservedAttributes;
536
- return;
537
- }
538
- seen.add(remainder);
539
- };
540
- const walk = (content) => {
541
- for (const block of content) switch (block.type) {
542
- case "paragraph":
543
- keepFirst(block);
544
- break;
545
- case "table":
546
- for (const row of block.rows) {
547
- keepFirst(row);
548
- for (const cell of row.cells) walk(cell.content);
549
- }
550
- break;
551
- case "blockSdt":
552
- walk(block.content);
553
- break;
554
- default: break;
555
- }
587
+ if (!isAuthored(record.preservedAttributes)) delete record.preservedAttributes;
588
+ if (!isAuthored(record.bookmarks)) delete record.bookmarks;
589
+ if (!isAuthored(record.preserved)) delete record.preserved;
556
590
  };
557
- walk(blocks);
591
+ visitBlockTreeRecords(blocks, (record) => {
592
+ keepFirst(record);
593
+ return BLOCK_TREE_DESCENT.descend;
594
+ });
558
595
  };
596
+ /**
597
+ * The section break belongs to the last paragraph that carries it.
598
+ *
599
+ * A `w:sectPr` inside a `w:pPr` says "the section ends at this paragraph's
600
+ * mark". ProseMirror copies a node's attrs when a command splits it, so
601
+ * pressing Enter inside a section-ending paragraph produces two nodes over the
602
+ * *same* `_sectionProperties` object; writing it back on both ends the section
603
+ * twice. The document gains a section nobody added, and its `w:sectPr` repeats
604
+ * the `w:rsidSect` of the real one, so the copy also claims that section's
605
+ * revision history. On a split the trailing half is the half that still ends
606
+ * the section, and the leading half becomes an ordinary paragraph — Word's own
607
+ * rule, and the exact opposite of the remainder's, which stays with the
608
+ * authored half above.
609
+ *
610
+ * The rule lives on the from-leg rather than in the split commands because the
611
+ * commands cannot be enumerated: Enter, a paste that lands several paragraphs
612
+ * in a section-ending one, an AI edit and a tracked-change resolution each
613
+ * split a paragraph by their own route, and a split merged in from another
614
+ * client reaches no local command at all. Every route arrives here.
615
+ *
616
+ * Reference identity is what tells a copy from a second authored break, and it
617
+ * is exact: two paragraphs that each parsed their own `w:sectPr` hold
618
+ * different objects however equal their contents, and only a copy made by the
619
+ * editor shares one. The projection passes the object through by reference and
620
+ * never clones it, which is what keeps that signal alive.
621
+ */
622
+ const keepTheSectionBreakOnTheLastParagraphThatCarriesIt = (blocks) => {
623
+ const lastCarrier = /* @__PURE__ */ new Map();
624
+ visitBlockTreeRecords(blocks, (record) => {
625
+ if (record.type !== "paragraph" || record.sectionProperties === void 0) return BLOCK_TREE_DESCENT.descend;
626
+ const earlier = lastCarrier.get(record.sectionProperties);
627
+ if (earlier) delete earlier.sectionProperties;
628
+ lastCarrier.set(record.sectionProperties, record);
629
+ return BLOCK_TREE_DESCENT.descend;
630
+ });
631
+ };
632
+ /**
633
+ * A bookmark marker standing between two blocks, back in the model.
634
+ *
635
+ * The node's place in the document is the whole of its position, so nothing is
636
+ * read off it but the marker's own attributes.
637
+ */
638
+ function blockBookmarkMarker(node) {
639
+ return bookmarkMarkerFromAttrs(expectBookmarkBoundaryAttrs(node));
640
+ }
559
641
  function convertPMBlockSdt(node, styleResolver) {
560
642
  const attrs = expectBlockSdtAttrs(node);
561
643
  const properties = { sdtType: attrs.sdtType };
@@ -570,8 +652,9 @@ function convertPMBlockSdt(node, styleResolver) {
570
652
  if (attrs.listItems) properties.listItems = decodeSdtListItems(attrs.listItems);
571
653
  if (typeof attrs.dropdownLastValue === "string") properties.dropdownLastValue = attrs.dropdownLastValue;
572
654
  if (typeof attrs.checked === "boolean") properties.checked = attrs.checked;
573
- if (attrs.rawPropertiesXml) properties.rawPropertiesXml = attrs.rawPropertiesXml;
655
+ if (attrs._preserved) properties.preserved = attrs._preserved;
574
656
  if (attrs.rawEndPropertiesXml) properties.rawEndPropertiesXml = attrs.rawEndPropertiesXml;
657
+ if (attrs.endProperties) properties.endProperties = attrs.endProperties;
575
658
  if (attrs.rawSdtChildrenBeforeContent) properties.rawSdtChildrenBeforeContent = attrs.rawSdtChildrenBeforeContent;
576
659
  if (attrs.rawSdtChildrenAfterContent) properties.rawSdtChildrenAfterContent = attrs.rawSdtChildrenAfterContent;
577
660
  const extracted = extractBlocks(node.type.schema.node("doc", null, node.content), "inherit", styleResolver);
@@ -682,7 +765,7 @@ function replaceTextBoxAnchorInBlocks(blocks, marker, textBoxRun) {
682
765
  for (const row of block.rows) for (const cell of row.cells) if (replaceTextBoxAnchorInBlocks(cell.content, marker, textBoxRun)) return true;
683
766
  continue;
684
767
  }
685
- if (block.type === "preservedBlock") continue;
768
+ if (block.type !== "blockSdt") continue;
686
769
  if (replaceTextBoxAnchorInBlocks(block.content, marker, textBoxRun)) return true;
687
770
  }
688
771
  return false;
@@ -751,7 +834,7 @@ function removeTextBoxAnchorFromBlocks(blocks, marker) {
751
834
  for (const row of block.rows) for (const cell of row.cells) if (removeTextBoxAnchorFromBlocks(cell.content, marker)) return true;
752
835
  continue;
753
836
  }
754
- if (block.type === "preservedBlock") continue;
837
+ if (block.type !== "blockSdt") continue;
755
838
  if (removeTextBoxAnchorFromBlocks(block.content, marker)) return true;
756
839
  }
757
840
  return false;
@@ -763,8 +846,8 @@ function removeTextBoxAnchorFromBlocks(blocks, marker) {
763
846
  * list markers on the way out of the editor.
764
847
  */
765
848
  function listRenderingFromAttrs(attrs) {
766
- const numId = attrs.numPr?.numId;
767
- if (!isNumberingReference(numId)) return;
849
+ const numId = paragraphNumberingReferenceId$1(attrs.numPr);
850
+ if (numId === void 0) return;
768
851
  if (!(attrs.listMarker != null || attrs.listIsBullet || attrs.listNumFmt != null)) return;
769
852
  return listRenderingFromAttrs$1({
770
853
  attrs,
@@ -844,7 +927,6 @@ function convertPMParagraph(node, documentCounts, textBoxAnchorMarkers, styleRes
844
927
  if (listRendering) paragraph.listRendering = listRendering;
845
928
  if (attrs.renderedPageBreakBefore) paragraph.renderedPageBreakBefore = true;
846
929
  if (attrs._sectionProperties) paragraph.sectionProperties = attrs._sectionProperties;
847
- else if (attrs.sectionBreakType) paragraph.sectionProperties = { sectionStart: attrs.sectionBreakType };
848
930
  if (attrs._propertyChanges && attrs._propertyChanges.length > 0) paragraph.propertyChanges = attrs._propertyChanges.map(propertyChangeFromAttrs);
849
931
  if (attrs.pPrMark) paragraph.pPrMark = attrs.pPrMark;
850
932
  if (attrs._preservedAttributes && attrs._preservedAttributes.length > 0) paragraph.preservedAttributes = attrs._preservedAttributes;
@@ -865,7 +947,7 @@ const propertyChangeFromAttrs = (change) => {
865
947
  currentFormatting
866
948
  };
867
949
  const { numPr, ...previousWithoutNumPr } = previousFormatting;
868
- const normalizedPrevious = numPr === null || numPr === void 0 ? previousWithoutNumPr : {
950
+ const normalizedPrevious = numPr == null ? previousWithoutNumPr : {
869
951
  ...previousWithoutNumPr,
870
952
  numPr
871
953
  };
@@ -938,11 +1020,12 @@ function paragraphAttrsToFormatting(attrs) {
938
1020
  else Reflect.deleteProperty(result, "lineSpacingRule");
939
1021
  if (directAlignment === void 0) Reflect.deleteProperty(result, "alignment");
940
1022
  else result.alignment = directAlignment;
941
- if (isStyleSourcedParagraphNumbering(attrs.numPr, attrs.numPrFromStyle)) {
1023
+ const statedNumbering = attrs.numPr;
1024
+ if (isStyleSourcedParagraphNumbering(statedNumbering, attrs.numPrFromStyle)) {
942
1025
  delete result.numPr;
943
1026
  delete result.numPrFromStyle;
944
- } else if (attrs.numPr !== orig.numPr && !sameAuthoredParagraphNumberingReference(attrs.numPr, orig.numPr)) {
945
- if (attrs.numPr) result.numPr = attrs.numPr;
1027
+ } else if (!sameStatedParagraphNumbering$1(statedNumbering, orig.numPr)) {
1028
+ if (statedNumbering !== void 0) result.numPr = statedNumbering;
946
1029
  else delete result.numPr;
947
1030
  delete result.numPrFromStyle;
948
1031
  }
@@ -984,7 +1067,7 @@ function paragraphAttrsToFormatting(attrs) {
984
1067
  const kinsoku = authored("kinsoku", attrs.kinsoku);
985
1068
  const overflowPunctuation = authored("overflowPunctuation", attrs.overflowPunctuation);
986
1069
  const suppressAutoHyphens = authored("suppressAutoHyphens", attrs.suppressAutoHyphens);
987
- if (!(directAlignment !== void 0 || shouldSerializeSpaceBefore || shouldSerializeSpaceAfter || beforeAutospacingEdited || afterAutospacingEdited || hasDirectLineSpacing || hasDirectLineSpacingRule || snapToGrid != null || indentLeft || indentRight || indentFirstLine || attrs.numPr || attrs.styleId || borders || shading || tabs || typeof outlineLevel === "number" || contextualSpacing || attrs.spacingExplicit || bidi != null || pageBreakBefore != null || widowControl != null || keepNext != null || keepLines != null || runInWithNext != null || kinsoku != null || overflowPunctuation != null || suppressAutoHyphens != null)) return;
1070
+ if (!(directAlignment !== void 0 || shouldSerializeSpaceBefore || shouldSerializeSpaceAfter || beforeAutospacingEdited || afterAutospacingEdited || hasDirectLineSpacing || hasDirectLineSpacingRule || snapToGrid != null || indentLeft || indentRight || indentFirstLine || attrs.numPr || attrs.styleId || borders || shading || tabs || outlineLevel !== void 0 || contextualSpacing || attrs.spacingExplicit || bidi != null || pageBreakBefore != null || widowControl != null || keepNext != null || keepLines != null || runInWithNext != null || kinsoku != null || overflowPunctuation != null || suppressAutoHyphens != null)) return;
988
1071
  const f = {};
989
1072
  if (directAlignment !== void 0) f.alignment = directAlignment;
990
1073
  if (shouldSerializeSpaceBefore) f.spaceBefore = spaceBefore;
@@ -999,12 +1082,12 @@ function paragraphAttrsToFormatting(attrs) {
999
1082
  if (indentRight) f.indentRight = indentRight;
1000
1083
  if (indentFirstLine) f.indentFirstLine = indentFirstLine;
1001
1084
  if (attrs.hangingIndent && indentFirstLine) f.hangingIndent = attrs.hangingIndent;
1002
- if (attrs.numPr && !isStyleSourcedParagraphNumbering(attrs.numPr, attrs.numPrFromStyle)) f.numPr = attrs.numPr;
1085
+ if (attrs.numPr !== void 0 && !isStyleSourcedParagraphNumbering(attrs.numPr, attrs.numPrFromStyle)) f.numPr = attrs.numPr;
1003
1086
  if (attrs.styleId) f.styleId = attrs.styleId;
1004
1087
  if (borders) f.borders = borders;
1005
1088
  if (shading) f.shading = shading;
1006
1089
  if (tabs) f.tabs = tabs;
1007
- if (typeof outlineLevel === "number") f.outlineLevel = outlineLevel;
1090
+ if (outlineLevel !== void 0) f.outlineLevel = outlineLevel;
1008
1091
  if (contextualSpacing) f.contextualSpacing = contextualSpacing;
1009
1092
  if (bidi != null) f.bidi = bidi;
1010
1093
  if (pageBreakBefore != null) f.pageBreakBefore = pageBreakBefore;
@@ -1150,7 +1233,7 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
1150
1233
  };
1151
1234
  const appendDirectRun = (node, run, coalescePlainText = false) => {
1152
1235
  const marksKey = getMarksKey(node.marks);
1153
- const ownerId = pageBreakRunOwnerId(node);
1236
+ const ownerId = runIdentityId(node);
1154
1237
  const currentOwnerId = currentRun ? sourceRunOwners.get(currentRun) : void 0;
1155
1238
  const currentRunIsPlainText = currentRun?.content.every((runContent) => runContent.type === "text");
1156
1239
  const joinsOwnedSourceRun = ownerId !== void 0 && ownerId === currentOwnerId && currentRun !== null && runsShareProperties(currentRun, run);
@@ -1242,6 +1325,19 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
1242
1325
  });
1243
1326
  return;
1244
1327
  }
1328
+ if (node.type.name === "rangeAnchor") {
1329
+ flushCurrentInline();
1330
+ currentTrackedChange = void 0;
1331
+ const { start, end } = expectRangeAnchorAttrs(node);
1332
+ content.push({ ...start }, { ...end });
1333
+ return;
1334
+ }
1335
+ if (node.type.name === "moveRangeBoundary") {
1336
+ flushCurrentInline();
1337
+ currentTrackedChange = void 0;
1338
+ content.push({ ...expectMoveRangeBoundaryAttrs(node) });
1339
+ return;
1340
+ }
1245
1341
  const linkMark = node.marks.find((m) => m.type.name === "hyperlink");
1246
1342
  const noteRefMark = node.marks.find((m) => m.type.name === "footnoteRef");
1247
1343
  const insertionMark = node.marks.find((m) => m.type.name === "insertion");
@@ -1356,20 +1452,7 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
1356
1452
  };
1357
1453
  }
1358
1454
  if (node.type.name === "bookmarkBoundary") {
1359
- const attrs = expectBookmarkBoundaryAttrs(node);
1360
- const boundary = attrs.type === "start" ? {
1361
- type: "bookmarkStart",
1362
- id: attrs.id,
1363
- name: attrs.name,
1364
- ...attrs.colFirst !== void 0 ? { colFirst: attrs.colFirst } : {},
1365
- ...attrs.colLast !== void 0 ? { colLast: attrs.colLast } : {},
1366
- ...bookmarkBoundaryDisplacement(attrs)
1367
- } : {
1368
- type: "bookmarkEnd",
1369
- id: attrs.id,
1370
- ...bookmarkBoundaryDisplacement(attrs)
1371
- };
1372
- currentTrackedChange.wrapper.content.push(boundary);
1455
+ currentTrackedChange.wrapper.content.push(bookmarkMarkerFromAttrs(expectBookmarkBoundaryAttrs(node)));
1373
1456
  return;
1374
1457
  }
1375
1458
  if (node.type.name === "field" || node.type.name === "structuredField") {
@@ -1396,7 +1479,7 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
1396
1479
  if (run) appendRunToTrackedWrapper(currentTrackedChange.wrapper, run, node, sourceRunOwners);
1397
1480
  return;
1398
1481
  }
1399
- const ownedRun = linkMark || pageBreakRunOwnerId(node) === void 0 ? null : createTrackedChangeRun({
1482
+ const ownedRun = linkMark || runIdentityId(node) === void 0 ? null : createTrackedChangeRun({
1400
1483
  ...formattingContext,
1401
1484
  marks: node.marks,
1402
1485
  node
@@ -1428,20 +1511,7 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
1428
1511
  if (currentHyperlink) flushCurrentInline();
1429
1512
  if (node.type.name === "bookmarkBoundary") {
1430
1513
  flushCurrentInline();
1431
- const attrs = expectBookmarkBoundaryAttrs(node);
1432
- if (attrs.type === "start") content.push({
1433
- type: "bookmarkStart",
1434
- id: attrs.id,
1435
- name: attrs.name,
1436
- ...attrs.colFirst !== void 0 ? { colFirst: attrs.colFirst } : {},
1437
- ...attrs.colLast !== void 0 ? { colLast: attrs.colLast } : {},
1438
- ...bookmarkBoundaryDisplacement(attrs)
1439
- });
1440
- else content.push({
1441
- type: "bookmarkEnd",
1442
- id: attrs.id,
1443
- ...bookmarkBoundaryDisplacement(attrs)
1444
- });
1514
+ content.push(bookmarkMarkerFromAttrs(expectBookmarkBoundaryAttrs(node)));
1445
1515
  } else if (node.isText) appendDirectRun(node, createRunFromText({
1446
1516
  ...formattingContext,
1447
1517
  marks: node.marks,
@@ -1541,7 +1611,7 @@ function createTrackedChangeRun({ baseParagraphFormatting, inheritedFormatting,
1541
1611
  }] : [],
1542
1612
  ...Object.keys(formatting).length > 0 ? { formatting } : {}
1543
1613
  };
1544
- restoreRunPropertyChanges(run, marks);
1614
+ restoreRunRecord(run, marks);
1545
1615
  } else if (node.type.name === "symbol") run = createSymbolRun(node, marks, formattingContext);
1546
1616
  else if (node.type.name === "preservedXml") run = createPreservedXmlRun(node, marks, formattingContext);
1547
1617
  else if (node.type.name === "hardBreak") run = createBreakRun(expectHardBreakAttrs(node), marks, formattingContext);
@@ -1556,11 +1626,11 @@ function createTrackedChangeRun({ baseParagraphFormatting, inheritedFormatting,
1556
1626
  else if (node.type.name === "shape") run = createShapeRun(node);
1557
1627
  else if (node.type.name === "tab") run = createTabRun(node, marks, formattingContext);
1558
1628
  else if (node.type.name === "renderedPageBreak") run = createRenderedPageBreakRun();
1559
- if (!run || pageBreakRunOwnerId(node) === void 0) return run;
1629
+ if (!run || runIdentityId(node) === void 0) return run;
1560
1630
  if (node.type.name === "image" || node.type.name === "shape" || node.type.name === "renderedPageBreak") {
1561
1631
  const formatting = getRunFormattingFromMarks(marks, formattingContext);
1562
1632
  if (formatting) run.formatting = formatting;
1563
- restoreRunPropertyChanges(run, marks);
1633
+ restoreRunRecord(run, marks);
1564
1634
  }
1565
1635
  return run;
1566
1636
  }
@@ -1651,20 +1721,7 @@ function createHyperlink(linkMark) {
1651
1721
  }
1652
1722
  function addNodeToHyperlink({ baseParagraphFormatting, hyperlink, inheritedFormatting, node, paragraphMarkFormatting, paragraphMarkPrecedesStyle, sourceRunOwners, styleResolver }) {
1653
1723
  if (node.type.name === "bookmarkBoundary") {
1654
- const attrs = expectBookmarkBoundaryAttrs(node);
1655
- if (attrs.type === "start") hyperlink.children.push({
1656
- type: "bookmarkStart",
1657
- id: attrs.id,
1658
- name: attrs.name,
1659
- ...attrs.colFirst !== void 0 ? { colFirst: attrs.colFirst } : {},
1660
- ...attrs.colLast !== void 0 ? { colLast: attrs.colLast } : {},
1661
- ...bookmarkBoundaryDisplacement(attrs)
1662
- });
1663
- else hyperlink.children.push({
1664
- type: "bookmarkEnd",
1665
- id: attrs.id,
1666
- ...bookmarkBoundaryDisplacement(attrs)
1667
- });
1724
+ hyperlink.children.push(bookmarkMarkerFromAttrs(expectBookmarkBoundaryAttrs(node)));
1668
1725
  return;
1669
1726
  }
1670
1727
  const formattingContext = {
@@ -1675,7 +1732,7 @@ function addNodeToHyperlink({ baseParagraphFormatting, hyperlink, inheritedForma
1675
1732
  styleResolver
1676
1733
  };
1677
1734
  const nonLinkMarks = node.marks.filter((mark) => mark.type.name !== "hyperlink");
1678
- const ownedRun = pageBreakRunOwnerId(node) === void 0 ? null : createTrackedChangeRun({
1735
+ const ownedRun = runIdentityId(node) === void 0 ? null : createTrackedChangeRun({
1679
1736
  ...formattingContext,
1680
1737
  marks: nonLinkMarks,
1681
1738
  node
@@ -1788,7 +1845,7 @@ function createNoteReferenceRun(noteRefMark, marks, formattingContext) {
1788
1845
  ...formatting,
1789
1846
  vertAlign
1790
1847
  };
1791
- restoreRunPropertyChanges(run, marks);
1848
+ restoreRunRecord(run, marks);
1792
1849
  return run;
1793
1850
  }
1794
1851
  function createRunFromText({ baseParagraphFormatting, inheritedFormatting, marks, paragraphMarkFormatting, paragraphMarkPrecedesStyle, styleResolver, text }) {
@@ -1807,7 +1864,7 @@ function createRunFromText({ baseParagraphFormatting, inheritedFormatting, marks
1807
1864
  }]
1808
1865
  };
1809
1866
  if (formatting) run.formatting = formatting;
1810
- restoreRunPropertyChanges(run, marks);
1867
+ restoreRunRecord(run, marks);
1811
1868
  return run;
1812
1869
  }
1813
1870
  function createSymbolRun(node, marks, formattingContext) {
@@ -1822,7 +1879,7 @@ function createSymbolRun(node, marks, formattingContext) {
1822
1879
  };
1823
1880
  const formatting = getAtomRunFormattingFromMarks(marks, formattingContext);
1824
1881
  if (formatting) run.formatting = formatting;
1825
- restoreRunPropertyChanges(run, marks);
1882
+ restoreRunRecord(run, marks);
1826
1883
  return run;
1827
1884
  }
1828
1885
  /**
@@ -1860,15 +1917,39 @@ function createPreservedXmlRun(node, marks, formattingContext) {
1860
1917
  };
1861
1918
  const formatting = getAtomRunFormattingFromMarks(marks, formattingContext);
1862
1919
  if (formatting) run.formatting = formatting;
1863
- restoreRunPropertyChanges(run, marks);
1920
+ restoreRunRecord(run, marks);
1864
1921
  return run;
1865
1922
  }
1866
- function restoreRunPropertyChanges(run, marks) {
1923
+ /**
1924
+ * Put back everything about the authored `w:r` that the marks still carry:
1925
+ * its property revision, its attribute remainder and its `w:rPr` sink.
1926
+ *
1927
+ * One helper for the three, called at every site that builds a run, because a
1928
+ * site that restored two of them would write a `w:r` that has lost the third
1929
+ * without anything saying so. A leaf with no identity mark produces a run with
1930
+ * neither remainder nor sink, which is what typed text is.
1931
+ */
1932
+ function restoreRunRecord(run, marks) {
1867
1933
  const changeMark = marks.find((mark) => mark.type.name === "runPropertyChange");
1868
- if (!changeMark) return;
1869
- const { changes } = expectRunPropertyChangeMarkAttrs(changeMark);
1870
- if (changes.length === 0) return;
1871
- run.propertyChanges = [...changes];
1934
+ if (changeMark) {
1935
+ const { changes } = expectRunPropertyChangeMarkAttrs(changeMark);
1936
+ if (changes.length > 0) run.propertyChanges = [...changes];
1937
+ }
1938
+ const identityMark = marks.find((mark) => mark.type.name === RUN_IDENTITY_MARK_NAME);
1939
+ if (!identityMark) return;
1940
+ const { preservedAttributes, preserved } = expectRunIdentityMarkAttrs(identityMark);
1941
+ if (preservedAttributes && preservedAttributes.length > 0) run.preservedAttributes = preservedAttributes.map(({ namespace, name, value }) => namespace === void 0 ? {
1942
+ name,
1943
+ value
1944
+ } : {
1945
+ namespace,
1946
+ name,
1947
+ value
1948
+ });
1949
+ if (preserved && (preserved.children?.length ?? 0) > 0) run.formatting = {
1950
+ ...run.formatting,
1951
+ preserved
1952
+ };
1872
1953
  }
1873
1954
  function getRunFormattingFromMarks(marks, options) {
1874
1955
  if (!marks || marks.length === 0 && !options) return;
@@ -1899,17 +1980,25 @@ function runsShareProperties(left, right) {
1899
1980
  propertyChanges: right.propertyChanges
1900
1981
  });
1901
1982
  }
1902
- function pageBreakRunOwnerId(node) {
1903
- const mark = node.marks.find(({ type }) => type.name === "pageBreakRunOwner");
1904
- return mark ? expectPageBreakRunOwnerMarkAttrs(mark).id : void 0;
1983
+ /**
1984
+ * The authored `w:r` this leaf came from, when it names one.
1985
+ *
1986
+ * Two leaves that share an id are two pieces of one authored run — the cut a
1987
+ * page-break atom makes — and the save leg rejoins them. Two leaves with
1988
+ * different ids are two runs however alike their formatting, which is what
1989
+ * keeps both sides' `w:rsid*` alive across a paragraph the editor rebuilt.
1990
+ */
1991
+ function runIdentityId(node) {
1992
+ const mark = node.marks.find(({ type }) => type.name === RUN_IDENTITY_MARK_NAME);
1993
+ return mark ? expectRunIdentityMarkAttrs(mark).id : void 0;
1905
1994
  }
1906
1995
  function canJoinOwnedRuns(previous, run, node, sourceRunOwners) {
1907
1996
  if (!previous || !runsShareProperties(previous, run)) return false;
1908
- const ownerId = pageBreakRunOwnerId(node);
1997
+ const ownerId = runIdentityId(node);
1909
1998
  return ownerId !== void 0 && sourceRunOwners.get(previous) === ownerId;
1910
1999
  }
1911
2000
  function rememberSourceRunOwner(run, node, sourceRunOwners) {
1912
- const ownerId = pageBreakRunOwnerId(node);
2001
+ const ownerId = runIdentityId(node);
1913
2002
  if (ownerId !== void 0) sourceRunOwners.set(run, ownerId);
1914
2003
  }
1915
2004
  function appendRunToTrackedWrapper(wrapper, run, node, sourceRunOwners) {
@@ -1947,7 +2036,7 @@ function createPageBreakCarrierRun({ baseParagraphFormatting, clear, inheritedFo
1947
2036
  styleResolver
1948
2037
  });
1949
2038
  if (formatting) run.formatting = formatting;
1950
- if (marks) restoreRunPropertyChanges(run, marks);
2039
+ if (marks) restoreRunRecord(run, marks);
1951
2040
  return run;
1952
2041
  }
1953
2042
  /**
@@ -1964,7 +2053,7 @@ function createBreakRun(attrs, marks, formattingContext) {
1964
2053
  };
1965
2054
  const formatting = getAtomRunFormattingFromMarks(marks, formattingContext);
1966
2055
  if (formatting) run.formatting = formatting;
1967
- if (marks) restoreRunPropertyChanges(run, marks);
2056
+ if (marks) restoreRunRecord(run, marks);
1968
2057
  return run;
1969
2058
  }
1970
2059
  function createRenderedPageBreakRun() {
@@ -1987,7 +2076,7 @@ function createTabRun(node, marks, formattingContext) {
1987
2076
  };
1988
2077
  const formatting = getAtomRunFormattingFromMarks(marks, formattingContext);
1989
2078
  if (formatting) run.formatting = formatting;
1990
- if (marks) restoreRunPropertyChanges(run, marks);
2079
+ if (marks) restoreRunRecord(run, marks);
1991
2080
  return run;
1992
2081
  }
1993
2082
  function createFieldFromNode(node, { baseParagraphFormatting, inheritedFormatting, marks, paragraphMarkFormatting, paragraphMarkPrecedesStyle, styleResolver, textBoxAnchorMarkers }) {
@@ -2005,7 +2094,7 @@ function createFieldFromNode(node, { baseParagraphFormatting, inheritedFormattin
2005
2094
  paragraphMarkFormatting,
2006
2095
  paragraphMarkPrecedesStyle: paragraphMarkPrecedesStyle ?? false,
2007
2096
  styleResolver: styleResolver ?? null
2008
- }).filter((content) => content.type === "run" || content.type === "hyperlink" || content.type === "preservedInline");
2097
+ }).filter(isSimpleFieldContent);
2009
2098
  const displayText = attrs.displayText ?? "";
2010
2099
  const displayRun = {
2011
2100
  type: "run",
@@ -2015,7 +2104,7 @@ function createFieldFromNode(node, { baseParagraphFormatting, inheritedFormattin
2015
2104
  }],
2016
2105
  ...formatting && Object.keys(formatting).length > 0 ? { formatting } : {}
2017
2106
  };
2018
- if (marks && node.type.name === "field") restoreRunPropertyChanges(displayRun, marks);
2107
+ if (marks && node.type.name === "field") restoreRunRecord(displayRun, marks);
2019
2108
  const fieldContent = extractedContent.length > 0 ? synchronizeFieldDisplayText(extractedContent, displayText, displayRun) : [];
2020
2109
  const fallbackFieldContent = displayText ? [displayRun] : [];
2021
2110
  if (attrs.fieldKind === "complex") {
@@ -2042,16 +2131,18 @@ function createFieldFromNode(node, { baseParagraphFormatting, inheritedFormattin
2042
2131
  }
2043
2132
  const synchronizeFieldDisplayText = (content, displayText, fallbackRun) => {
2044
2133
  let currentText = "";
2045
- const visitRuns = (visit) => {
2046
- for (const child of content) {
2134
+ const visitRunsIn = (items, visit) => {
2135
+ for (const child of items) {
2047
2136
  if (child.type === "run") {
2048
2137
  visit(child);
2049
2138
  continue;
2050
2139
  }
2051
- if (child.type !== "hyperlink") continue;
2052
- for (const hyperlinkChild of child.children) if (hyperlinkChild.type === "run") visit(hyperlinkChild);
2140
+ if (child.type === "hyperlink" || child.type === "inlineWrapper") visitRunsIn(child.type === "hyperlink" ? child.children : child.content, visit);
2053
2141
  }
2054
2142
  };
2143
+ const visitRuns = (visit) => {
2144
+ visitRunsIn(content, visit);
2145
+ };
2055
2146
  visitRuns((run) => {
2056
2147
  for (const runContent of run.content) if (runContent.type === "text") currentText += runContent.text;
2057
2148
  });
@@ -2088,14 +2179,42 @@ function createMathFromNode(node) {
2088
2179
  return math;
2089
2180
  }
2090
2181
  /**
2182
+ * A revision covering every child of a control, written around the control.
2183
+ *
2184
+ * `w:ins > w:sdt` and `w:sdt > w:ins` reach the editor as the same revision
2185
+ * mark on the same leaves, so the save leg has to pick one and writes the
2186
+ * canonical order: the revision outermost, as it already is around a hyperlink
2187
+ * and around a transparent wrapper. Outermost is also the only form in which
2188
+ * accepting or rejecting the change is an operation over the whole control —
2189
+ * the reader who inserted a bound field inserted the field, not its text.
2190
+ *
2191
+ * A revision that covers only part of the content has no such form and stays
2192
+ * where the editor holds it, per child.
2193
+ */
2194
+ const hoistUniformRevision = (sdt) => {
2195
+ const only = sdt.content.length === 1 ? sdt.content.at(0) : void 0;
2196
+ if (only === void 0 || !isRevisionWrapper(only)) return sdt;
2197
+ const admitted = only.content.filter(isInlineSdtContent);
2198
+ if (admitted.length !== only.content.length) return sdt;
2199
+ return {
2200
+ ...only,
2201
+ content: [{
2202
+ ...sdt,
2203
+ content: admitted
2204
+ }]
2205
+ };
2206
+ };
2207
+ /**
2091
2208
  * Create an InlineSdt from a PM sdt node
2092
2209
  */
2093
2210
  function createInlineSdtFromNode(node, textBoxAnchorMarkers, formattingContext) {
2094
- return {
2211
+ const properties = sdtPropertiesFromAttrs(expectSdtAttrs(node));
2212
+ const content = extractParagraphContent(node, void 0, void 0, textBoxAnchorMarkers, false, formattingContext).filter(isInlineSdtContent);
2213
+ return hoistUniformRevision({
2095
2214
  type: "inlineSdt",
2096
- properties: sdtPropertiesFromAttrs(expectSdtAttrs(node)),
2097
- content: extractParagraphContent(node, void 0, void 0, textBoxAnchorMarkers, false, formattingContext).filter(isInlineSdtContent)
2098
- };
2215
+ properties,
2216
+ content
2217
+ });
2099
2218
  }
2100
2219
  /**
2101
2220
  * Create a Run containing an image
@@ -2108,15 +2227,24 @@ function createInlineSdtFromNode(node, textBoxAnchorMarkers, formattingContext)
2108
2227
  * around one has no other record of the properties it was authored with.
2109
2228
  */
2110
2229
  const carriedRunFormatting = (formatting) => formatting && Object.keys(formatting).length > 0 ? { formatting } : {};
2230
+ /**
2231
+ * The anchor record off a node's attrs, copied so the model never aliases a
2232
+ * ProseMirror attribute object.
2233
+ */
2234
+ const restoredDrawingAnchor = (anchor) => anchor === void 0 ? void 0 : {
2235
+ ...anchor,
2236
+ ...anchor.simplePosition === void 0 ? {} : { simplePosition: { ...anchor.simplePosition } }
2237
+ };
2111
2238
  function createImageRun(node) {
2112
2239
  const attrs = expectImageAttrs(node);
2113
2240
  const wrap = { type: attrs.wrapType || "inline" };
2114
2241
  assignWrapDistances(wrap, attrs);
2115
2242
  if (attrs.wrapText) wrap.wrapText = attrs.wrapText;
2116
2243
  const authoredEmu = attrs._docxAuthoredEmu;
2244
+ const rId = relationshipIdOf(attrs.rId);
2117
2245
  const image = {
2118
2246
  type: "image",
2119
- rId: attrs.rId || "",
2247
+ ...rId === void 0 ? {} : { rId },
2120
2248
  src: attrs.src,
2121
2249
  size: {
2122
2250
  width: emuFromPixels(attrs.width || 0, "width", authoredEmu, emuToPixels),
@@ -2136,7 +2264,8 @@ function createImageRun(node) {
2136
2264
  };
2137
2265
  const imagePosition = imagePositionFromAttrs(attrs.position);
2138
2266
  if (imagePosition) image.position = imagePosition;
2139
- if (attrs.layoutInCell !== void 0) image.layoutInCell = attrs.layoutInCell;
2267
+ const imageAnchor = restoredDrawingAnchor(attrs.anchor);
2268
+ if (imageAnchor) image.anchor = imageAnchor;
2140
2269
  if (attrs.decorative !== void 0) image.decorative = attrs.decorative;
2141
2270
  if (attrs.hidden !== void 0) image.hidden = attrs.hidden;
2142
2271
  if (attrs.docPrExtensions !== void 0) image.docPrExtensions = [...attrs.docPrExtensions];
@@ -2144,21 +2273,15 @@ function createImageRun(node) {
2144
2273
  if (attrs.borderWidth && attrs.borderWidth > 0) {
2145
2274
  const outline = {
2146
2275
  width: emuFromPixels(attrs.borderWidth, "borderWidth", authoredEmu, emuToStrokePixels),
2147
- style: attrs.borderStyle ? {
2148
- solid: "solid",
2149
- dotted: "dot",
2150
- dashed: "dash",
2151
- double: "solid",
2152
- groove: "solid",
2153
- ridge: "solid",
2154
- inset: "solid",
2155
- outset: "solid"
2156
- }[attrs.borderStyle] || "solid" : "solid"
2276
+ dash: presetDashForCssBorderStyle(attrs.borderStyle)
2157
2277
  };
2158
2278
  if (attrs.borderColor) outline.color = { rgb: attrs.borderColor.replace("#", "") };
2159
2279
  image.outline = outline;
2160
2280
  }
2161
2281
  if (attrs.hlinkHref) image.hlinkHref = attrs.hlinkHref;
2282
+ if (attrs.docPrId !== void 0) image.id = attrs.docPrId;
2283
+ if (attrs.hlinkClickSource !== void 0) image.hlinkClickSource = { ...attrs.hlinkClickSource };
2284
+ if (attrs.hlinkHoverXml !== void 0) image.hlinkHoverXml = attrs.hlinkHoverXml;
2162
2285
  if (attrs.hlinkRId) image.hlinkRId = attrs.hlinkRId;
2163
2286
  const cropTop = attrs.cropTop != null && attrs.cropTop > 0 ? attrs.cropTop : void 0;
2164
2287
  const cropRight = attrs.cropRight != null && attrs.cropRight > 0 ? attrs.cropRight : void 0;
@@ -2181,11 +2304,13 @@ function createImageRun(node) {
2181
2304
  if (paddingLeft !== void 0) padding.left = paddingLeft;
2182
2305
  image.padding = padding;
2183
2306
  }
2184
- return {
2307
+ const run = {
2185
2308
  type: "run",
2186
2309
  ...carriedRunFormatting(attrs._docxRunFormatting),
2187
2310
  content: [drawingFromImageAttrs(image, attrs)]
2188
2311
  };
2312
+ restoreRunRecord(run, node.marks);
2313
+ return run;
2189
2314
  }
2190
2315
  /**
2191
2316
  * Rebuild the `DrawingContent` union member the image node came from.
@@ -2246,6 +2371,8 @@ function createShapeRun(node) {
2246
2371
  shape.wrap = wrap;
2247
2372
  const shapePosition = imagePositionFromAttrs(attrs.position);
2248
2373
  if (shapePosition) shape.position = shapePosition;
2374
+ const shapeAnchor = restoredDrawingAnchor(attrs.anchor);
2375
+ if (shapeAnchor) shape.anchor = shapeAnchor;
2249
2376
  if (attrs.fillType === "gradient" && attrs.gradientStops) try {
2250
2377
  const parsed = JSON.parse(attrs.gradientStops);
2251
2378
  const gradient = {
@@ -2275,8 +2402,8 @@ function createShapeRun(node) {
2275
2402
  const shapeOutline = {};
2276
2403
  if (attrs.outlineWidth !== void 0 && attrs.outlineWidth > 0) shapeOutline.width = emuFromPixels(attrs.outlineWidth, "outlineWidth", authoredEmu, emuToStrokePixels);
2277
2404
  if (attrs.outlineStyle) {
2278
- const style = normalizeShapeOutlineStyle(attrs.outlineStyle);
2279
- if (style !== void 0) shapeOutline.style = style;
2405
+ const dash = normalizeShapeOutlineDash(attrs.outlineStyle);
2406
+ if (dash !== void 0) shapeOutline.dash = dash;
2280
2407
  }
2281
2408
  if (attrs.outlineCap) shapeOutline.cap = attrs.outlineCap;
2282
2409
  if (attrs.outlineJoin) shapeOutline.join = attrs.outlineJoin;
@@ -2289,11 +2416,13 @@ function createShapeRun(node) {
2289
2416
  type: "shape",
2290
2417
  shape
2291
2418
  };
2292
- return {
2419
+ const run = {
2293
2420
  type: "run",
2294
2421
  ...carriedRunFormatting(attrs._docxRunFormatting),
2295
2422
  content: [shapeContent]
2296
2423
  };
2424
+ restoreRunRecord(run, node.marks);
2425
+ return run;
2297
2426
  }
2298
2427
  const RUN_FORMATTING_VISUAL_GROUPS = {
2299
2428
  bold: "bold",
@@ -2327,7 +2456,8 @@ const RUN_FORMATTING_VISUAL_GROUPS = {
2327
2456
  shadow: "shadow",
2328
2457
  rtl: "rtl",
2329
2458
  cs: null,
2330
- styleId: null
2459
+ styleId: null,
2460
+ preserved: null
2331
2461
  };
2332
2462
  const RUN_FORMATTING_FAST_PATH_DISPOSITION = {
2333
2463
  bold: "visual",
@@ -2361,7 +2491,8 @@ const RUN_FORMATTING_FAST_PATH_DISPOSITION = {
2361
2491
  shadow: "visual",
2362
2492
  rtl: "visual",
2363
2493
  cs: "structural",
2364
- styleId: "character-style"
2494
+ styleId: "character-style",
2495
+ preserved: "structural"
2365
2496
  };
2366
2497
  const hasOnlyCarrierlessVisualFormatting = (formatting) => {
2367
2498
  for (const property of Object.keys(formatting)) if (RUN_FORMATTING_FAST_PATH_DISPOSITION[property] !== "visual") return false;
@@ -2895,7 +3026,7 @@ function convertPMTable(node, documentCounts, styleResolver = null) {
2895
3026
  rows
2896
3027
  };
2897
3028
  if (attrs.columnWidths) minTable.columnWidths = attrs.columnWidths;
2898
- restoreTablePropertyChanges(minTable, attrs);
3029
+ restoreCarriedTableAttrs(minTable, attrs);
2899
3030
  return minTable;
2900
3031
  }
2901
3032
  }
@@ -2905,16 +3036,22 @@ function convertPMTable(node, documentCounts, styleResolver = null) {
2905
3036
  };
2906
3037
  if (attrs.columnWidths) table.columnWidths = attrs.columnWidths;
2907
3038
  if (formatting && Object.keys(formatting).length > 0) table.formatting = formatting;
2908
- restoreTablePropertyChanges(table, attrs);
3039
+ restoreCarriedTableAttrs(table, attrs);
2909
3040
  return table;
2910
3041
  }
2911
3042
  /**
2912
- * Restore `w:tblPrChange` entries that PM carried opaquely on the table attrs
2913
- * (same rationale as the paragraph `_propertyChanges` attr): they must survive
2914
- * an edit so the saved DOCX keeps the tracked property-change history.
3043
+ * Restore what PM carried opaquely on the table attrs, on both paths out of
3044
+ * {@link convertPMTable}.
3045
+ *
3046
+ * `w:tblPrChange` (same rationale as the paragraph `_propertyChanges` attr)
3047
+ * must survive an edit so the saved DOCX keeps the tracked property-change
3048
+ * history, and the child sink must survive it so the markup the table held
3049
+ * beside its rows comes back between the same two.
2915
3050
  */
2916
- function restoreTablePropertyChanges(table, attrs) {
3051
+ function restoreCarriedTableAttrs(table, attrs) {
2917
3052
  if (Array.isArray(attrs.tblPrChange) && attrs.tblPrChange.length > 0) table.propertyChanges = [...attrs.tblPrChange];
3053
+ if (attrs._bookmarks && attrs._bookmarks.length > 0) table.bookmarks = attrs._bookmarks;
3054
+ if (hasSinkChildren(attrs._preserved)) table.preserved = attrs._preserved;
2918
3055
  }
2919
3056
  function convertPMTableRows(node, documentCounts, styleResolver = null) {
2920
3057
  const rows = [];
@@ -3025,10 +3162,15 @@ function convertPMTableRow(node, documentCounts, activeVerticalMerges, styleReso
3025
3162
  }
3026
3163
  };
3027
3164
  node.forEach((cellNode) => {
3028
- appendActiveVerticalMerges();
3029
3165
  if (cellNode.type.name === "tableCell" || cellNode.type.name === "tableHeader") {
3030
3166
  const cellAttrs = expectTableCellAttrs(cellNode);
3031
3167
  const colspan = Math.max(cellAttrs.colspan, 1);
3168
+ if (cellAttrs._omittedGridSlot) {
3169
+ if (!(cellNode.childCount === 1 && cellNode.child(0).type.name === "paragraph" && cellNode.child(0).content.size === 0)) panic("An omitted table grid slot acquired authored content");
3170
+ gridColumn += colspan;
3171
+ return;
3172
+ }
3173
+ appendActiveVerticalMerges();
3032
3174
  cells.push(convertPMTableCell(cellNode, documentCounts, styleResolver));
3033
3175
  if (cellAttrs.rowspan > 1) {
3034
3176
  const continuationCells = cellAttrs._docxVMergeContinuationCells !== void 0 && cellAttrs._docxVMergeContinuationCells !== null ? restoreTableCellsWithParagraphPropertySources(decodeTableCellParagraphSourcePayload(cellAttrs._docxVMergeContinuationCells)) : void 0;
@@ -3048,8 +3190,13 @@ function convertPMTableRow(node, documentCounts, activeVerticalMerges, styleReso
3048
3190
  };
3049
3191
  const rowFormatting = tableRowAttrsToFormatting(attrs);
3050
3192
  if (rowFormatting) row.formatting = rowFormatting;
3193
+ if (attrs._tablePropertyExceptions) row.tablePropertyExceptions = attrs._tablePropertyExceptions;
3194
+ if (Array.isArray(attrs.tblPrExChange) && attrs.tblPrExChange.length > 0) row.tablePropertyExceptionChanges = [...attrs.tblPrExChange];
3051
3195
  if (Array.isArray(attrs.trPrChange) && attrs.trPrChange.length > 0) row.propertyChanges = [...attrs.trPrChange];
3052
3196
  if (attrs._preservedAttributes && attrs._preservedAttributes.length > 0) row.preservedAttributes = attrs._preservedAttributes;
3197
+ if (attrs._bookmarks && attrs._bookmarks.length > 0) row.bookmarks = attrs._bookmarks;
3198
+ if (attrs.contentControls && attrs.contentControls.length > 0) row.contentControls = attrs.contentControls;
3199
+ if (hasSinkChildren(attrs._preserved)) row.preserved = attrs._preserved;
3053
3200
  if (attrs.trIns) row.structuralChange = {
3054
3201
  type: "tableRowInsertion",
3055
3202
  info: {
@@ -3106,11 +3253,11 @@ function tableRowAttrsToFormatting(attrs) {
3106
3253
  else delete result.heightRule;
3107
3254
  if (attrs.isHeader !== (orig.header ?? void 0)) if (attrs.isHeader) result.header = attrs.isHeader;
3108
3255
  else delete result.header;
3109
- if (attrs.hidden !== (orig.hidden ?? void 0)) if (attrs.hidden) result.hidden = attrs.hidden;
3110
- else delete result.hidden;
3256
+ if (attrs.hidden !== orig.hidden) if (attrs.hidden === void 0) delete result.hidden;
3257
+ else result.hidden = attrs.hidden;
3111
3258
  return result;
3112
3259
  }
3113
- if (!(attrs.height || attrs.isHeader || attrs.hidden)) return;
3260
+ if (!(attrs.height || attrs.isHeader || attrs.hidden !== void 0)) return;
3114
3261
  const f = {};
3115
3262
  if (attrs.height) f.height = {
3116
3263
  value: attrs.height,
@@ -3118,7 +3265,7 @@ function tableRowAttrsToFormatting(attrs) {
3118
3265
  };
3119
3266
  if (attrs.heightRule) f.heightRule = attrs.heightRule;
3120
3267
  if (attrs.isHeader) f.header = attrs.isHeader;
3121
- if (attrs.hidden) f.hidden = attrs.hidden;
3268
+ if (attrs.hidden !== void 0) f.hidden = attrs.hidden;
3122
3269
  return f;
3123
3270
  }
3124
3271
  /**
@@ -3148,6 +3295,9 @@ function convertPMTableCell(node, documentCounts, styleResolver = null) {
3148
3295
  xml: expectPreservedBlockAttrs(contentNode).xml
3149
3296
  });
3150
3297
  previousStandaloneTextBox = null;
3298
+ } else if (contentNode.type.name === "blockBookmarkBoundary") {
3299
+ content.push(blockBookmarkMarker(contentNode));
3300
+ previousStandaloneTextBox = null;
3151
3301
  }
3152
3302
  });
3153
3303
  removeUnresolvedTextBoxAnchors(content, textBoxAnchorMarkers);
@@ -3158,6 +3308,7 @@ function convertPMTableCell(node, documentCounts, styleResolver = null) {
3158
3308
  const cellFormatting = tableCellAttrsToFormatting(attrs);
3159
3309
  if (cellFormatting) cell.formatting = cellFormatting;
3160
3310
  if (Array.isArray(attrs.tcPrChange) && attrs.tcPrChange.length > 0) cell.propertyChanges = [...attrs.tcPrChange];
3311
+ if (attrs.contentControls && attrs.contentControls.length > 0) cell.contentControls = attrs.contentControls;
3161
3312
  if (attrs.cellMarker) {
3162
3313
  const info = {
3163
3314
  id: attrs.cellMarker.info.revisionId,
@@ -3193,11 +3344,8 @@ function tableCellAttrsToFormatting(attrs) {
3193
3344
  else delete result.gridSpan;
3194
3345
  if (attrs.rowspan > 1) result.vMerge = "restart";
3195
3346
  else if (result.vMerge === "restart" && !attrs._preserveVMergeRestart) delete result.vMerge;
3196
- const cellWidth = attrs.width;
3197
- if (typeof cellWidth === "number") result.width = {
3198
- value: cellWidth,
3199
- type: attrs.widthType ?? "dxa"
3200
- };
3347
+ const authoredWidth = attrs._authoredWidth;
3348
+ if (authoredWidth) result.width = authoredWidth;
3201
3349
  else delete result.width;
3202
3350
  if (attrs.verticalAlign !== (orig.verticalAlign ?? void 0)) if (attrs.verticalAlign) result.verticalAlign = attrs.verticalAlign;
3203
3351
  else delete result.verticalAlign;
@@ -3208,15 +3356,12 @@ function tableCellAttrsToFormatting(attrs) {
3208
3356
  else delete result.textDirection;
3209
3357
  return result;
3210
3358
  }
3211
- const cellWidth = attrs.width;
3212
- if (!(attrs.colspan > 1 || attrs.rowspan > 1 || typeof cellWidth === "number" || attrs.verticalAlign || backgroundChanged || attrs.borders || attrs.margins || attrs.textDirection)) return;
3359
+ const authoredWidth = attrs._authoredWidth;
3360
+ if (!(attrs.colspan > 1 || attrs.rowspan > 1 || authoredWidth !== void 0 || attrs.verticalAlign || backgroundChanged || attrs.borders || attrs.margins || attrs.textDirection)) return;
3213
3361
  const f = {};
3214
3362
  if (attrs.colspan > 1) f.gridSpan = attrs.colspan;
3215
3363
  if (attrs.rowspan > 1) f.vMerge = "restart";
3216
- if (typeof cellWidth === "number") f.width = {
3217
- value: cellWidth,
3218
- type: attrs.widthType ?? "dxa"
3219
- };
3364
+ if (authoredWidth) f.width = authoredWidth;
3220
3365
  if (attrs.verticalAlign) f.verticalAlign = attrs.verticalAlign;
3221
3366
  if (attrs.textDirection) f.textDirection = attrs.textDirection;
3222
3367
  if (backgroundChanged) f.shading = cellShadingFromAttrs(attrs);
@@ -3292,7 +3437,7 @@ function convertPMTextBox(node, styleResolver = null) {
3292
3437
  if (attrs.outlineStyle !== "none" && attrs.outlineWidth && attrs.outlineWidth > 0) {
3293
3438
  const tbOutline = {
3294
3439
  width: emuFromPixels(attrs.outlineWidth, "outlineWidth", authoredEmu, emuToStrokePixels),
3295
- style: normalizeShapeOutlineStyle(attrs.outlineStyle) ?? "solid"
3440
+ dash: normalizeShapeOutlineDash(attrs.outlineStyle) ?? "solid"
3296
3441
  };
3297
3442
  if (attrs.outlineColor) tbOutline.color = { rgb: attrs.outlineColor.replace("#", "") };
3298
3443
  shape.outline = tbOutline;
@@ -3301,6 +3446,8 @@ function convertPMTextBox(node, styleResolver = null) {
3301
3446
  if (wrap) shape.wrap = wrap;
3302
3447
  const position = imagePositionFromAttrs(attrs.position);
3303
3448
  if (position) shape.position = position;
3449
+ const anchor = restoredDrawingAnchor(attrs.anchor);
3450
+ if (anchor) shape.anchor = anchor;
3304
3451
  const run = {
3305
3452
  type: "run",
3306
3453
  content: [{