@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
@@ -2,6 +2,7 @@ import { htmlCommentEnd } from "../../../utils/htmlComments.js";
2
2
  import { stripXmlDeclarations } from "../../../utils/stripXmlDeclarations.js";
3
3
  import { readBookmarkBoundaryAttrs } from "../../bookmarkBoundaryAttrs.js";
4
4
  import { findInvalidBookmarkBoundaryIds } from "../../bookmarkBoundaryIntegrity.js";
5
+ import { readMoveRangeBoundaryAttrs } from "../../moveRangeBoundaryAttrs.js";
5
6
  import { Fragment, Slice } from "prosemirror-model";
6
7
  //#region src/prosemirror/extensions/features/pasteCleanup.ts
7
8
  /**
@@ -124,6 +125,8 @@ const MAX_EMPTY_SPAN_PASSES = 5;
124
125
  const INTERNAL_CLIPBOARD_ATTR_PATTERN = /\s+data-docx-internal-clipboard(?:="([^"]*)"|='([^']*)'|=([^\s>]+))?/gi;
125
126
  const TEXTBOX_ANCHOR_ATTR = /\s+data-docx-textbox-anchor(?:="[^"]*"|='[^']*')?/gi;
126
127
  const BOOKMARK_BOUNDARY_ATTR = /\s+data-docx-bookmark-(?:boundary|id|name|col-first|col-last)(?:="[^"]*"|='[^']*'|=[^\s>]+)?/gi;
128
+ const RANGE_ANCHOR_ATTR = /\s+data-docx-range-anchor(?:="[^"]*"|='[^']*'|=[^\s>]+)?/gi;
129
+ const MOVE_RANGE_BOUNDARY_ATTR = /\s+data-docx-move-range-boundary(?:="[^"]*"|='[^']*'|=[^\s>]+)?/gi;
127
130
  const STRUCTURED_FIELD_ATTR = /\s+data-field-structured(?:="[^"]*"|='[^']*'|=[^\s>]+)?/gi;
128
131
  /**
129
132
  * Treat reconstruction attributes as internal only when the HTML carries the
@@ -144,6 +147,10 @@ function stripForeignBookmarkBoundaries(html, internal) {
144
147
  if (internal) return html;
145
148
  return html.replace(BOOKMARK_BOUNDARY_ATTR, "");
146
149
  }
150
+ function stripForeignRangeCarriers(html, internal) {
151
+ if (internal) return html;
152
+ return html.replace(RANGE_ANCHOR_ATTR, "").replace(MOVE_RANGE_BOUNDARY_ATTR, "");
153
+ }
147
154
  function stripForeignStructuredFields(html, internal) {
148
155
  if (internal) return html;
149
156
  return html.replace(STRUCTURED_FIELD_ATTR, "");
@@ -158,7 +165,7 @@ function stripEmptySpans(html, preserveInternalAtoms) {
158
165
  let current = html;
159
166
  for (let pass = 0; pass < MAX_EMPTY_SPAN_PASSES; pass++) {
160
167
  const next = current.replace(EMPTY_SPAN, (span) => {
161
- if (preserveInternalAtoms && /\bdata-docx-(?:bookmark-boundary|textbox-anchor)\s*=/i.test(span)) return span;
168
+ if (preserveInternalAtoms && /\bdata-docx-(?:bookmark-boundary|textbox-anchor|range-anchor|move-range-boundary)\s*=/i.test(span)) return span;
162
169
  return "";
163
170
  });
164
171
  if (next === current) break;
@@ -179,6 +186,7 @@ function cleanPastedHtml(html, options = {}) {
179
186
  cleaned = stripEmptySpans(cleaned, internal);
180
187
  cleaned = stripForeignTextBoxAnchors(cleaned, internal);
181
188
  cleaned = stripForeignBookmarkBoundaries(cleaned, internal);
189
+ cleaned = stripForeignRangeCarriers(cleaned, internal);
182
190
  cleaned = stripForeignStructuredFields(cleaned, internal);
183
191
  cleaned = cleaned.replace(INTERNAL_CLIPBOARD_ATTR_PATTERN, "");
184
192
  return cleaned.trim();
@@ -218,5 +226,51 @@ function removeUnpairedBookmarkBoundaries(slice) {
218
226
  };
219
227
  return new Slice(filterFragment(slice.content), slice.openStart, slice.openEnd);
220
228
  }
229
+ const moveRangeKey = (marker) => {
230
+ return `${marker.type.startsWith("moveFrom") ? "moveFrom" : "moveTo"}:${marker.id}`;
231
+ };
232
+ const moveRangeBoundaryType = (marker) => marker.type.endsWith("Start") ? "start" : "end";
233
+ /** Remove incomplete, duplicate, or reversed tracked-move pairs at copied slice edges. */
234
+ function removeUnpairedMoveRangeBoundaries(slice) {
235
+ const summaries = /* @__PURE__ */ new Map();
236
+ const malformedNodes = /* @__PURE__ */ new Set();
237
+ let boundaryIndex = 0;
238
+ slice.content.descendants((node) => {
239
+ if (node.type.name !== "moveRangeBoundary") return true;
240
+ const result = readMoveRangeBoundaryAttrs(node);
241
+ if (!result.ok) {
242
+ malformedNodes.add(node);
243
+ return false;
244
+ }
245
+ const key = moveRangeKey(result.value);
246
+ const summary = summaries.get(key) ?? {
247
+ startPositions: [],
248
+ endPositions: []
249
+ };
250
+ summary[moveRangeBoundaryType(result.value) === "start" ? "startPositions" : "endPositions"].push(boundaryIndex);
251
+ summaries.set(key, summary);
252
+ boundaryIndex += 1;
253
+ return false;
254
+ });
255
+ const invalidKeys = /* @__PURE__ */ new Set();
256
+ for (const [key, { startPositions, endPositions }] of summaries) {
257
+ const start = startPositions.at(0);
258
+ const end = endPositions.at(0);
259
+ if (startPositions.length !== 1 || endPositions.length !== 1 || start === void 0 || end === void 0 || start >= end) invalidKeys.add(key);
260
+ }
261
+ const filterFragment = (fragment) => {
262
+ const children = [];
263
+ fragment.forEach((node) => {
264
+ if (node.type.name === "moveRangeBoundary") {
265
+ const result = readMoveRangeBoundaryAttrs(node);
266
+ if (result.ok && !malformedNodes.has(node) && !invalidKeys.has(moveRangeKey(result.value))) children.push(node);
267
+ return;
268
+ }
269
+ children.push(node.childCount === 0 ? node : node.copy(filterFragment(node.content)));
270
+ });
271
+ return Fragment.fromArray(children);
272
+ };
273
+ return new Slice(filterFragment(slice.content), slice.openStart, slice.openEnd);
274
+ }
221
275
  //#endregion
