@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
@@ -11,16 +11,22 @@ const defaultDisplay = (checked) => ({
11
11
  char: checked ? DEFAULT_CHECKED_CHARACTER : DEFAULT_UNCHECKED_CHARACTER,
12
12
  font: DEFAULT_CHECKBOX_FONT
13
13
  });
14
- /** Resolve the authored checkbox state into the run payload Word expects. */
15
- const checkboxDisplayContent = (rawPropertiesXml, checked) => {
16
- if (!rawPropertiesXml || rawPropertiesXml.length > MAX_CHECKBOX_PROPERTIES_CHARACTERS) return defaultDisplay(checked);
14
+ /**
15
+ * Resolve the authored checkbox state into the run payload Word expects.
16
+ *
17
+ * @param checkboxXml the preserved `w14:checkbox` element, from
18
+ * `SdtProperties.preserved`. A control that carries none — one built in
19
+ * code, or one whose author wrote no glyphs — gets Word's own defaults.
20
+ */
21
+ const checkboxDisplayContent = (checkboxXml, checked) => {
22
+ if (!checkboxXml || checkboxXml.length > MAX_CHECKBOX_PROPERTIES_CHARACTERS) return defaultDisplay(checked);
17
23
  let root;
18
24
  try {
19
- root = parseXml(rawPropertiesXml, OOXML_NAMESPACE_SCOPE);
25
+ root = parseXml(checkboxXml, OOXML_NAMESPACE_SCOPE);
20
26
  } catch {
21
27
  return defaultDisplay(checked);
22
28
  }
23
- const state = findChildByNamespaceUri(findChildByNamespaceUri(findChildByNamespaceUri(root, WORDPROCESSINGML_NAMESPACE_URIS, "sdtPr"), CHECKBOX_NAMESPACE_URIS, "checkbox"), CHECKBOX_NAMESPACE_URIS, checked ? "checkedState" : "uncheckedState");
29
+ const state = findChildByNamespaceUri(findChildByNamespaceUri(root, CHECKBOX_NAMESPACE_URIS, "checkbox"), CHECKBOX_NAMESPACE_URIS, checked ? "checkedState" : "uncheckedState");
24
30
  const rawCharacter = getAttributeByNamespaceUri(state, CHECKBOX_NAMESPACE_URIS, "val");
25
31
  if (!rawCharacter || !HEX_CODE_POINT.test(rawCharacter)) return defaultDisplay(checked);
26
32
  const codePoint = Number.parseInt(rawCharacter, 16);
@@ -1,5 +1,6 @@
1
1
  import { formatDate } from "../docx/fieldParser.js";
2
2
  import { cloneParagraphWithPropertySource } from "../docx/paragraphPropertySource.js";
3
+ import { preservedSdtChild, withoutPreservedSdtChild } from "../docx/sdtProperties.js";
3
4
  import { checkboxDisplayContent } from "./checkboxDisplay.js";
4
5
  import { ContentControlBoundError, ContentControlLockedError, ContentControlTypeError } from "./errors.js";
5
6
  import { sanitizeXmlCharacters } from "@stll/docx-core";
@@ -95,22 +96,16 @@ function ensureSdtNotLocked(control, force) {
95
96
  if (lock === "sdtLocked" || lock === "sdtContentLocked") throwLocked(control, lock);
96
97
  }
97
98
  function isRepeatingSection(control) {
98
- const raw = control.properties.rawPropertiesXml;
99
- return raw !== void 0 && REPEATING_SECTION_RE.test(raw);
99
+ return preservedSdtChild(control.properties.preserved, "repeatingSection") !== void 0;
100
100
  }
101
- const REPEATING_SECTION_RE = /<\w+:repeatingSection\b/u;
102
- const DATA_BINDING_RE = /<\w+:dataBinding\b(?<attrs>[^>]*)\/?>/iu;
103
101
  /**
104
- * Detect a `<w:dataBinding w:xpath="…"/>` (or alt-prefix variant) inside
105
- * the captured rawPropertiesXml + extract the xpath / storeItemID for
106
- * the error payload. Returns null when no binding is present.
102
+ * The binding a `<w:dataBinding w:xpath="…"/>` states, for the error payload.
103
+ *
104
+ * Returns null when the control carries no binding.
107
105
  */
108
106
  function readDataBinding(control) {
109
- const raw = control.properties.rawPropertiesXml;
110
- if (raw === void 0) return null;
111
- const match = DATA_BINDING_RE.exec(raw);
112
- if (!match) return null;
113
- const attrs = match.groups?.["attrs"] ?? "";
107
+ const attrs = preservedSdtChild(control.properties.preserved, "dataBinding");
108
+ if (attrs === void 0) return null;
114
109
  const xpathMatch = /\bxpath="(?<xpath>[^"]*)"/iu.exec(attrs);
115
110
  if (!xpathMatch) return null;
116
111
  const xpath = xpathMatch.groups?.["xpath"] ?? "";
@@ -123,14 +118,13 @@ function readDataBinding(control) {
123
118
  }
124
119
  /**
125
120
  * Refuse content mutations on bound SDTs unless the caller passes
126
- * `{ force: true }`. When force is set, return the rawPropertiesXml
127
- * with the `<w:dataBinding>` element stripped so the caller's write
128
- * actually sticks on next Word open. See `ContentControlBoundError`
129
- * for the rationale.
121
+ * `{ force: true }`. When force is set, return the property set without its
122
+ * `<w:dataBinding>` child so the caller's write actually sticks on next Word
123
+ * open. See `ContentControlBoundError` for the rationale.
130
124
  */
131
125
  function ensureContentNotBound(control, force) {
132
126
  const binding = readDataBinding(control);
133
- if (!binding) return { strippedRawPropertiesXml: void 0 };
127
+ if (!binding) return { wasBound: false };
134
128
  if (!force) throw new ContentControlBoundError({
135
129
  message: `Control "${control.properties.tag ?? control.properties.alias ?? "(unnamed)"}" is bound to ${binding.xpath}. Word regenerates the body from the bound XML on open; pass { force: true } to strip the binding inline, or remove it explicitly before writing.`,
136
130
  xpath: binding.xpath,
@@ -138,9 +132,19 @@ function ensureContentNotBound(control, force) {
138
132
  ...control.properties.tag !== void 0 ? { tag: control.properties.tag } : {},
139
133
  ...control.properties.alias !== void 0 ? { alias: control.properties.alias } : {}
140
134
  });
141
- const raw = control.properties.rawPropertiesXml;
142
- if (raw === void 0) return { strippedRawPropertiesXml: void 0 };
143
- return { strippedRawPropertiesXml: raw.replaceAll(/<\w+:dataBinding\b[^>]*\/?>(?:[\s\S]*?<\/\w+:dataBinding>)?/giu, "") };
135
+ return {
136
+ wasBound: true,
137
+ unbound: withoutPreservedSdtChild(control.properties.preserved, "dataBinding")
138
+ };
139
+ }
140
+ /** Write a {@link BindingRemoval} onto a copy of a control's properties. */
141
+ function applyBindingRemoval(properties, removal) {
142
+ if (!removal.wasBound) return;
143
+ if (removal.unbound === void 0) {
144
+ delete properties.preserved;
145
+ return;
146
+ }
147
+ properties.preserved = removal.unbound;
144
148
  }
145
149
  function mapBlock(block, match) {
146
150
  if (block.type === "blockSdt") {
@@ -242,7 +246,7 @@ function makeCheckboxParagraph(control, checked) {
242
246
  const content = [{
243
247
  type: "run",
244
248
  ...run?.formatting !== void 0 ? { formatting: run.formatting } : {},
245
- content: [checkboxDisplayContent(control.properties.rawPropertiesXml, checked)]
249
+ content: [checkboxDisplayContent(preservedSdtChild(control.properties.preserved, "checkbox"), checked)]
246
250
  }];
247
251
  if (!paragraph) return {
248
252
  type: "paragraph",
@@ -273,11 +277,11 @@ function setContentControlContent(doc, filter, input, options = {}) {
273
277
  const match = (control) => {
274
278
  if (!controlMatchesFilter(control, filter)) return;
275
279
  ensureContentNotLocked(control, options.force);
276
- const { strippedRawPropertiesXml } = ensureContentNotBound(control, options.force);
280
+ const removal = ensureContentNotBound(control, options.force);
277
281
  const blocks = typeof input === "string" ? [makeParagraphFromText(input)] : input.map(cloneBlock);
278
282
  const properties = { ...control.properties };
279
283
  properties.showingPlaceholder = false;
280
- if (strippedRawPropertiesXml !== void 0) properties.rawPropertiesXml = strippedRawPropertiesXml;
284
+ applyBindingRemoval(properties, removal);
281
285
  return {
282
286
  ...control,
283
287
  properties,
@@ -295,7 +299,17 @@ function setContentControlValue(doc, filter, input, options = {}) {
295
299
  const match = (control) => {
296
300
  if (!controlMatchesFilter(control, filter)) return;
297
301
  ensureContentNotLocked(control, options.force);
298
- const { strippedRawPropertiesXml } = ensureContentNotBound(control, options.force);
302
+ const removal = ensureContentNotBound(control, options.force);
303
+ /** The control's properties, unbound, plus whatever this input sets. */
304
+ const nextProperties = (set) => {
305
+ const properties = {
306
+ ...control.properties,
307
+ ...set
308
+ };
309
+ properties.showingPlaceholder = false;
310
+ applyBindingRemoval(properties, removal);
311
+ return properties;
312
+ };
299
313
  const sdtType = control.properties.sdtType;
300
314
  if (input.kind === "dropdown") {
301
315
  if (sdtType !== "dropdown" && sdtType !== "comboBox") throw new ContentControlTypeError({
@@ -316,12 +330,7 @@ function setContentControlValue(doc, filter, input, options = {}) {
316
330
  const display = item?.displayText ?? input.value;
317
331
  return {
318
332
  ...control,
319
- properties: {
320
- ...control.properties,
321
- dropdownLastValue: sanitizeXmlCharacters(input.value),
322
- showingPlaceholder: false,
323
- ...strippedRawPropertiesXml !== void 0 ? { rawPropertiesXml: strippedRawPropertiesXml } : {}
324
- },
333
+ properties: nextProperties({ dropdownLastValue: sanitizeXmlCharacters(input.value) }),
325
334
  content: [makeParagraphFromText(display)]
326
335
  };
327
336
  }
@@ -335,12 +344,7 @@ function setContentControlValue(doc, filter, input, options = {}) {
335
344
  });
336
345
  return {
337
346
  ...control,
338
- properties: {
339
- ...control.properties,
340
- checked: input.checked,
341
- showingPlaceholder: false,
342
- ...strippedRawPropertiesXml !== void 0 ? { rawPropertiesXml: strippedRawPropertiesXml } : {}
343
- },
347
+ properties: nextProperties({ checked: input.checked }),
344
348
  content: [makeCheckboxParagraph(control, input.checked)]
345
349
  };
346
350
  }
@@ -354,12 +358,7 @@ function setContentControlValue(doc, filter, input, options = {}) {
354
358
  const display = formatDateForSdtBody(input.date, control.properties.dateFormat);
355
359
  return {
356
360
  ...control,
357
- properties: {
358
- ...control.properties,
359
- dateValueISO: input.date,
360
- showingPlaceholder: false,
361
- ...strippedRawPropertiesXml !== void 0 ? { rawPropertiesXml: strippedRawPropertiesXml } : {}
362
- },
361
+ properties: nextProperties({ dateValueISO: input.date }),
363
362
  content: [makeParagraphFromText(display)]
364
363
  };
365
364
  };
@@ -119,7 +119,8 @@ function runLayoutPipeline(deps, state, options = {}) {
119
119
  const flowOpts = {
120
120
  pageContentHeight,
121
121
  fontAlternates,
122
- ...styles ? { styles } : {}
122
+ ...styles ? { styles } : {},
123
+ ...document === null ? {} : { defaultSize: 10 }
123
124
  };
124
125
  if (_theme !== void 0) flowOpts.theme = _theme;
125
126
  if (defaultTabStop !== void 0) flowOpts.defaultTabStopTwips = defaultTabStop;
@@ -188,6 +189,7 @@ function runLayoutPipeline(deps, state, options = {}) {
188
189
  const hfMeasureBlocks = (hfBlocks, hfWidth) => measureBlocks(hfBlocks, hfWidth, void 0, void 0, buildHeaderFooterFieldValues(hfBlocks, pageCount, hfClock, fieldInputs), { allowEndTabOverflow: true });
189
190
  return {
190
191
  ...flowOpts.styles ? { styles: flowOpts.styles } : {},
192
+ ...flowOpts.defaultSize === void 0 ? {} : { defaultSize: flowOpts.defaultSize },
191
193
  ..._theme !== void 0 ? { theme: _theme } : {},
192
194
  fontAlternates,
193
195
  measureBlocks: hfMeasureBlocks,
@@ -288,7 +290,8 @@ function runLayoutPipeline(deps, state, options = {}) {
288
290
  marginBottom: blockMeasureInputs.physicalPageGeometry.marginBottoms
289
291
  },
290
292
  columnIndex: blockMeasureInputs.columnIndices,
291
- columnCount: blockMeasureInputs.columnCounts
293
+ columnCount: blockMeasureInputs.columnCounts,
294
+ sectionAdvances: blockMeasureInputs.sectionAdvances
292
295
  });
293
296
  newBlocks = resolveEffectiveParagraphSpacingTree(newBlocks);
294
297
  outcome.blocks = newBlocks;
@@ -338,6 +341,7 @@ function runLayoutPipeline(deps, state, options = {}) {
338
341
  footnoteContentMap = buildFootnoteContentMap(documentFootnotes, footnoteRefs, contentWidth, (() => {
339
342
  const footnoteOptions = { measureBlocks };
340
343
  if (flowOpts.styles) footnoteOptions.styles = flowOpts.styles;
344
+ if (flowOpts.defaultSize !== void 0) footnoteOptions.defaultSize = flowOpts.defaultSize;
341
345
  if (_theme !== void 0) footnoteOptions.theme = _theme;
342
346
  footnoteOptions.fontAlternates = fontAlternates;
343
347
  if (defaultTabStop !== void 0) footnoteOptions.defaultTabStopTwips = defaultTabStop;
@@ -416,7 +420,8 @@ function runLayoutPipeline(deps, state, options = {}) {
416
420
  marginBottom: blockMeasureInputs.physicalPageGeometry.marginBottoms
417
421
  },
418
422
  columnIndex: blockMeasureInputs.columnIndices,
419
- columnCount: blockMeasureInputs.columnCounts
423
+ columnCount: blockMeasureInputs.columnCounts,
424
+ sectionAdvances: blockMeasureInputs.sectionAdvances
420
425
  }, values);
421
426
  relayoutWithCurrentMeasures(layoutOptsUsed);
422
427
  pendingArtifacts = {
@@ -1,4 +1,3 @@
1
- import { isHeadingOutlineLevel } from "../../docx/builtInStyles.js";
2
1
  import { HIT_REGION_KINDS } from "../primitives.js";
3
2
  import { AuthorColorTable } from "./buildContext.js";
4
3
  import { DOC_CANVAS } from "./colors.js";
@@ -12,6 +11,7 @@ import { blockRegion, createPageComposer } from "./regions.js";
12
11
  import { paintTableFragment } from "./tablePrimitives.js";
13
12
  import { paintTextBoxFragment } from "./textBoxPrimitives.js";
14
13
  import { UNSUPPORTED_CONSTRUCT, UnsupportedCollector } from "./unsupported.js";
14
+ import { headingLevelOf } from "@stll/docx-core/model";
15
15
  //#region src/display-list/build/buildDisplayList.ts
16
16
  /**
17
17
  * `Layout` + `BlockLookup` → `DisplayList`.
@@ -75,10 +75,10 @@ const paragraphTextOf = (block) => block.runs.map((run) => run.kind === "text" ?
75
75
  * where each bookmark lands (a `#name` hyperlink cannot become a page target
76
76
  * until then) and the heading outline.
77
77
  *
78
- * The outline takes the levels {@link isHeadingOutlineLevel} accepts and no
79
- * others: `w:outlineLvl` 9 is the reserved body-text value, not a tenth level,
80
- * and a `TOC Heading` paragraph carrying it would otherwise become a PDF
81
- * bookmark nested nine deep.
78
+ * The outline takes the levels {@link headingLevelOf} names and no others:
79
+ * `w:outlineLvl` 9 is the reserved body-text value, not a tenth level, and a
80
+ * `TOC Heading` paragraph carrying it would otherwise become a PDF bookmark
81
+ * nested nine deep.
82
82
  */
83
83
  const collectDocumentTargets = (layout, blockLookup) => {
84
84
  const bookmarkTargets = /* @__PURE__ */ new Map();
@@ -92,8 +92,8 @@ const collectDocumentTargets = (layout, blockLookup) => {
92
92
  pageIndex,
93
93
  yPx: fragment.y
94
94
  });
95
- const level = block.attrs?.outlineLevel;
96
- if (isHeadingOutlineLevel(level) && fragment.continuesFromPrev !== true) {
95
+ const level = headingLevelOf(block.attrs?.outlineLevel);
96
+ if (level !== void 0 && fragment.continuesFromPrev !== true) {
97
97
  const title = paragraphTextOf(block);
98
98
  if (title.length > 0) outline.push({
99
99
  title,
@@ -15,7 +15,7 @@ declare class ImageTable {
15
15
  failureFor(src: string): string | undefined;
16
16
  snapshot(): readonly DisplayImageSource[];
17
17
  }
18
- type ImageVisualSource = Pick<ImageBlock, "src" | "opacity" | "brightness" | "contrast" | "cropTop" | "cropRight" | "cropBottom" | "cropLeft" | "borderWidth" | "borderColor" | "borderStyle" | "transform">;
18
+ type ImageVisualSource = Pick<ImageBlock, "src" | "preview" | "opacity" | "brightness" | "contrast" | "cropTop" | "cropRight" | "cropBottom" | "cropLeft" | "borderWidth" | "borderColor" | "borderStyle" | "transform">;
19
19
  type PaintImageOptions = {
20
20
  readonly source: ImageVisualSource;
21
21
  readonly rect: DisplayRect;
@@ -24,9 +24,9 @@ type PaintImageOptions = {
24
24
  readonly label: string;
25
25
  };
26
26
  /**
27
- * The primitives one picture draws: the bitmap (rotated and/or washed as the
28
- * source asks) followed by its border. Empty when the bytes are unusable, with
29
- * the reason already reported.
27
+ * The primitives one picture draws: the bitmap or the drawn preview (rotated
28
+ * and/or washed as the source asks) followed by its border. Empty when the
29
+ * bytes are unusable, with the reason already reported.
30
30
  */
31
31
  declare const paintImage: ({ source, rect, context, label }: PaintImageOptions) => readonly DisplayPrimitive[];
32
32
  /** An anchored or block image fragment placed by the layout engine. */
@@ -1,5 +1,6 @@
1
1
  import { parseRotationDegrees } from "../../utils/rotationBoundingBox.js";
2
2
  import { sanitizeImageSrc } from "../../utils/sanitizeImageSrc.js";
3
+ import { paintPreview } from "./previewPrimitives.js";
3
4
  import { resolveBorderStroke } from "./strokes.js";
4
5
  import { UNSUPPORTED_CONSTRUCT } from "./unsupported.js";
5
6
  import { Result } from "better-result";
@@ -194,37 +195,54 @@ const cropOf = (source) => {
194
195
  b
195
196
  };
196
197
  };
197
- /**
198
- * The primitives one picture draws: the bitmap (rotated and/or washed as the
199
- * source asks) followed by its border. Empty when the bytes are unusable, with
200
- * the reason already reported.
201
- */
202
- const paintImage = ({ source, rect, context, label }) => {
203
- const primitives = [];
198
+ const opacityOf = (source) => source.opacity == null ? 1 : Math.min(1, Math.max(0, source.opacity));
199
+ const withOpacity = (children, opacity) => opacity === 1 || children.length === 0 ? children : [{
200
+ kind: "opacityGroup",
201
+ opacity,
202
+ children
203
+ }];
204
+ /** The bitmap one picture draws, or nothing, with the reason already reported. */
205
+ const paintBitmap = ({ source, rect, context, label }) => {
204
206
  const ref = context.images.intern(source.src);
205
207
  if (ref === void 0) {
206
208
  const reason = context.images.failureFor(source.src) ?? "image could not be decoded";
207
209
  const construct = reason.includes("not PNG or JPEG") ? UNSUPPORTED_CONSTRUCT.imageFormat : UNSUPPORTED_CONSTRUCT.imageSource;
208
210
  context.unsupported.report(construct, context.pageIndex, `${label}: ${reason}`);
209
- } else {
210
- const crop = cropOf(source);
211
- const image = {
212
- kind: "image",
213
- image: ref,
214
- rect,
215
- ...crop === void 0 ? {} : { crop },
216
- opacity: source.opacity == null ? 1 : Math.min(1, Math.max(0, source.opacity)),
217
- ...source.brightness == null ? {} : { brightness: source.brightness },
218
- ...source.contrast == null ? {} : { contrast: source.contrast }
219
- };
211
+ return [];
212
+ }
213
+ const crop = cropOf(source);
214
+ return [{
215
+ kind: "image",
216
+ image: ref,
217
+ rect,
218
+ ...crop === void 0 ? {} : { crop },
219
+ opacity: opacityOf(source),
220
+ ...source.brightness == null ? {} : { brightness: source.brightness },
221
+ ...source.contrast == null ? {} : { contrast: source.contrast }
222
+ }];
223
+ };
224
+ /**
225
+ * The primitives one picture draws: the bitmap or the drawn preview (rotated
226
+ * and/or washed as the source asks) followed by its border. Empty when the
227
+ * bytes are unusable, with the reason already reported.
228
+ */
229
+ const paintImage = ({ source, rect, context, label }) => {
230
+ const primitives = [];
231
+ const drawn = source.preview === void 0 ? paintBitmap({
232
+ source,
233
+ rect,
234
+ context,
235
+ label
236
+ }) : withOpacity(paintPreview(source.preview, rect), opacityOf(source));
237
+ if (drawn.length > 0) {
220
238
  const degrees = parseRotationDegrees(source.transform);
221
- if (degrees === 0) primitives.push(image);
239
+ if (degrees === 0) primitives.push(...drawn);
222
240
  else primitives.push({
223
241
  kind: "rotateGroup",
224
242
  degrees,
225
243
  originXPx: rect.xPx + rect.widthPx / 2,
226
244
  originYPx: rect.yPx + rect.heightPx / 2,
227
- children: [image]
245
+ children: drawn
228
246
  });
229
247
  }
230
248
  if (source.borderWidth != null && source.borderWidth > 0) {
@@ -1,3 +1,4 @@
1
+ import { cssBorderStyle } from "../../utils/borderCss.js";
1
2
  import { resolveColor } from "../../utils/colorResolver.js";
2
3
  import { eighthsToPixels, pointsToPixels } from "../../utils/units.js";
3
4
  import { resolveBorderStroke } from "./strokes.js";
@@ -25,7 +26,7 @@ const strokeOf = (border, theme, context) => {
25
26
  if (!border) return;
26
27
  const { stroke, unresolvedColor } = resolveBorderStroke({
27
28
  width: border.size === void 0 || border.size === 0 ? HAIRLINE_WIDTH_PX : eighthsToPixels(border.size),
28
- style: border.style,
29
+ style: cssBorderStyle(border.style),
29
30
  color: resolveColor(border.color, theme)
30
31
  });
31
32
  if (unresolvedColor !== void 0) context.unsupported.report(UNSUPPORTED_CONSTRUCT.unresolvedColor, context.pageIndex, `page border colour ${unresolvedColor}`);
@@ -6,17 +6,17 @@ import { countCompressibleSpaces, toPaintedText } from "../../layout-engine/meas
6
6
  import { isFloatingImageRun } from "../../layout-engine/types.js";
7
7
  import { resolveParagraphBorderHorizontalOutsets } from "../../layout-painter/borderStroke.js";
8
8
  import { getAutomaticTextColorForBackground } from "../../layout-painter/documentColors.js";
9
- import { UNICODE_BIDI_BY_WRAPPER_CONTROL, getLeaderChar, getRenderableTextColor, sliceRunsForLine, splitCollapsibleLineEdgeSpaces, splitTextRunsByEastAsia, startsAfterSoftWrap } from "../../layout-painter/renderParagraph.js";
9
+ import { UNICODE_BIDI_BY_WRAPPER_CONTROL, getLeaderChar, getRenderableTextColor, paragraphHasTrackedChanges, sliceRunsForLine, splitCollapsibleLineEdgeSpaces, splitTextRunsByEastAsia, startsAfterSoftWrap } from "../../layout-painter/renderParagraph.js";
10
10
  import { getHorizontalScaleFactor } from "../../utils/horizontalScale.js";
11
11
  import { resolvePhysicalParagraphInlineLayout } from "../../utils/paragraphInlineLayout.js";
12
12
  import { inlineImageBoundingBox } from "../../utils/rotationBoundingBox.js";
13
13
  import { sanitizeExternalUrl } from "../../utils/urlSecurity.js";
14
- import { HIT_REGION_KINDS } from "../primitives.js";
14
+ import { HIT_REGION_KINDS, strokeCrossExtentPx } from "../primitives.js";
15
15
  import { trackedChangeColor } from "./buildContext.js";
16
16
  import { DOC_CANVAS_TEXT, parseDisplayColor } from "./colors.js";
17
17
  import { buildGlyphs, glyphRunText } from "./glyphs.js";
18
18
  import { paintImage } from "./imagePrimitives.js";
19
- import { decorationPatternForStyle, resolveBorderStroke } from "./strokes.js";
19
+ import { resolveBorderStroke, underlinePattern, underlineStrokeCount, underlineWeight } from "./strokes.js";
20
20
  import { strikethroughCenterYPx, underlineCenterYPx, underlineThicknessPx } from "./textDecorations.js";
21
21
  import { UNSUPPORTED_CONSTRUCT } from "./unsupported.js";
22
22
  //#region src/display-list/build/paragraphPrimitives.ts
@@ -66,6 +66,14 @@ const SUBSCRIPT_DROP_RATIO = .2;
66
66
  const WIDTH_EPSILON_PX = .5;
67
67
  /** `w:pBdr` bar borders hang this far left of the text (`renderParagraph.ts:3072`). */
68
68
  const BAR_BORDER_OFFSET_PX = 8;
69
+ /** Word's review indicator sits in the page margin outside the paragraph. */
70
+ const REVIEW_BAR_OFFSET_PX = 24;
71
+ const REVIEW_BAR_COLOR = {
72
+ r: 0,
73
+ g: 0,
74
+ b: 0,
75
+ a: 1
76
+ };
69
77
  const AUTOMATIC_TEXT_COLOR_VALUES = /* @__PURE__ */ new Set(["auto", "windowtext"]);
70
78
  /** `w:color w:val="auto"` and its `windowtext` spelling, normalized as the painter normalizes them. */
71
79
  const isAutomaticTextColor = (color) => AUTOMATIC_TEXT_COLOR_VALUES.has(color.trim().toLowerCase().replace(/^#/u, ""));
@@ -151,6 +159,18 @@ const paintParagraphChrome = ({ fragment, block, context, prevBorders, nextBorde
151
159
  });
152
160
  else context.unsupported.report(UNSUPPORTED_CONSTRUCT.unresolvedColor, context.pageIndex, `paragraph shading ${shading}`);
153
161
  }
162
+ if (paragraphHasTrackedChanges(block)) primitives.push({
163
+ kind: "line",
164
+ x1Px: fragment.x - REVIEW_BAR_OFFSET_PX,
165
+ y1Px: fragment.y,
166
+ x2Px: fragment.x - REVIEW_BAR_OFFSET_PX,
167
+ y2Px: fragment.y + fragment.height,
168
+ stroke: {
169
+ color: REVIEW_BAR_COLOR,
170
+ thicknessPx: 2,
171
+ pattern: "solid"
172
+ }
173
+ });
154
174
  const borders = block.attrs?.borders;
155
175
  if (!borders) return primitives;
156
176
  const topBorder = bordersFormGroup(prevBorders, borders) ? borders.between : borders.top;
@@ -380,7 +400,7 @@ const emitGlyphRun = ({ sink, context, run, glyphs, style, paintXPx, baselineYPx
380
400
  color,
381
401
  context,
382
402
  xPx: paintXPx,
383
- widthPx: glyphs.widthPx,
403
+ glyphs,
384
404
  baselineYPx: runBaselineYPx,
385
405
  fontSizePx
386
406
  });
@@ -399,23 +419,83 @@ const emitGlyphRun = ({ sink, context, run, glyphs, style, paintXPx, baselineYPx
399
419
  }
400
420
  reportRunEffects(run, context);
401
421
  };
402
- const emitDecorations = ({ sink, run, color, context, xPx, widthPx, baselineYPx, fontSizePx }) => {
422
+ /**
423
+ * The ordinary space, the only character `words` breaks an underline at.
424
+ *
425
+ * It is the same character justification stretches (`countCompressibleSpaces`):
426
+ * a no-break space holds two words together, so Word underlines through it.
427
+ */
428
+ const WORD_SEPARATOR = " ";
429
+ /**
430
+ * Where an underline is drawn under a run: the whole run, or one span per word.
431
+ *
432
+ * Word's `words` member underlines the words and not the gaps between them.
433
+ * CSS cannot express that, so the editor underlines the run whole
434
+ * (`text-decoration-skip-ink` skips descender ink, and
435
+ * `text-decoration-skip: spaces` never shipped). A display list carries one
436
+ * advance per code point, so here the member is exact rather than approximated.
437
+ */
438
+ const underlineSpans = (glyphs, xPx, perWord) => {
439
+ if (!perWord) return [{
440
+ xPx,
441
+ widthPx: glyphs.widthPx
442
+ }];
443
+ const spans = [];
444
+ let cursorPx = xPx;
445
+ let wordStartPx;
446
+ let index = 0;
447
+ const pushWord = (endPx) => {
448
+ if (wordStartPx !== void 0 && endPx > wordStartPx) spans.push({
449
+ xPx: wordStartPx,
450
+ widthPx: endPx - wordStartPx
451
+ });
452
+ wordStartPx = void 0;
453
+ };
454
+ for (const char of glyphs.text) {
455
+ const advancePx = glyphs.advancesPx[index] ?? 0;
456
+ index += 1;
457
+ if (char === WORD_SEPARATOR) pushWord(cursorPx);
458
+ else if (wordStartPx === void 0) wordStartPx = cursorPx;
459
+ cursorPx += advancePx;
460
+ }
461
+ pushWord(cursorPx);
462
+ return spans;
463
+ };
464
+ /**
465
+ * Where each stroke of a stacked decoration sits, relative to the path.
466
+ *
467
+ * One stroke sits on the path. Two are pushed apart by the band each occupies
468
+ * plus the gap a `double` stroke leaves between its rules, so `wavyDouble`'s
469
+ * waves clear each other by the same margin and stay centred on the underline.
470
+ */
471
+ const stackedStrokeOffsetsPx = (stroke, count) => {
472
+ if (count < 2) return [0];
473
+ const separationPx = strokeCrossExtentPx(stroke) + 1 * stroke.thicknessPx;
474
+ return Array.from({ length: count }, (_, index) => (index - (count - 1) / 2) * separationPx);
475
+ };
476
+ const emitDecorations = ({ sink, run, color, context, xPx, glyphs, baselineYPx, fontSizePx }) => {
477
+ const { widthPx } = glyphs;
403
478
  if (widthPx <= 0) return;
404
- const thicknessPx = underlineThicknessPx(fontSizePx);
479
+ const plainThicknessPx = underlineThicknessPx(fontSizePx);
405
480
  const trackedColor = run.isInsertion || run.isDeletion ? trackedChangeColor(context.authorColors, run.changeAuthor, run.isSuggestion) : void 0;
406
481
  if (Boolean(run.underline) && !isNoteReferenceRun(run) || run.isInsertion) {
407
482
  const authored = typeof run.underline === "object" ? run.underline : void 0;
408
483
  const authoredColor = authored?.color === void 0 ? void 0 : parseDisplayColor(authored.color);
409
- const pattern = run.isSuggestion ? "dotted" : decorationPatternForStyle(authored?.style);
410
- sink.decorations.push(horizontalLine(xPx, widthPx, underlineCenterYPx(baselineYPx, fontSizePx), {
411
- color: trackedColor ?? authoredColor ?? color,
412
- thicknessPx,
413
- pattern
414
- }));
484
+ const style = run.isSuggestion ? void 0 : authored?.style;
485
+ const pattern = run.isSuggestion ? "dotted" : underlinePattern(style);
486
+ if (pattern !== "none") {
487
+ const stroke = {
488
+ color: trackedColor ?? authoredColor ?? color,
489
+ thicknessPx: plainThicknessPx * underlineWeight(style),
490
+ pattern
491
+ };
492
+ const centerYPx = underlineCenterYPx(baselineYPx, fontSizePx);
493
+ for (const span of underlineSpans(glyphs, xPx, style === "words")) for (const offsetPx of stackedStrokeOffsetsPx(stroke, underlineStrokeCount(style))) sink.decorations.push(horizontalLine(span.xPx, span.widthPx, centerYPx + offsetPx, stroke));
494
+ }
415
495
  }
416
496
  if (run.strike || run.isDeletion) sink.decorations.push(horizontalLine(xPx, widthPx, strikethroughCenterYPx(baselineYPx, fontSizePx), {
417
497
  color: trackedColor ?? color,
418
- thicknessPx,
498
+ thicknessPx: plainThicknessPx,
419
499
  pattern: run.isSuggestion ? "dotted" : "solid"
420
500
  }));
421
501
  };
@@ -0,0 +1,10 @@
1
+ import { document_d_exports } from "../../types/document.js";
2
+ import { DisplayPrimitive, DisplayRect } from "../types.js";
3
+ //#region src/display-list/build/previewPrimitives.d.ts
4
+ /**
5
+ * The marks a descriptor makes inside `box`, back to front: the backdrop, then
6
+ * each shape in the order the drawing lists them.
7
+ */
8
+ declare const paintPreview: (descriptor: document_d_exports.PreviewDescriptor, box: DisplayRect) => readonly DisplayPrimitive[];
9
+ //#endregion
10
+ export { paintPreview };
@@ -0,0 +1,89 @@
1
+ import { parseDisplayColor } from "./colors.js";
2
+ import { panic } from "better-result";
3
+ //#region src/display-list/build/previewPrimitives.ts
4
+ /**
5
+ * The primitives a preview descriptor draws.
6
+ *
7
+ * A drawing with no image data used to be given one: a megapixel PNG built the
8
+ * moment something was about to paint it, which the DOM backend showed as an
9
+ * `<img>` and the PDF exporter embedded as a bitmap — a photograph of a
10
+ * drawing that is nothing but flat rectangles.
11
+ *
12
+ * The descriptor already holds those rectangles, in the drawing's own
13
+ * coordinate space, and `rect` is a primitive both backends draw natively. So
14
+ * the preview is drawn rather than sampled: the extent maps affinely onto the
15
+ * image's box, every shape becomes a filled rectangle inside it, and no raster
16
+ * exists at any point. The DOM backend paints each one as the absolutely
17
+ * positioned div it paints every other `rect` as, and the PDF backend emits
18
+ * `re`/`f` operators, so the drawing stays a drawing at any zoom.
19
+ */
20
+ /** The flat backdrop a preview is drawn on, behind every shape. */
21
+ const PREVIEW_BACKGROUND = {
22
+ r: 238,
23
+ g: 242,
24
+ b: 247,
25
+ a: 1
26
+ };
27
+ /** A shape whose `a:srgbClr` was missing or is not a colour. */
28
+ const PREVIEW_SHAPE_FILL = {
29
+ r: 232,
30
+ g: 238,
31
+ b: 247,
32
+ a: 1
33
+ };
34
+ const clampFraction = (value) => Math.min(1, Math.max(0, value));
35
+ /**
36
+ * One shape's box, as the fraction of the extent it covers applied to the
37
+ * image's box. `undefined` for a shape the box keeps nothing of, which is the
38
+ * clip the raster did by clamping to its own bounds.
39
+ */
40
+ const shapeRect = ({ shape, extent, box }) => {
41
+ const left = clampFraction(shape.x / extent.width);
42
+ const right = clampFraction((shape.x + shape.width) / extent.width);
43
+ const top = clampFraction(shape.y / extent.height);
44
+ const bottom = clampFraction((shape.y + shape.height) / extent.height);
45
+ if (right <= left || bottom <= top) return;
46
+ return {
47
+ xPx: box.xPx + left * box.widthPx,
48
+ yPx: box.yPx + top * box.heightPx,
49
+ widthPx: (right - left) * box.widthPx,
50
+ heightPx: (bottom - top) * box.heightPx
51
+ };
52
+ };
53
+ /**
54
+ * The marks a descriptor makes inside `box`, back to front: the backdrop, then
55
+ * each shape in the order the drawing lists them.
56
+ */
57
+ const paintPreview = (descriptor, box) => {
58
+ switch (descriptor.kind) {
59
+ case "diagram": {
60
+ const primitives = [{
61
+ kind: "rect",
62
+ rect: box,
63
+ fill: PREVIEW_BACKGROUND
64
+ }];
65
+ const { extent } = descriptor;
66
+ if (!(extent.width > 0 && extent.height > 0)) return primitives;
67
+ for (const shape of descriptor.shapes) {
68
+ const rect = shapeRect({
69
+ shape,
70
+ extent,
71
+ box
72
+ });
73
+ if (rect === void 0) continue;
74
+ primitives.push({
75
+ kind: "rect",
76
+ rect,
77
+ fill: parseDisplayColor(shape.color) ?? PREVIEW_SHAPE_FILL
78
+ });
79
+ }
80
+ return primitives;
81
+ }
82
+ default: {
83
+ const unreachable = descriptor.kind;
84
+ return panic(`unhandled preview kind: ${String(unreachable)}`);
85
+ }
86
+ }
87
+ };
88
+ //#endregion
89
+ export { paintPreview };