222
- export { cleanPastedHtml, removeUnpairedBookmarkBoundaries };
276
+ export { cleanPastedHtml, removeUnpairedBookmarkBoundaries, removeUnpairedMoveRangeBoundaries };
@@ -1,5 +1,6 @@
1
- import { isHeadingOutlineLevel } from "../../../docx/builtInStyles.js";
1
+ import { readOutlineLevelAttr } from "../../outlineLevelAttr.js";
2
2
  import { getDocumentBuiltInStyles, getDocumentStyleResolver } from "../../plugins/documentStyles.js";
3
+ import { headingLevelOf } from "@stll/docx-core/model";
3
4
  import { Fragment, Slice } from "prosemirror-model";
4
5
  //#region src/prosemirror/extensions/features/pastedHeadingStyles.ts
5
6
  /**
@@ -39,11 +40,11 @@ const nearestHeadingStyleId = (outlineLevel, styles) => {
39
40
  const retargetedStyleId = (node, view) => {
40
41
  const styleId = node.attrs["styleId"];
41
42
  if (typeof styleId !== "string") return;
42
- const outlineLevel = node.attrs["outlineLevel"];
43
- if (typeof outlineLevel !== "number" || !isHeadingOutlineLevel(outlineLevel)) return;
43
+ const headingLevel = headingLevelOf(readOutlineLevelAttr(node.attrs["outlineLevel"]));
44
+ if (headingLevel === void 0) return;
44
45
  const resolver = getDocumentStyleResolver(view.state);
45
46
  if (resolver === null || resolver.getStyle(styleId) !== void 0) return;
46
- const target = nearestHeadingStyleId(outlineLevel, getDocumentBuiltInStyles(view.state));
47
+ const target = nearestHeadingStyleId(headingLevel, getDocumentBuiltInStyles(view.state));
47
48
  return target === styleId ? void 0 : target;
48
49
  };
49
50
  const retargetFragment = (fragment, view) => {
@@ -28,7 +28,7 @@ declare const MARK_EXTENSIONS: {
28
28
  readonly textEffect: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
29
29
  readonly runFormattingOverride: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
30
30
  readonly characterStyle: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
31
- readonly pageBreakRunOwner: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
31
+ readonly runIdentity: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
32
32
  readonly comment: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
33
33
  readonly insertion: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
34
34
  readonly deletion: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
@@ -37,5 +37,29 @@ declare const MARK_EXTENSIONS: {
37
37
  };
38
38
  /** A mark the editor schema declares. */
39
39
  type SchemaMarkName = keyof typeof MARK_EXTENSIONS;
40
+ /**
41
+ * Outermost first: the order the editor registers marks in, which is the order
42
+ * it nests their DOM elements in.
43
+ *
44
+ * Five of these marks are containers on the save leg as well, and their
45
+ * relative order is that leg's rather than a choice made here.
46
+ * `extractParagraphContent` opens a comment range around everything a leaf
47
+ * produces (it flushes the open run and hyperlink and drops the tracked wrapper
48
+ * before pushing the marker: `fromProseDoc.ts:2359-2369`), then the revision
49
+ * wrapper (`fromProseDoc.ts:2530`), then the wrapper stack inside that revision
50
+ * (`nestInlineWrapperGroups`, `fromProseDoc.ts:2200`), then the hyperlink and
51
+ * the runs it holds (`fromProseDoc.ts:2567`). So the save writes
52
+ * `w:commentRangeStart … w:ins > w:bdo > w:hyperlink > w:r`, and the editor DOM
53
+ * nests `span.docx-comment > span.docx-insertion > bdo > a`.
54
+ * `markNestingOrder.test.ts` holds the two legs to each other.
55
+ *
56
+ * `runIdentity` is the fifth: `w:r` is the element it names, and it is the
57
+ * innermost element that leg emits.
58
+ *
59
+ * Every other mark is a run property or run content: it has no element of its
60
+ * own in OOXML, so the save leg ranks it against nothing and its place here is
61
+ * a presentation decision.
62
+ */
63
+ declare const MARK_NESTING_ORDER: readonly ["bold", "italic", "underline", "strike", "textColor", "runShading", "highlight", "fontSize", "fontFamily", "language", "superscript", "subscript", "allCaps", "smallCaps", "footnoteRef", "characterSpacing", "emboss", "imprint", "hidden", "textShadow", "emphasisMark", "textOutline", "rtl", "textEffect", "runFormattingOverride", "characterStyle", "comment", "insertion", "deletion", "inlineWrapper", "hyperlink", "runPropertyChange", "runIdentity"];
40
64
  //#endregion
41
- export { MARK_EXTENSIONS, SchemaMarkName };
65
+ export { MARK_EXTENSIONS, MARK_NESTING_ORDER, SchemaMarkName };
@@ -12,9 +12,9 @@ import { HyperlinkExtension } from "./marks/HyperlinkExtension.js";
12
12
  import { InlineWrapperExtension } from "./marks/InlineWrapperExtension.js";
13
13
  import { ItalicExtension } from "./marks/ItalicExtension.js";
14
14
  import { LanguageExtension } from "./marks/LanguageExtension.js";
15
- import { PageBreakRunOwnerExtension } from "./marks/PageBreakRunOwnerExtension.js";
16
15
  import { RtlExtension } from "./marks/RtlExtension.js";
17
16
  import { RunFormattingOverrideExtension } from "./marks/RunFormattingOverrideExtension.js";
17
+ import { RunIdentityExtension } from "./marks/RunIdentityExtension.js";
18
18
  import { RunShadingExtension } from "./marks/RunShadingExtension.js";
19
19
  import { SmallCapsExtension } from "./marks/SmallCapsExtension.js";
20
20
  import { StrikeExtension } from "./marks/StrikeExtension.js";
@@ -27,14 +27,17 @@ import { DeletionExtension, InsertionExtension, RunPropertyChangeExtension } fro
27
27
  import { UnderlineExtension } from "./marks/UnderlineExtension.js";
28
28
  //#region src/prosemirror/extensions/markRegistry.ts
29
29
  /**
30
- * Every mark the editor schema declares, in registration order.
30
+ * Every mark the editor schema declares, and the order they nest in.
31
31
  *
32
- * Registration order is DOM nesting order: a mark registered later is the
33
- * inner span. `StarterKit` builds the schema from this record and from nothing
34
- * else, so `SchemaMarkName` is the set of marks that exist rather than a list
35
- * beside it — a table that must decide something per mark (what the painter
36
- * does with it) can be checked total against this union, and a mark added
37
- * without that decision does not compile.
32
+ * `StarterKit` builds the schema from this record and from nothing else, so
33
+ * `SchemaMarkName` is the set of marks that exist rather than a list beside it
34
+ * — a table that must decide something per mark (what the painter does with
35
+ * it) can be checked total against this union, and a mark added without that
36
+ * decision does not compile.
37
+ *
38
+ * The record answers which marks exist and how each is built; its key order
39
+ * answers nothing. `MARK_NESTING_ORDER` is the registration order, and
40
+ * registration order is DOM nesting order.
38
41
  */
39
42
  const MARK_EXTENSIONS = {
40
43
  bold: BoldExtension,
@@ -64,12 +67,72 @@ const MARK_EXTENSIONS = {
64
67
  textEffect: TextEffectExtension,
65
68
  runFormattingOverride: RunFormattingOverrideExtension,
66
69
  characterStyle: CharacterStyleExtension,
67
- pageBreakRunOwner: PageBreakRunOwnerExtension,
70
+ runIdentity: RunIdentityExtension,
68
71
  comment: CommentExtension,
69
72
  insertion: InsertionExtension,
70
73
  deletion: DeletionExtension,
71
74
  runPropertyChange: RunPropertyChangeExtension,
72
75
  inlineWrapper: InlineWrapperExtension
73
76
  };
77
+ /** The order, rejected unless it names every mark; a repeat is the test's. */
78
+ const markNestingOrder = (names) => names;
79
+ /**
80
+ * Outermost first: the order the editor registers marks in, which is the order
81
+ * it nests their DOM elements in.
82
+ *
83
+ * Five of these marks are containers on the save leg as well, and their
84
+ * relative order is that leg's rather than a choice made here.
85
+ * `extractParagraphContent` opens a comment range around everything a leaf
86
+ * produces (it flushes the open run and hyperlink and drops the tracked wrapper
87
+ * before pushing the marker: `fromProseDoc.ts:2359-2369`), then the revision
88
+ * wrapper (`fromProseDoc.ts:2530`), then the wrapper stack inside that revision
89
+ * (`nestInlineWrapperGroups`, `fromProseDoc.ts:2200`), then the hyperlink and
90
+ * the runs it holds (`fromProseDoc.ts:2567`). So the save writes
91
+ * `w:commentRangeStart … w:ins > w:bdo > w:hyperlink > w:r`, and the editor DOM
92
+ * nests `span.docx-comment > span.docx-insertion > bdo > a`.
93
+ * `markNestingOrder.test.ts` holds the two legs to each other.
94
+ *
95
+ * `runIdentity` is the fifth: `w:r` is the element it names, and it is the
96
+ * innermost element that leg emits.
97
+ *
98
+ * Every other mark is a run property or run content: it has no element of its
99
+ * own in OOXML, so the save leg ranks it against nothing and its place here is
100
+ * a presentation decision.
101
+ */
102
+ const MARK_NESTING_ORDER = markNestingOrder([
103
+ "bold",
104
+ "italic",
105
+ "underline",
106
+ "strike",
107
+ "textColor",
108
+ "runShading",
109
+ "highlight",
110
+ "fontSize",
111
+ "fontFamily",
112
+ "language",
113
+ "superscript",
114
+ "subscript",
115
+ "allCaps",
116
+ "smallCaps",
117
+ "footnoteRef",
118
+ "characterSpacing",
119
+ "emboss",
120
+ "imprint",
121
+ "hidden",
122
+ "textShadow",
123
+ "emphasisMark",
124
+ "textOutline",
125
+ "rtl",
126
+ "textEffect",
127
+ "runFormattingOverride",
128
+ "characterStyle",
129
+ "comment",
130
+ "insertion",
131
+ "deletion",
132
+ "inlineWrapper",
133
+ "hyperlink",
134
+ "runPropertyChange",
135
+ "runIdentity"
136
+ ]);
74
137
  //#endregion
75
- export { MARK_EXTENSIONS };
138
+ export { MARK_EXTENSIONS, MARK_NESTING_ORDER };
@@ -16,11 +16,19 @@ import { panic } from "better-result";
16
16
  * extend the wrapper over text the author wrote outside it.
17
17
  */
18
18
  const INLINE_WRAPPER_MARK_NAME = "inlineWrapper";
19
+ /** What a tagged layer's element name is spelled as on the rendered span. */
20
+ const TAGGED_ELEMENT_ATTRIBUTES = {
21
+ smartTag: "data-smart-tag-element",
22
+ customXml: "data-custom-xml-element"
23
+ };
19
24
  /**
20
25
  * How one layer is spelled in HTML.
21
26
  *
22
27
  * `w:bdo` is `unicode-bidi: bidi-override`, which HTML gives an element of its
23
28
  * own; `w:dir` is `unicode-bidi: embed`, which a `dir`-carrying span states.
29
+ * A smart tag and a custom-XML wrapper say nothing about layout, so they are a
30
+ * passthrough `<span>` that names the tagged element for a stylesheet or a
31
+ * host that wants to show it; the stack attribute is what carries them back.
24
32
  */
25
33
  const layerElement = (layer, attributes) => {
26
34
  switch (layer.kind) {
@@ -31,9 +39,15 @@ const layerElement = (layer, attributes) => {
31
39
  attributes,
32
40
  0
33
41
  ];
34
- default:
35
- layer.kind;
36
- panic(`Unspelled inline wrapper layer: ${JSON.stringify(layer)}`);
42
+ case "smartTag":
43
+ case "customXml":
44
+ attributes[TAGGED_ELEMENT_ATTRIBUTES[layer.kind]] = layer.element;
45
+ return [
46
+ "span",
47
+ attributes,
48
+ 0
49
+ ];
50
+ default: panic(`Unspelled inline wrapper layer: ${JSON.stringify(layer)}`);
37
51
  }
38
52
  };
39
53
  const InlineWrapperExtension = createMarkExtension({
@@ -0,0 +1,26 @@
1
+ import { MarkExtension } from "../types.js";
2
+ //#region src/prosemirror/extensions/marks/RunIdentityExtension.d.ts
3
+ /**
4
+ * Editor-side identity for one authored `w:r`, and the payload that element
5
+ * carried which no formatting mark holds.
6
+ *
7
+ * Ordinary formatting marks cannot tell two adjacent source runs with
8
+ * identical properties apart, so the save leg would fold them into one and
9
+ * discard whichever record it did not keep. This mark is what keeps them
10
+ * apart: it is in `getMarksKey`, so a change of identity is a run boundary,
11
+ * and `joinsOwnedSourceRun` rejoins the leaves a page break cut out of one
12
+ * authored run.
13
+ *
14
+ * `inclusive: false` settles the edges. The interior is settled by the strip
15
+ * below: ProseMirror's stored marks at a position inside a span include every
16
+ * mark of the preceding character, so text typed inside an authored run would
17
+ * otherwise ride that run's `w:rsidR` — a claim about which editing session
18
+ * wrote it. folio cannot register a session (`settings.xml`'s `w:rsids` is
19
+ * copied through on every repack, and no save path mints one), so it must
20
+ * never write a session id it did not read. Typed text becomes its own run
21
+ * with no attributes instead, and `w:rsidRDefault` on the parent `w:p`
22
+ * supplies the session the format itself says such a run belongs to.
23
+ */
24
+ declare const RunIdentityExtension: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
25
+ //#endregion
26
+ export { RunIdentityExtension };
@@ -0,0 +1,134 @@
1
+ import { expectRunIdentityMarkAttrs } from "../../attrs/index.js";
2
+ import { RUN_IDENTITY_ATTRIBUTE, RUN_IDENTITY_MARK_NAME, runIdentityAttrs } from "../../runIdentity.js";
3
+ import { createMarkExtension } from "../create.js";
4
+ import { Plugin, PluginKey } from "prosemirror-state";
5
+ //#region src/prosemirror/extensions/marks/RunIdentityExtension.ts
6
+ /**
7
+ * Editor-side identity for one authored `w:r`, and the payload that element
8
+ * carried which no formatting mark holds.
9
+ *
10
+ * Ordinary formatting marks cannot tell two adjacent source runs with
11
+ * identical properties apart, so the save leg would fold them into one and
12
+ * discard whichever record it did not keep. This mark is what keeps them
13
+ * apart: it is in `getMarksKey`, so a change of identity is a run boundary,
14
+ * and `joinsOwnedSourceRun` rejoins the leaves a page break cut out of one
15
+ * authored run.
16
+ *
17
+ * `inclusive: false` settles the edges. The interior is settled by the strip
18
+ * below: ProseMirror's stored marks at a position inside a span include every
19
+ * mark of the preceding character, so text typed inside an authored run would
20
+ * otherwise ride that run's `w:rsidR` — a claim about which editing session
21
+ * wrote it. folio cannot register a session (`settings.xml`'s `w:rsids` is
22
+ * copied through on every repack, and no save path mints one), so it must
23
+ * never write a session id it did not read. Typed text becomes its own run
24
+ * with no attributes instead, and `w:rsidRDefault` on the parent `w:p`
25
+ * supplies the session the format itself says such a run belongs to.
26
+ */
27
+ const CANONICAL_RUN_IDENTITY_ID = /^(?:0|[1-9]\d*)$/u;
28
+ const runIdentityStripKey = new PluginKey("runIdentityStrip");
29
+ /**
30
+ * Every range `transactions` inserted, in the document they produced.
31
+ *
32
+ * A step map reports each replacement as an old span and the new span it
33
+ * became; a new span longer than nothing is content the step put there, which
34
+ * is exactly the text that may not claim an authored run. Each range is then
35
+ * carried through the steps that followed it — the rest of its own
36
+ * transaction, then every later one — so a batch applied together reports
37
+ * positions in the document this hook is looking at rather than in an
38
+ * intermediate one.
39
+ */
40
+ const insertedRanges = (transactions) => {
41
+ const ranges = [];
42
+ for (const [transactionIndex, transaction] of transactions.entries()) {
43
+ const later = transactions.slice(transactionIndex + 1);
44
+ const carryForward = (pos, bias) => {
45
+ let mapped = pos;
46
+ for (const next of later) mapped = next.mapping.map(mapped, bias);
47
+ return mapped;
48
+ };
49
+ transaction.mapping.maps.forEach((stepMap, stepIndex) => {
50
+ const rest = transaction.mapping.slice(stepIndex + 1);
51
+ stepMap.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
52
+ if (newEnd <= newStart) return;
53
+ ranges.push({
54
+ from: carryForward(rest.map(newStart, -1), -1),
55
+ to: carryForward(rest.map(newEnd, 1), 1)
56
+ });
57
+ });
58
+ });
59
+ }
60
+ return ranges;
61
+ };
62
+ /**
63
+ * Remove `runIdentity` from what a transaction inserted.
64
+ *
65
+ * Runs after the edit rather than in front of it because an insertion's marks
66
+ * are decided by ProseMirror from the text around it, and there is no hook
67
+ * that sees every route to that decision: typing, paste, a command and a
68
+ * collaborative apply all arrive here and nowhere else in common.
69
+ */
70
+ const createRunIdentityStripPlugin = () => new Plugin({
71
+ key: runIdentityStripKey,
72
+ appendTransaction(transactions, _oldState, newState) {
73
+ if (!transactions.some((transaction) => transaction.docChanged)) return null;
74
+ const markType = newState.schema.marks[RUN_IDENTITY_MARK_NAME];
75
+ if (markType === void 0) return null;
76
+ const ranges = insertedRanges(transactions);
77
+ if (ranges.length === 0) return null;
78
+ const tr = newState.tr;
79
+ const stripRange = ({ from, to }) => {
80
+ const clampedTo = Math.min(to, newState.doc.content.size);
81
+ const clampedFrom = Math.min(from, clampedTo);
82
+ if (clampedFrom === clampedTo) return false;
83
+ let rangeStripped = false;
84
+ newState.doc.nodesBetween(clampedFrom, clampedTo, (node, pos) => {
85
+ if (!node.isInline || !markType.isInSet(node.marks)) return true;
86
+ tr.removeMark(Math.max(pos, clampedFrom), Math.min(pos + node.nodeSize, clampedTo), markType);
87
+ rangeStripped = true;
88
+ return true;
89
+ });
90
+ return rangeStripped;
91
+ };
92
+ let stripped = false;
93
+ for (const range of ranges) stripped = stripRange(range) || stripped;
94
+ if (!stripped) return null;
95
+ tr.setMeta("addToHistory", false);
96
+ tr.setMeta(runIdentityStripKey, "stripped");
97
+ if (newState.storedMarks !== null) tr.setStoredMarks(newState.storedMarks.filter((mark) => mark.type !== markType));
98
+ return tr;
99
+ }
100
+ });
101
+ const RunIdentityExtension = createMarkExtension({
102
+ name: RUN_IDENTITY_MARK_NAME,
103
+ schemaMarkName: RUN_IDENTITY_MARK_NAME,
104
+ markSpec: {
105
+ attrs: {
106
+ id: {},
107
+ preservedAttributes: { default: null },
108
+ preserved: { default: null }
109
+ },
110
+ inclusive: false,
111
+ parseDOM: [{
112
+ tag: `span[${RUN_IDENTITY_ATTRIBUTE}]`,
113
+ getAttrs(dom) {
114
+ const rawId = dom.dataset["docxRunIdentity"];
115
+ if (rawId === void 0 || !CANONICAL_RUN_IDENTITY_ID.test(rawId)) return false;
116
+ const id = Number(rawId);
117
+ return Number.isSafeInteger(id) ? runIdentityAttrs(id) : false;
118
+ }
119
+ }],
120
+ toDOM(mark) {
121
+ const { id } = expectRunIdentityMarkAttrs(mark);
122
+ return [
123
+ "span",
124
+ { [RUN_IDENTITY_ATTRIBUTE]: String(id) },
125
+ 0
126
+ ];
127
+ }
128
+ },
129
+ onSchemaReady() {
130
+ return { plugins: [createRunIdentityStripPlugin()] };
131
+ }
132
+ });
133
+ //#endregion
134
+ export { RunIdentityExtension };
@@ -100,7 +100,8 @@ const DeletionExtension = createMarkExtension({
100
100
  moveKind: { default: null },
101
101
  initials: { default: null },
102
102
  provenance: { default: "user" },
103
- suggestionId: { default: null }
103
+ suggestionId: { default: null },
104
+ _historicalFormatting: { default: null }
104
105
  },
105
106
  inclusive: false,
106
107
  parseDOM: [{
@@ -1,3 +1,4 @@
1
+ import { PLAIN_UNDERLINE, underlineDecorationCss, underlineStyleFromCssDecoration } from "../../../utils/formatToStyle.js";
1
2
  import { expectUnderlineMarkAttrs } from "../../attrs/index.js";
2
3
  import { createMarkExtension } from "../create.js";
3
4
  import { setMark, toggleUnderlineMark } from "./markUtils.js";
@@ -6,39 +7,32 @@ import { panic } from "better-result";
6
7
  /**
7
8
  * Underline Mark Extension
8
9
  */
10
+ /** `w:u w:val="none"`: the token that cancels an inherited underline. */
11
+ const NO_UNDERLINE = "none";
9
12
  const UnderlineExtension = createMarkExtension({
10
13
  name: "underline",
11
14
  schemaMarkName: "underline",
12
15
  markSpec: {
13
16
  attrs: {
14
- style: { default: "single" },
17
+ style: { default: PLAIN_UNDERLINE },
15
18
  color: { default: null }
16
19
  },
17
20
  parseDOM: [{ tag: "u" }, {
18
21
  style: "text-decoration",
19
22
  getAttrs: (value) => {
20
- if (value.includes("underline")) return {};
21
- return value.includes("none") ? { style: "none" } : false;
23
+ if (value.includes("underline")) return { style: underlineStyleFromCssDecoration(value) };
24
+ return value.includes(NO_UNDERLINE) ? { style: NO_UNDERLINE } : false;
22
25
  }
23
26
  }],
24
27
  toDOM(mark) {
25
- const attrs = expectUnderlineMarkAttrs(mark);
26
- const style = attrs.style;
27
- const colorRgb = attrs.color?.rgb;
28
- const cssStyle = [`text-decoration: ${style === "none" ? "none" : "underline"}`];
29
- if (style && style !== "single" && style !== "none") {
30
- const cssDecorationStyle = {
31
- double: "double",
32
- dotted: "dotted",
33
- dash: "dashed",
34
- wave: "wavy"
35
- }[style];
36
- if (cssDecorationStyle) cssStyle.push(`text-decoration-style: ${cssDecorationStyle}`);
37
- }
38
- if (colorRgb) cssStyle.push(`text-decoration-color: #${colorRgb}`);
28
+ const { style = PLAIN_UNDERLINE, color } = expectUnderlineMarkAttrs(mark);
29
+ const { decorationStyle, decorationThickness } = underlineDecorationCss(style);
30
+ const declarations = [`text-decoration: ${decorationStyle === void 0 ? NO_UNDERLINE : `underline ${decorationStyle}`}`];
31
+ if (decorationThickness !== void 0) declarations.push(`text-decoration-thickness: ${decorationThickness}`);
32
+ if (color?.rgb) declarations.push(`text-decoration-color: #${color.rgb}`);
39
33
  return [
40
34
  "span",
41
- { style: cssStyle.join("; ") },
35
+ { style: declarations.join("; ") },
42
36
  0
43
37
  ];
44
38
  }
@@ -7,6 +7,7 @@ import { selectRunFormattingCarrierRepresentations } from "../../runFormattingIn
7
7
  import { hasRunFormattingOverrideAttrs } from "../../runFormattingProvenance.js";
8
8
  import { COMPLEX_SCRIPT_RUN_PROPERTY_KEYS } from "../../schema/marks.js";
9
9
  import { applyRunFormattingOverrideMark, buildRunFormattingOverrideAttrs } from "./RunFormattingOverrideExtension.js";
10
+ import { readThemeColor } from "@stll/docx-core/model";
10
11
  import { toggleMark } from "prosemirror-commands";
11
12
  //#region src/prosemirror/extensions/marks/markUtils.ts
12
13
  const isFontTheme = (value) => value !== void 0 && FONT_THEME_VALUES.some((theme) => theme === value);
@@ -42,7 +43,7 @@ function marksToTextFormatting(marks) {
42
43
  break;
43
44
  case "textColor": {
44
45
  const colorRgb = mark.attrs["rgb"] !== null && mark.attrs["rgb"] !== void 0 ? String(mark.attrs["rgb"]) : void 0;
45
- const colorTheme = mark.attrs["themeColor"] !== null && mark.attrs["themeColor"] !== void 0 ? String(mark.attrs["themeColor"]) : void 0;
46
+ const colorTheme = mark.attrs["themeColor"] !== null && mark.attrs["themeColor"] !== void 0 ? readThemeColor(String(mark.attrs["themeColor"])) : void 0;
46
47
  const colorTint = mark.attrs["themeTint"] !== null && mark.attrs["themeTint"] !== void 0 ? String(mark.attrs["themeTint"]) : void 0;
47
48
  const colorShade = mark.attrs["themeShade"] !== null && mark.attrs["themeShade"] !== void 0 ? String(mark.attrs["themeShade"]) : void 0;
48
49
  formatting.color = {
@@ -0,0 +1,29 @@
1
+ import { NodeExtension } from "../types.js";
2
+ //#region src/prosemirror/extensions/nodes/BlockBookmarkBoundaryExtension.d.ts
3
+ /**
4
+ * A bookmark boundary that stands between two blocks.
5
+ *
6
+ * The block-level twin of `bookmarkBoundary`. `CT_Body`, `CT_Tc` and
7
+ * `CT_SdtContentBlock` declare `w:bookmarkStart`/`w:bookmarkEnd` beside their
8
+ * paragraphs and tables, and Word writes them there whenever the selection was
9
+ * whole blocks: `_GoBack` after an edit, a table-of-contents range around the
10
+ * headings it lists. ProseMirror decides inline or block per node type, so the
11
+ * inline atom cannot also sit here and this is its own node — with the same
12
+ * attributes, read by the same reader, so the two levels cannot describe a
13
+ * bookmark differently.
14
+ *
15
+ * **Position is structure, not an attribute**, for the reason
16
+ * `PreservedBlockExtension` gives: the node sits between the same two blocks it
17
+ * sat between in the source and ProseMirror's own mapping keeps it there, so an
18
+ * edit inside the range cannot change what the range covers.
19
+ *
20
+ * Pairing is owned one level up. A bookmark may open at block level and close
21
+ * inside a paragraph, which is the commoner shape in real documents, so the
22
+ * integrity pass in `BookmarkBoundaryExtension` reads both node types together;
23
+ * a rule enforced here would see half of each such pair and delete it.
24
+ */
25
+ /** The node name, for callers asking what a block container holds. */
26
+ declare const BLOCK_BOOKMARK_BOUNDARY_NODE_NAME = "blockBookmarkBoundary";
27
+ declare const BlockBookmarkBoundaryExtension: (options?: Partial<Record<string, unknown>> | undefined) => NodeExtension;
28
+ //#endregion
29
+ export { BLOCK_BOOKMARK_BOUNDARY_NODE_NAME, BlockBookmarkBoundaryExtension };
@@ -0,0 +1,46 @@
1
+ import { createNodeExtension } from "../create.js";
2
+ import { bookmarkBoundaryAttrSpec, bookmarkBoundaryDomAttributes, parseBookmarkBoundaryDom } from "./bookmarkBoundaryDom.js";
3
+ //#region src/prosemirror/extensions/nodes/BlockBookmarkBoundaryExtension.ts
4
+ /**
5
+ * A bookmark boundary that stands between two blocks.
6
+ *
7
+ * The block-level twin of `bookmarkBoundary`. `CT_Body`, `CT_Tc` and
8
+ * `CT_SdtContentBlock` declare `w:bookmarkStart`/`w:bookmarkEnd` beside their
9
+ * paragraphs and tables, and Word writes them there whenever the selection was
10
+ * whole blocks: `_GoBack` after an edit, a table-of-contents range around the
11
+ * headings it lists. ProseMirror decides inline or block per node type, so the
12
+ * inline atom cannot also sit here and this is its own node — with the same
13
+ * attributes, read by the same reader, so the two levels cannot describe a
14
+ * bookmark differently.
15
+ *
16
+ * **Position is structure, not an attribute**, for the reason
17
+ * `PreservedBlockExtension` gives: the node sits between the same two blocks it
18
+ * sat between in the source and ProseMirror's own mapping keeps it there, so an
19
+ * edit inside the range cannot change what the range covers.
20
+ *
21
+ * Pairing is owned one level up. A bookmark may open at block level and close
22
+ * inside a paragraph, which is the commoner shape in real documents, so the
23
+ * integrity pass in `BookmarkBoundaryExtension` reads both node types together;
24
+ * a rule enforced here would see half of each such pair and delete it.
25
+ */
26
+ /** The node name, for callers asking what a block container holds. */
27
+ const BLOCK_BOOKMARK_BOUNDARY_NODE_NAME = "blockBookmarkBoundary";
28
+ const BlockBookmarkBoundaryExtension = createNodeExtension({
29
+ name: BLOCK_BOOKMARK_BOUNDARY_NODE_NAME,
30
+ schemaNodeName: BLOCK_BOOKMARK_BOUNDARY_NODE_NAME,
31
+ nodeSpec: {
32
+ group: "block",
33
+ atom: true,
34
+ selectable: false,
35
+ attrs: bookmarkBoundaryAttrSpec,
36
+ parseDOM: [{
37
+ tag: "div[data-docx-bookmark-boundary]",
38
+ getAttrs: parseBookmarkBoundaryDom
39
+ }],
40
+ toDOM(node) {
41
+ return ["div", bookmarkBoundaryDomAttributes(node)];
42
+ }
43
+ }
44
+ });
45
+ //#endregion
46
+ export { BLOCK_BOOKMARK_BOUNDARY_NODE_NAME, BlockBookmarkBoundaryExtension };
@@ -12,9 +12,10 @@ import { NodeExtension } from "../types.js";
12
12
  * - `sdtType` / `alias` / `tag` / `lock` / `placeholder` /
13
13
  * `showingPlaceholder` / `dateFormat` / `listItems` / `checked` — modeled
14
14
  * projection of `w:sdtPr`; drives addressing and widget UX.
15
- * - `rawPropertiesXml` / `rawEndPropertiesXml` — verbatim original strings
16
- * so unmodeled OOXML features (`w:dataBinding`, `w15:repeatingSection`,
17
- * etc.) round-trip without being enumerated here.
15
+ * - `_preserved` — the `w:sdtPr` children folio does not model, at their
16
+ * schema ordinal, so `w:dataBinding`, `w15:repeatingSection` and the
17
+ * control-kind element round-trip without being enumerated here.
18
+ * - `rawEndPropertiesXml` — the verbatim `<w:sdtEndPr>`.
18
19
  */
19
20
  declare const BlockSdtExtension: (options?: Partial<Record<string, unknown>> | undefined) => NodeExtension;
20
21
  //#endregion