@stll/folio-core 0.46.0 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. package/dist/ai-edits/apply.js +26 -24
  2. package/dist/ai-edits/headless.js +1 -1
  3. package/dist/ai-edits/read.d.ts +1 -0
  4. package/dist/ai-edits/read.js +1 -0
  5. package/dist/ai-edits/snapshot.js +32 -27
  6. package/dist/ai-edits/table-cell-mutations.js +15 -7
  7. package/dist/ai-edits/table-geometry.js +21 -18
  8. package/dist/ai-edits/table-template.js +2 -2
  9. package/dist/compare/content-alignment.js +108 -12
  10. package/dist/compare/content-types.d.ts +8 -2
  11. package/dist/compare/content.js +2 -11
  12. package/dist/compare/plan.js +7 -4
  13. package/dist/compare/section-boundary-properties.js +1 -2
  14. package/dist/content-controls/checkboxDisplay.d.ts +8 -2
  15. package/dist/content-controls/checkboxDisplay.js +11 -5
  16. package/dist/content-controls/mutateContentControls.js +41 -42
  17. package/dist/controller/layoutPipeline.js +8 -3
  18. package/dist/display-list/build/buildDisplayList.js +7 -7
  19. package/dist/display-list/build/imagePrimitives.d.ts +4 -4
  20. package/dist/display-list/build/imagePrimitives.js +38 -20
  21. package/dist/display-list/build/pageBorderPrimitives.js +2 -1
  22. package/dist/display-list/build/paragraphPrimitives.js +93 -13
  23. package/dist/display-list/build/previewPrimitives.d.ts +10 -0
  24. package/dist/display-list/build/previewPrimitives.js +89 -0
  25. package/dist/display-list/build/strokes.d.ts +177 -8
  26. package/dist/display-list/build/strokes.js +167 -47
  27. package/dist/display-list/build/tablePrimitives.js +4 -2
  28. package/dist/display-list/build/textBoxPrimitives.js +6 -4
  29. package/dist/display-list/build/textDecorations.d.ts +15 -1
  30. package/dist/display-list/build/textDecorations.js +15 -1
  31. package/dist/display-list/dom/renderDisplayListToDom.js +1 -19
  32. package/dist/display-list/primitives.d.ts +13 -2
  33. package/dist/display-list/primitives.js +36 -1
  34. package/dist/document-operations.js +2 -1
  35. package/dist/docx/attributeRemainder.d.ts +34 -1
  36. package/dist/docx/attributeRemainder.js +49 -3
  37. package/dist/docx/blockContentParser.d.ts +2 -0
  38. package/dist/docx/blockContentParser.js +39 -67
  39. package/dist/docx/blockPlainText.js +3 -1
  40. package/dist/docx/borderParser.js +26 -11
  41. package/dist/docx/builtInStyles.d.ts +8 -16
  42. package/dist/docx/builtInStyles.js +54 -17
  43. package/dist/docx/commentAnchorIndex.js +1 -1
  44. package/dist/docx/commentParser.js +3 -3
  45. package/dist/docx/commentRangeIntegrity.js +1 -1
  46. package/dist/docx/commentRangeJoin.js +1 -1
  47. package/dist/docx/commentReferenceNormalization.js +3 -2
  48. package/dist/docx/commentReplyMarkers.js +1 -1
  49. package/dist/docx/compatibility.js +56 -42
  50. package/dist/docx/containerChildren.d.ts +110 -13
  51. package/dist/docx/containerChildren.gen.d.ts +16 -1
  52. package/dist/docx/containerChildren.gen.js +18 -1
  53. package/dist/docx/containerChildren.js +63 -13
  54. package/dist/docx/diagramPreview.d.ts +14 -2
  55. package/dist/docx/diagramPreview.js +81 -169
  56. package/dist/docx/documentParser.js +4 -1
  57. package/dist/docx/drawingAnchor.d.ts +87 -0
  58. package/dist/docx/drawingAnchor.js +201 -0
  59. package/dist/docx/drawingUtils.d.ts +43 -38
  60. package/dist/docx/drawingUtils.js +205 -118
  61. package/dist/docx/fontTableParser.js +102 -41
  62. package/dist/docx/footnoteParser.js +10 -6
  63. package/dist/docx/groupDrawingParser.js +4 -3
  64. package/dist/docx/headerFooterReferenceNormalization.js +1 -1
  65. package/dist/docx/hyperlinkParser.d.ts +45 -7
  66. package/dist/docx/hyperlinkParser.js +126 -57
  67. package/dist/docx/imageParser.js +127 -107
  68. package/dist/docx/index.d.ts +2 -1
  69. package/dist/docx/index.js +2 -1
  70. package/dist/docx/inlineContentRemovals.d.ts +28 -0
  71. package/dist/docx/inlineContentRemovals.js +46 -0
  72. package/dist/docx/inlineWrapperContent.d.ts +84 -3
  73. package/dist/docx/inlineWrapperContent.js +85 -4
  74. package/dist/docx/inlineWrapperParser.d.ts +11 -0
  75. package/dist/docx/inlineWrapperParser.js +60 -0
  76. package/dist/docx/nonVisualDrawingProps.d.ts +5 -13
  77. package/dist/docx/normalizeBaseDirection.js +4 -2
  78. package/dist/docx/numberingParser.d.ts +25 -2
  79. package/dist/docx/numberingParser.js +264 -361
  80. package/dist/docx/numberingReference.d.ts +9 -16
  81. package/dist/docx/numberingReference.js +17 -16
  82. package/dist/docx/numberingReferenceNormalization.js +7 -7
  83. package/dist/docx/ooxmlCounterFormatter.d.ts +1 -1
  84. package/dist/docx/ooxmlCounterFormatter.js +4 -1
  85. package/dist/docx/paraIdAttribute.d.ts +91 -1
  86. package/dist/docx/paraIdAttribute.js +79 -1
  87. package/dist/docx/paragraphParser.d.ts +9 -24
  88. package/dist/docx/paragraphParser.js +212 -396
  89. package/dist/docx/paragraphProperties.d.ts +23 -0
  90. package/dist/docx/paragraphProperties.js +279 -0
  91. package/dist/docx/paragraphPropertySource.js +2 -0
  92. package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
  93. package/dist/docx/paragraphTextBoxEnrichment.js +14 -7
  94. package/dist/docx/paragraphTraversal.d.ts +14 -10
  95. package/dist/docx/paragraphTraversal.js +47 -49
  96. package/dist/docx/parseWarningMessage.js +3 -0
  97. package/dist/docx/parserEnums.d.ts +6 -8
  98. package/dist/docx/parserEnums.js +4 -6
  99. package/dist/docx/preservedRunContent.js +16 -6
  100. package/dist/docx/previewBudget.d.ts +44 -23
  101. package/dist/docx/previewBudget.js +61 -30
  102. package/dist/docx/propertyElementAttributes.d.ts +178 -0
  103. package/dist/docx/propertyElementAttributes.js +114 -0
  104. package/dist/docx/renderedPageBreakNormalization.js +2 -2
  105. package/dist/docx/rezip.d.ts +28 -2
  106. package/dist/docx/rezip.js +78 -9
  107. package/dist/docx/runConsolidator.d.ts +42 -2
  108. package/dist/docx/runConsolidator.js +60 -6
  109. package/dist/docx/runParser.d.ts +54 -18
  110. package/dist/docx/runParser.js +379 -295
  111. package/dist/docx/runPayload.d.ts +5 -0
  112. package/dist/docx/runPayload.js +4 -0
  113. package/dist/docx/sdtProperties.d.ts +39 -5
  114. package/dist/docx/sdtProperties.js +205 -84
  115. package/dist/docx/sdtPropertiesPatch.d.ts +5 -9
  116. package/dist/docx/sdtPropertiesPatch.js +68 -112
  117. package/dist/docx/sectionParser.d.ts +1 -2
  118. package/dist/docx/sectionParser.js +236 -240
  119. package/dist/docx/selectiveSave.js +3 -2
  120. package/dist/docx/selectiveXmlPatch.d.ts +21 -2
  121. package/dist/docx/selectiveXmlPatch.js +195 -99
  122. package/dist/docx/serializer/blockSdtSerializer.js +2 -96
  123. package/dist/docx/serializer/borderSerializer.d.ts +5 -5
  124. package/dist/docx/serializer/borderSerializer.js +10 -8
  125. package/dist/docx/serializer/documentSerializer.js +3 -0
  126. package/dist/docx/serializer/fontTableSerializer.js +31 -3
  127. package/dist/docx/serializer/headerFooterSerializer.js +3 -0
  128. package/dist/docx/serializer/markupRangeAttributes.d.ts +9 -1
  129. package/dist/docx/serializer/markupRangeAttributes.js +9 -1
  130. package/dist/docx/serializer/noteSerializer.js +3 -0
  131. package/dist/docx/serializer/numberingSerializer.d.ts +1 -6
  132. package/dist/docx/serializer/numberingSerializer.js +81 -79
  133. package/dist/docx/serializer/paragraphSerializer.d.ts +1 -9
  134. package/dist/docx/serializer/paragraphSerializer.js +88 -188
  135. package/dist/docx/serializer/runSerializer.d.ts +1 -5
  136. package/dist/docx/serializer/runSerializer.js +109 -59
  137. package/dist/docx/serializer/sdtPropertiesSerializer.d.ts +26 -0
  138. package/dist/docx/serializer/sdtPropertiesSerializer.js +111 -0
  139. package/dist/docx/serializer/sectionPropertiesSerializer.js +34 -45
  140. package/dist/docx/serializer/settingsSerializer.js +6 -4
  141. package/dist/docx/serializer/stylesSerializer.js +8 -11
  142. package/dist/docx/serializer/tableSerializer.js +268 -100
  143. package/dist/docx/serializer/textFormattingSerializer.d.ts +28 -4
  144. package/dist/docx/serializer/textFormattingSerializer.js +111 -101
  145. package/dist/docx/serializer/xmlUtils.d.ts +1 -1
  146. package/dist/docx/serializer/xmlUtils.js +1 -1
  147. package/dist/docx/server/createBilingualDocument.js +18 -16
  148. package/dist/docx/server/migrateYjsAttrSchema.js +3 -3
  149. package/dist/docx/settingsParser.js +7 -4
  150. package/dist/docx/shadingParser.d.ts +2 -1
  151. package/dist/docx/shadingParser.js +43 -7
  152. package/dist/docx/shapeParser.js +8 -3
  153. package/dist/docx/strictNames.d.ts +11 -0
  154. package/dist/docx/strictNames.gen.d.ts +45 -0
  155. package/dist/docx/strictNames.gen.js +50 -0
  156. package/dist/docx/strictNames.js +43 -0
  157. package/dist/docx/strictValueEncodings.gen.js +133 -131
  158. package/dist/docx/styleParser.js +17 -349
  159. package/dist/docx/tableParser.d.ts +10 -1
  160. package/dist/docx/tableParser.js +505 -181
  161. package/dist/docx/textBoxParser.d.ts +3 -1
  162. package/dist/docx/textBoxParser.js +18 -8
  163. package/dist/docx/themeColorAttribute.d.ts +13 -0
  164. package/dist/docx/themeColorAttribute.js +24 -0
  165. package/dist/docx/trackedMoveRangeNormalization.js +2 -1
  166. package/dist/docx/vmlImageParser.d.ts +13 -4
  167. package/dist/docx/vmlImageParser.js +74 -31
  168. package/dist/docx/vmlPreview.js +2 -2
  169. package/dist/docx/wrapPolygon.d.ts +30 -0
  170. package/dist/docx/wrapPolygon.js +70 -0
  171. package/dist/docx/xmlParser.d.ts +14 -1
  172. package/dist/docx/xmlParser.js +18 -2
  173. package/dist/fonts/embeddedFonts.js +3 -3
  174. package/dist/headless-layout.js +2 -0
  175. package/dist/i18n/messages/catalogs.gen.d.ts +68 -0
  176. package/dist/i18n/messages/catalogs.gen.js +102 -34
  177. package/dist/i18n/messages/messages.gen.d.ts +4 -0
  178. package/dist/internal/headlessRevisionResolution.js +9 -0
  179. package/dist/internal/pageBreakRunSourceDescendantIndex.js +3 -1
  180. package/dist/internal/paragraphFormattingSerialization.d.ts +20 -9
  181. package/dist/internal/paragraphFormattingSerialization.js +118 -83
  182. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  183. package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
  184. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  185. package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
  186. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +17 -12
  187. package/dist/layout-bridge/convert/toFlowBlocks.js +177 -101
  188. package/dist/layout-engine/index.d.ts +2 -2
  189. package/dist/layout-engine/index.js +53 -17
  190. package/dist/layout-engine/measure/measureBlocks.d.ts +3 -0
  191. package/dist/layout-engine/measure/measureBlocks.js +6 -10
  192. package/dist/layout-engine/measure/tableCellGrid.js +2 -1
  193. package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +2 -1
  194. package/dist/layout-engine/measure/tableInlinePlacement.js +2 -5
  195. package/dist/layout-engine/paragraphSequence.js +3 -2
  196. package/dist/layout-engine/renderedBreakReconciliation.js +2 -1
  197. package/dist/layout-engine/section-breaks.d.ts +49 -2
  198. package/dist/layout-engine/section-breaks.js +55 -4
  199. package/dist/layout-engine/types.d.ts +47 -17
  200. package/dist/layout-engine/types.js +16 -1
  201. package/dist/layout-painter/borderStroke.d.ts +18 -4
  202. package/dist/layout-painter/renderPage.js +6 -4
  203. package/dist/layout-painter/renderParagraph.d.ts +2 -1
  204. package/dist/layout-painter/renderParagraph.js +13 -26
  205. package/dist/layout-painter/renderTable.d.ts +4 -1
  206. package/dist/layout-painter/renderTable.js +22 -22
  207. package/dist/layout-painter/renderTextBox.js +5 -3
  208. package/dist/markdown/renderBlock.js +3 -1
  209. package/dist/markdown/renderRuns.js +7 -2
  210. package/dist/markdown/renderTable.js +2 -1
  211. package/dist/model.d.ts +3 -3
  212. package/dist/model.js +2 -2
  213. package/dist/paged-layout/sectionBlockWidths.d.ts +3 -0
  214. package/dist/paged-layout/sectionBlockWidths.js +26 -4
  215. package/dist/prosemirror/attrs/index.d.ts +22 -4
  216. package/dist/prosemirror/attrs/index.js +498 -60
  217. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +9 -1
  218. package/dist/prosemirror/bookmarkBoundaryAttrs.js +22 -3
  219. package/dist/prosemirror/commands/comments.js +68 -53
  220. package/dist/prosemirror/commands/contentControls.js +24 -19
  221. package/dist/prosemirror/commands/image.d.ts +1 -1
  222. package/dist/prosemirror/commands/image.js +4 -1
  223. package/dist/prosemirror/commands/paragraph.d.ts +2 -1
  224. package/dist/prosemirror/commands/propertyChangeScope.d.ts +12 -4
  225. package/dist/prosemirror/commands/propertyChangeScope.js +22 -4
  226. package/dist/prosemirror/commands/sectionBreak.d.ts +33 -1
  227. package/dist/prosemirror/commands/sectionBreak.js +187 -11
  228. package/dist/prosemirror/conversion/fromProseDoc.d.ts +18 -2
  229. package/dist/prosemirror/conversion/fromProseDoc.js +330 -183
  230. package/dist/prosemirror/conversion/index.d.ts +2 -2
  231. package/dist/prosemirror/conversion/preservedSinkCarriers.d.ts +39 -0
  232. package/dist/prosemirror/conversion/preservedSinkCarriers.js +19 -0
  233. package/dist/prosemirror/conversion/runShadingMark.js +14 -1
  234. package/dist/prosemirror/conversion/sdtAttrs.d.ts +10 -1
  235. package/dist/prosemirror/conversion/sdtAttrs.js +19 -5
  236. package/dist/prosemirror/conversion/toProseDoc.js +371 -141
  237. package/dist/prosemirror/emptyRangeAnchor.d.ts +53 -0
  238. package/dist/prosemirror/emptyRangeAnchor.js +158 -0
  239. package/dist/prosemirror/extensions/StarterKit.js +8 -2
  240. package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
  241. package/dist/prosemirror/extensions/core/ParagraphExtension.js +19 -15
  242. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +3 -2
  243. package/dist/prosemirror/extensions/features/ListExtension.js +43 -24
  244. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +4 -3
  245. package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +3 -3
  246. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +5 -5
  247. package/dist/prosemirror/extensions/features/pasteCleanup.d.ts +3 -1
  248. package/dist/prosemirror/extensions/features/pasteCleanup.js +56 -2
  249. package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +5 -4
  250. package/dist/prosemirror/extensions/markRegistry.d.ts +26 -2
  251. package/dist/prosemirror/extensions/markRegistry.js +73 -10
  252. package/dist/prosemirror/extensions/marks/InlineWrapperExtension.js +17 -3
  253. package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +26 -0
  254. package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +134 -0
  255. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -1
  256. package/dist/prosemirror/extensions/marks/UnderlineExtension.js +12 -18
  257. package/dist/prosemirror/extensions/marks/markUtils.js +2 -1
  258. package/dist/prosemirror/extensions/nodes/BlockBookmarkBoundaryExtension.d.ts +29 -0
  259. package/dist/prosemirror/extensions/nodes/BlockBookmarkBoundaryExtension.js +46 -0
  260. package/dist/prosemirror/extensions/nodes/BlockSdtExtension.d.ts +4 -3
  261. package/dist/prosemirror/extensions/nodes/BlockSdtExtension.js +18 -13
  262. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +28 -53
  263. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +10 -0
  264. package/dist/prosemirror/extensions/nodes/ImageExtension.js +8 -1
  265. package/dist/prosemirror/extensions/nodes/MoveRangeBoundaryExtension.d.ts +11 -0
  266. package/dist/prosemirror/extensions/nodes/MoveRangeBoundaryExtension.js +43 -0
  267. package/dist/prosemirror/extensions/nodes/RangeAnchorExtension.d.ts +13 -0
  268. package/dist/prosemirror/extensions/nodes/RangeAnchorExtension.js +65 -0
  269. package/dist/prosemirror/extensions/nodes/SdtExtension.d.ts +3 -1
  270. package/dist/prosemirror/extensions/nodes/SdtExtension.js +22 -16
  271. package/dist/prosemirror/extensions/nodes/ShapeExtension.js +4 -0
  272. package/dist/prosemirror/extensions/nodes/TableExtension.js +141 -123
  273. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +4 -0
  274. package/dist/prosemirror/extensions/nodes/bookmarkBoundaryDom.d.ts +23 -0
  275. package/dist/prosemirror/extensions/nodes/bookmarkBoundaryDom.js +57 -0
  276. package/dist/prosemirror/extensions/types.d.ts +12 -3
  277. package/dist/prosemirror/index.d.ts +4 -2
  278. package/dist/prosemirror/index.js +2 -1
  279. package/dist/prosemirror/inlineWrapperStack.js +20 -3
  280. package/dist/prosemirror/listMarker.d.ts +2 -2
  281. package/dist/prosemirror/listMarker.js +7 -8
  282. package/dist/prosemirror/listRenderingAttrs.js +11 -1
  283. package/dist/prosemirror/listState.d.ts +62 -0
  284. package/dist/prosemirror/listState.js +49 -0
  285. package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +13 -0
  286. package/dist/prosemirror/moveRangeBoundaryAttrs.js +114 -0
  287. package/dist/prosemirror/numberedRefFields.js +4 -4
  288. package/dist/prosemirror/numberingAttr.d.ts +55 -0
  289. package/dist/prosemirror/numberingAttr.js +74 -0
  290. package/dist/prosemirror/outlineLevelAttr.d.ts +29 -0
  291. package/dist/prosemirror/outlineLevelAttr.js +42 -0
  292. package/dist/prosemirror/paragraphFormattingProvenance.d.ts +9 -0
  293. package/dist/prosemirror/paragraphFormattingProvenance.js +4 -1
  294. package/dist/prosemirror/plugins/selectionTracker.d.ts +3 -6
  295. package/dist/prosemirror/plugins/selectionTracker.js +3 -10
  296. package/dist/prosemirror/rangeAnchorAttrs.d.ts +14 -0
  297. package/dist/prosemirror/rangeAnchorAttrs.js +101 -0
  298. package/dist/prosemirror/replacedAnnotations.d.ts +1 -1
  299. package/dist/prosemirror/replacedAnnotations.js +24 -6
  300. package/dist/prosemirror/revisionCarriers.d.ts +86 -2
  301. package/dist/prosemirror/revisionCarriers.js +86 -60
  302. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -0
  303. package/dist/prosemirror/runFormattingInlineCarriers.js +2 -0
  304. package/dist/prosemirror/runIdentity.d.ts +28 -0
  305. package/dist/prosemirror/runIdentity.js +36 -0
  306. package/dist/prosemirror/runStyleFormatting.js +1 -1
  307. package/dist/prosemirror/schema/index.d.ts +2 -2
  308. package/dist/prosemirror/schema/marks.d.ts +23 -4
  309. package/dist/prosemirror/schema/nodes.d.ts +220 -24
  310. package/dist/prosemirror/sectionCarrier.d.ts +37 -0
  311. package/dist/prosemirror/sectionCarrier.js +40 -0
  312. package/dist/prosemirror/selectionState.d.ts +3 -0
  313. package/dist/prosemirror/selectionState.js +4 -1
  314. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +5 -4
  315. package/dist/prosemirror/styles/resolvedStyleAttrs.js +15 -13
  316. package/dist/prosemirror/tableResize.js +5 -6
  317. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +2 -0
  318. package/dist/prosemirror/trackedRunInlineAtoms.js +2 -0
  319. package/dist/prosemirror/utils/extractTrackedChanges.d.ts +10 -11
  320. package/dist/prosemirror/utils/extractTrackedChanges.js +109 -92
  321. package/dist/prosemirror/validation.js +17 -6
  322. package/dist/prosemirror/yjsDocumentMetadata.d.ts +2 -2
  323. package/dist/prosemirror/yjsDocumentMetadata.js +428 -7
  324. package/dist/prosemirror/zeroWidthAnchors.js +4 -0
  325. package/dist/style-sets/extract.js +4 -4
  326. package/dist/style-sets/stellaStyle.js +36 -23
  327. package/dist/types/colors.d.ts +2 -2
  328. package/dist/types/content.d.ts +2 -2
  329. package/dist/types/documentEnumValues.d.ts +53 -26
  330. package/dist/types/documentEnumValues.js +72 -174
  331. package/dist/types/formatting.d.ts +2 -2
  332. package/dist/types/index.d.ts +9 -2
  333. package/dist/utils/borderCss.d.ts +246 -0
  334. package/dist/utils/borderCss.js +325 -0
  335. package/dist/utils/colorResolver.d.ts +4 -3
  336. package/dist/utils/colorResolver.js +45 -76
  337. package/dist/utils/createDocument.js +24 -6
  338. package/dist/utils/findReplace.js +52 -10
  339. package/dist/utils/formatToStyle.d.ts +84 -2
  340. package/dist/utils/formatToStyle.js +133 -52
  341. package/dist/utils/headingCollector.js +3 -2
  342. package/dist/utils/mergeDocumentContent.js +5 -3
  343. package/dist/utils/paragraphFormattingMerge.js +27 -6
  344. package/dist/utils/replaceText.js +1 -1
  345. package/dist/utils/tableOperations.d.ts +5 -3
  346. package/dist/utils/tableOperations.js +14 -1
  347. package/dist/utils/tablePlacement.d.ts +7 -0
  348. package/dist/utils/tablePlacement.js +14 -0
  349. package/dist/utils/textDirectionFlow.d.ts +15 -0
  350. package/dist/utils/textDirectionFlow.js +38 -0
  351. package/dist/utils/textFormattingMerge.js +16 -4
  352. package/package.json +10 -10
  353. package/dist/ai-edits/__fixtures__/paragraphs.d.ts +0 -17
  354. package/dist/ai-edits/__fixtures__/paragraphs.js +0 -33
  355. package/dist/compare/__fixtures__/body-sequence.d.ts +0 -119
  356. package/dist/compare/__fixtures__/body-sequence.js +0 -225
  357. package/dist/compare/__fixtures__/nested-table.d.ts +0 -16
  358. package/dist/compare/__fixtures__/nested-table.js +0 -50
  359. package/dist/compare/__fixtures__/numbered-list.d.ts +0 -34
  360. package/dist/compare/__fixtures__/numbered-list.js +0 -85
  361. package/dist/docx/bookmarkPlacement.d.ts +0 -9
  362. package/dist/docx/bookmarkPlacement.js +0 -52
  363. package/dist/fonts/embeddedFontTable.d.ts +0 -45
  364. package/dist/fonts/embeddedFontTable.js +0 -80
  365. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.d.ts +0 -13
  366. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.js +0 -39
@@ -1,4 +1,5 @@
1
1
  import { applyFolioAIEditOperations, previewFolioAIEditOperations } from "./ai-edits/apply.js";
2
+ import { isNumberingReference } from "./docx/numberingReference.js";
2
3
  import { LINE_SPACING_RULE_VALUES, PARAGRAPH_ALIGNMENT_VALUES } from "./types/documentEnumValues.js";
3
4
  import { TaggedError } from "better-result";
4
5
  import { sanitizeXmlCharacters } from "@stll/docx-core";
@@ -299,7 +300,7 @@ const readClearableNumbering = ({ value, key, path }) => {
299
300
  if (!isPlainObject(candidate)) return invalidBatch(numberingPath, "expected an object or null when provided");
300
301
  assertAllowedKeys(candidate, numberingPath, ["numId", "level"]);
301
302
  const numId = readNonNegativeInteger(candidate, "numId", numberingPath);
302
- if (numId === 0) return invalidBatch(`${numberingPath}.numId`, "expected a positive integer");
303
+ if (!isNumberingReference(numId)) return invalidBatch(`${numberingPath}.numId`, "expected a positive integer");
303
304
  return {
304
305
  numId,
305
306
  level: readNonNegativeInteger(candidate, "level", numberingPath)
@@ -1,6 +1,14 @@
1
+ import { ModelledAttributes } from "./propertyElementAttributes.js";
1
2
  import { XmlElement } from "./xmlParser.js";
2
3
  import { PreservedAttribute } from "@stll/docx-core/model";
3
4
  //#region src/docx/attributeRemainder.d.ts
5
+ declare const InvalidPreservedAttributeError_base: import("better-result").TaggedErrorClass<"InvalidPreservedAttributeError">;
6
+ declare class InvalidPreservedAttributeError extends InvalidPreservedAttributeError_base<{
7
+ message: string;
8
+ name: string;
9
+ }> {}
10
+ /** Whether an attribute remainder can be emitted under a bound canonical name. */
11
+ declare const isSerializablePreservedAttribute: ({ namespace, name }: Pick<PreservedAttribute, "namespace" | "name">) => boolean;
4
12
  /**
5
13
  * The modelled set of an element whose serializer writes no attribute at all.
6
14
  *
@@ -10,6 +18,18 @@ import { PreservedAttribute } from "@stll/docx-core/model";
10
18
  * one of them gains a modelled attribute.
11
19
  */
12
20
  declare const NO_MODELLED_ATTRIBUTES: ReadonlySet<string>;
21
+ /**
22
+ * What a part's root element states rather than carries, so the remainder skips it.
23
+ *
24
+ * `mc:Ignorable` is a projection of the root's own `xmlns:*` bindings — it
25
+ * lists which of them a consumer may skip — and `serializePartElement` derives
26
+ * both from the prefixes the rebuilt body actually uses. Replaying the
27
+ * source's would name prefixes the rebuilt root does not bind, which no
28
+ * consumer accepts, and the writer appends its own, so the part would carry
29
+ * the attribute twice. This is the same rule namespace declarations already
30
+ * follow, one attribute further on.
31
+ */
32
+ declare const DERIVED_PART_ROOT_ATTRIBUTES: ReadonlySet<string>;
13
33
  type AttributeRemainderOptions = {
14
34
  /** The element, as the source wrote it. */
15
35
  element: XmlElement;
@@ -31,6 +51,19 @@ type AttributeRemainderOptions = {
31
51
  * in the model.
32
52
  */
33
53
  declare const attributeRemainder: ({ element, modelled }: AttributeRemainderOptions) => PreservedAttribute[] | undefined;
54
+ /**
55
+ * The remainder of an attribute bag, with the modelled set derived from the
56
+ * record's own fields.
57
+ *
58
+ * `w:ind`, `w:spacing`, `w:framePr`, `w:tab`, a border side and `w:shd` are
59
+ * bags rather than containers: the child dispatcher decides each of them
60
+ * whole, so an attribute the record has no field for is kept only while the
61
+ * reader takes nothing from the element at all. Passing the record's table
62
+ * from `propertyElementAttributes.ts` rather than a set spelled at the call
63
+ * site is what keeps the predicate derived from the model: a field added
64
+ * without an attribute to name does not compile.
65
+ */
66
+ declare const readAttributeBag: (element: XmlElement, modelled: ModelledAttributes<string>) => PreservedAttribute[] | undefined;
34
67
  /**
35
68
  * The element's attributes, modelled first and the remainder after them.
36
69
  *
@@ -40,4 +73,4 @@ declare const attributeRemainder: ({ element, modelled }: AttributeRemainderOpti
40
73
  */
41
74
  declare const serializePreservedAttributes: (modelled: readonly string[], preserved: readonly PreservedAttribute[] | undefined) => string[];
42
75
  //#endregion
43
- export { NO_MODELLED_ATTRIBUTES, attributeRemainder, serializePreservedAttributes };
76
+ export { DERIVED_PART_ROOT_ATTRIBUTES, InvalidPreservedAttributeError, NO_MODELLED_ATTRIBUTES, attributeRemainder, isSerializablePreservedAttribute, readAttributeBag, serializePreservedAttributes };
@@ -1,9 +1,15 @@
1
+ import { modelledAttributeNames } from "./propertyElementAttributes.js";
1
2
  import { OOXML_NAMESPACES } from "./serializer/partNamespaces.js";
2
3
  import { getLocalName, resolveAttributeNamespaceUri } from "./xmlParser.js";
4
+ import { TaggedError } from "better-result";
3
5
  import { escapeXmlAttribute } from "@stll/docx-core";
4
6
  //#region src/docx/attributeRemainder.ts
5
7
  /** Namespace URI to the prefix a rebuilt part binds for it. */
6
8
  const CANONICAL_PREFIX = new Map(Object.entries(OOXML_NAMESPACES).map(([prefix, { uri }]) => [uri, prefix]));
9
+ const XML_LOCAL_NAME = /^[\p{L}_][\p{L}\p{M}\p{N}._\-\u{00B7}\u{203F}-\u{2040}]*$/u;
10
+ var InvalidPreservedAttributeError = class extends TaggedError("InvalidPreservedAttributeError") {};
11
+ /** Whether an attribute remainder can be emitted under a bound canonical name. */
12
+ const isSerializablePreservedAttribute = ({ namespace, name }) => name !== "xmlns" && XML_LOCAL_NAME.test(name) && (namespace === void 0 || CANONICAL_PREFIX.has(namespace));
7
13
  /**
8
14
  * The modelled set of an element whose serializer writes no attribute at all.
9
15
  *
@@ -14,6 +20,18 @@ const CANONICAL_PREFIX = new Map(Object.entries(OOXML_NAMESPACES).map(([prefix,
14
20
  */
15
21
  const NO_MODELLED_ATTRIBUTES = /* @__PURE__ */ new Set();
16
22
  /**
23
+ * What a part's root element states rather than carries, so the remainder skips it.
24
+ *
25
+ * `mc:Ignorable` is a projection of the root's own `xmlns:*` bindings — it
26
+ * lists which of them a consumer may skip — and `serializePartElement` derives
27
+ * both from the prefixes the rebuilt body actually uses. Replaying the
28
+ * source's would name prefixes the rebuilt root does not bind, which no
29
+ * consumer accepts, and the writer appends its own, so the part would carry
30
+ * the attribute twice. This is the same rule namespace declarations already
31
+ * follow, one attribute further on.
32
+ */
33
+ const DERIVED_PART_ROOT_ATTRIBUTES = /* @__PURE__ */ new Set(["Ignorable"]);
34
+ /**
17
35
  * Every attribute on the element the model has no field for.
18
36
  *
19
37
  * @returns the remainder, or `undefined` when the parser read them all — an
@@ -38,6 +56,30 @@ const attributeRemainder = ({ element, modelled }) => {
38
56
  }
39
57
  return remainder.length === 0 ? void 0 : remainder;
40
58
  };
59
+ const NAMES_BY_TABLE = /* @__PURE__ */ new WeakMap();
60
+ /**
61
+ * The remainder of an attribute bag, with the modelled set derived from the
62
+ * record's own fields.
63
+ *
64
+ * `w:ind`, `w:spacing`, `w:framePr`, `w:tab`, a border side and `w:shd` are
65
+ * bags rather than containers: the child dispatcher decides each of them
66
+ * whole, so an attribute the record has no field for is kept only while the
67
+ * reader takes nothing from the element at all. Passing the record's table
68
+ * from `propertyElementAttributes.ts` rather than a set spelled at the call
69
+ * site is what keeps the predicate derived from the model: a field added
70
+ * without an attribute to name does not compile.
71
+ */
72
+ const readAttributeBag = (element, modelled) => {
73
+ let names = NAMES_BY_TABLE.get(modelled);
74
+ if (names === void 0) {
75
+ names = new Set(modelledAttributeNames(modelled));
76
+ NAMES_BY_TABLE.set(modelled, names);
77
+ }
78
+ return attributeRemainder({
79
+ element,
80
+ modelled: names
81
+ });
82
+ };
41
83
  /** The name a fragment such as `w14:paraId="1F2E"` writes. */
42
84
  const spelledName = (fragment) => fragment.slice(0, fragment.indexOf("="));
43
85
  /**
@@ -51,9 +93,13 @@ const serializePreservedAttributes = (modelled, preserved) => {
51
93
  if (preserved === void 0 || preserved.length === 0) return [...modelled];
52
94
  const written = new Set(modelled.map(spelledName));
53
95
  const fragments = [...modelled];
54
- for (const { namespace, name, value } of preserved) {
96
+ for (const attribute of preserved) {
97
+ const { namespace, name, value } = attribute;
98
+ if (!isSerializablePreservedAttribute(attribute)) throw new InvalidPreservedAttributeError({
99
+ message: "A preserved attribute must have an XML local name and a bound namespace",
100
+ name
101
+ });
55
102
  const prefix = namespace === void 0 ? void 0 : CANONICAL_PREFIX.get(namespace);
56
- if (namespace !== void 0 && prefix === void 0) continue;
57
103
  const spelling = prefix === void 0 ? name : `${prefix}:${name}`;
58
104
  if (written.has(spelling)) continue;
59
105
  written.add(spelling);
@@ -62,4 +108,4 @@ const serializePreservedAttributes = (modelled, preserved) => {
62
108
  return fragments;
63
109
  };
64
110
  //#endregion
65
- export { NO_MODELLED_ATTRIBUTES, attributeRemainder, serializePreservedAttributes };
111
+ export { DERIVED_PART_ROOT_ATTRIBUTES, InvalidPreservedAttributeError, NO_MODELLED_ATTRIBUTES, attributeRemainder, isSerializablePreservedAttribute, readAttributeBag, serializePreservedAttributes };
@@ -1,11 +1,13 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { NumberingMap } from "./numberingParser.js";
3
+ import { ParseContext } from "./parseContext.js";
3
4
  import { XmlElement } from "./xmlParser.js";
4
5
  import { StyleMap } from "./styleParser.js";
5
6
  //#region src/docx/blockContentParser.d.ts
6
7
  type ParseBlockContentOptions = {
7
8
  inHeaderFooter?: boolean;
8
9
  rootXmlns?: Record<string, string>;
10
+ context?: ParseContext | undefined;
9
11
  };
10
12
  declare const parseBlockContent: (parent: XmlElement, styles: StyleMap | null, theme: document_d_exports.Theme | null, numbering: NumberingMap | null, rels: document_d_exports.RelationshipMap | null, media: Map<string, document_d_exports.MediaFile> | null, options?: ParseBlockContentOptions) => document_d_exports.BlockContent[];
11
13
  //#endregion
@@ -1,15 +1,13 @@
1
1
  import { parseBookmarkEnd, parseBookmarkStart } from "./bookmarkParser.js";
2
- import { appendBookmarkMarkerToLastParagraphInBlocks, prependBookmarkMarkersToFirstParagraphInBlocks } from "./bookmarkPlacement.js";
3
2
  import { convertBulletToUnicode } from "./bulletMarkers.js";
4
- import { CAPTURE, OWNED_ELSEWHERE, dispatchChildren, withPreservedChildren } from "./containerChildren.js";
3
+ import { CAPTURE, dispatchChildren, ownedElsewhere, withPreservedChildren } from "./containerChildren.js";
5
4
  import { isNumberingReference } from "./numberingReference.js";
6
5
  import { formatOoxmlCounter } from "./ooxmlCounterFormatter.js";
7
6
  import { parseParagraph } from "./paragraphParser.js";
8
7
  import { enrichParagraphTextBoxes } from "./paragraphTextBoxEnrichment.js";
9
- import { parseSdtProperties } from "./sdtProperties.js";
8
+ import { captureSdtSiblingMarkers, parseSdtProperties } from "./sdtProperties.js";
10
9
  import { parseTable } from "./tableParser.js";
11
- import { captureVerbatimXml } from "./verbatimCapture.js";
12
- import { findChild, getLocalName, mergeXmlnsDeclarations, selectAlternateContentBranch } from "./xmlParser.js";
10
+ import { findWordprocessingChild, mergeXmlnsDeclarations, selectAlternateContentBranch } from "./xmlParser.js";
13
11
  //#region src/docx/blockContentParser.ts
14
12
  const computeListMarker = (paragraph, { numbering, listCounters, abstractCounters, restartedNumIds, previousList }) => {
15
13
  const listRendering = paragraph.listRendering;
@@ -89,6 +87,29 @@ const withContainerXmlns = (state, element) => ({
89
87
  rootXmlns: mergeXmlnsDeclarations(state.options?.rootXmlns ?? {}, element)
90
88
  }
91
89
  });
90
+ /**
91
+ * The two block children this walk skips, and who reads them instead.
92
+ *
93
+ * Both are read off the container element rather than met here: the body's own
94
+ * `w:sectPr` by the document parser, a cell's `w:tcPr` by the table parser.
95
+ * They are in this map because it is total over the union every block
96
+ * container shares, not because this walk reads them.
97
+ *
98
+ * Declared at module scope so the claim is registered when the module loads,
99
+ * rather than the first time a document is parsed.
100
+ */
101
+ const BLOCK_CHILD_OWNERS = {
102
+ sectPr: ownedElsewhere({
103
+ container: "block-content",
104
+ child: "sectPr",
105
+ reader: "documentParser#parseDocumentBody"
106
+ }),
107
+ tcPr: ownedElsewhere({
108
+ container: "block-content",
109
+ child: "tcPr",
110
+ reader: "tableParser#parseTableCell"
111
+ })
112
+ };
92
113
  const parseBlockContent = (parent, styles, theme, numbering, rels, media, options) => parseBlockContentWithState(parent, styles, theme, numbering, rels, media, {
93
114
  listCounters: /* @__PURE__ */ new Map(),
94
115
  abstractCounters: /* @__PURE__ */ new Map(),
@@ -105,11 +126,10 @@ const parseBlockContent = (parent, styles, theme, numbering, rels, media, option
105
126
  });
106
127
  const parseBlockContentWithState = (parent, styles, theme, numbering, rels, media, state) => {
107
128
  const modelled = [];
108
- const pendingBookmarkMarkers = [];
109
- const content = withPreservedChildren(modelled, dispatchChildren({
129
+ return withPreservedChildren(modelled, dispatchChildren({
110
130
  element: parent,
111
131
  container: "block-content",
112
- modelledCount: () => modelled.length,
132
+ capturePosition: () => modelled.length,
113
133
  undeclared: { AlternateContent: (child) => {
114
134
  const selectedBranch = selectAlternateContentBranch(child);
115
135
  if (!selectedBranch) return;
@@ -117,9 +137,11 @@ const parseBlockContentWithState = (parent, styles, theme, numbering, rels, medi
117
137
  } },
118
138
  handlers: {
119
139
  p: (child) => {
120
- const paragraph = parseParagraph(child, styles, theme, numbering, rels, media, state.options);
121
- prependPendingBookmarkMarkers(paragraph, pendingBookmarkMarkers);
122
- enrichParagraphTextBoxes(paragraph, child, styles, theme, numbering, rels, media, parseTable);
140
+ const paragraph = parseParagraph(child, styles, theme, numbering, rels, media, {
141
+ ...state.options,
142
+ runConsolidation: "deferred"
143
+ });
144
+ enrichParagraphTextBoxes(paragraph, child, styles, theme, numbering, rels, media, parseTable, state.options?.context);
123
145
  computeListMarker(paragraph, {
124
146
  numbering,
125
147
  listCounters: state.listCounters,
@@ -132,22 +154,18 @@ const parseBlockContentWithState = (parent, styles, theme, numbering, rels, medi
132
154
  tbl: (child) => {
133
155
  const table = parseTable(child, styles, theme, numbering, rels, media, state.options);
134
156
  if (!table) return;
135
- if (prependBookmarkMarkersToFirstParagraphInBlocks([table], pendingBookmarkMarkers)) pendingBookmarkMarkers.length = 0;
136
157
  modelled.push(table);
137
158
  },
138
159
  sdt: (child) => {
139
- const blockSdt = parseBlockSdt(child, styles, theme, numbering, rels, media, state);
140
- if (prependBookmarkMarkersToFirstParagraphInBlocks(blockSdt.content, pendingBookmarkMarkers)) pendingBookmarkMarkers.length = 0;
141
- modelled.push(blockSdt);
160
+ modelled.push(parseBlockSdt(child, styles, theme, numbering, rels, media, state));
142
161
  },
143
162
  bookmarkStart: (child) => {
144
- collectBookmarkMarker(child, "bookmarkStart", modelled, pendingBookmarkMarkers);
163
+ modelled.push(parseBookmarkStart(child));
145
164
  },
146
165
  bookmarkEnd: (child) => {
147
- collectBookmarkMarker(child, "bookmarkEnd", modelled, pendingBookmarkMarkers);
166
+ modelled.push(parseBookmarkEnd(child));
148
167
  },
149
- sectPr: OWNED_ELSEWHERE,
150
- tcPr: OWNED_ELSEWHERE,
168
+ ...BLOCK_CHILD_OWNERS,
151
169
  altChunk: CAPTURE,
152
170
  commentRangeEnd: CAPTURE,
153
171
  commentRangeStart: CAPTURE,
@@ -176,15 +194,10 @@ const parseBlockContentWithState = (parent, styles, theme, numbering, rels, medi
176
194
  type: "preservedBlock",
177
195
  xml
178
196
  }));
179
- if (pendingBookmarkMarkers.length > 0) content.push({
180
- type: "paragraph",
181
- content: [...pendingBookmarkMarkers]
182
- });
183
- return content;
184
197
  };
185
198
  const parseBlockSdt = (child, styles, theme, numbering, rels, media, state) => {
186
- const sdtContent = findChild(child, "w", "sdtContent");
187
- const properties = parseSdtProperties(findChild(child, "w", "sdtPr"), findChild(child, "w", "sdtEndPr"));
199
+ const sdtContent = findWordprocessingChild(child, "sdtContent");
200
+ const properties = parseSdtProperties(findWordprocessingChild(child, "sdtPr"), findWordprocessingChild(child, "sdtEndPr"));
188
201
  const captured = captureSdtSiblingMarkers(child);
189
202
  if (captured.before.length > 0) properties.rawSdtChildrenBeforeContent = captured.before;
190
203
  if (captured.after.length > 0) properties.rawSdtChildrenAfterContent = captured.after;
@@ -194,46 +207,5 @@ const parseBlockSdt = (child, styles, theme, numbering, rels, media, state) => {
194
207
  content: sdtContent ? parseBlockContentWithState(sdtContent, styles, theme, numbering, rels, media, withContainerXmlns(withContainerXmlns(state, child), sdtContent)) : []
195
208
  };
196
209
  };
197
- const collectBookmarkMarker = (child, localName, content, pending) => {
198
- const marker = localName === "bookmarkStart" ? parseBookmarkStart(child) : parseBookmarkEnd(child);
199
- if (!appendBookmarkMarkerToLastParagraphInBlocks(content, marker)) pending.push(marker);
200
- };
201
- /**
202
- * Walk a `<w:sdt>` element's direct children and return the verbatim XML
203
- * for every child that is NOT `<w:sdtPr>`, `<w:sdtEndPr>`, or
204
- * `<w:sdtContent>` — split by position relative to sdtContent.
205
- *
206
- * Per MS-OE376 §2.5.2.30, Word emits 16 range-marker elements (bookmark,
207
- * comment, custom XML, tracked-change ranges) as direct sdt siblings of
208
- * sdtContent. Without preserving them, a comment thread or tracked
209
- * change that crosses an SDT boundary loses a delimiter when folio
210
- * serializes the parsed model back out.
211
- */
212
- const captureSdtSiblingMarkers = (sdt) => {
213
- const beforeParts = [];
214
- const afterParts = [];
215
- let sawContent = false;
216
- for (const ch of sdt.elements ?? []) {
217
- if (ch.type !== "element" || !ch.name) continue;
218
- const local = getLocalName(ch.name);
219
- if (local === "sdtPr" || local === "sdtEndPr") continue;
220
- if (local === "sdtContent") {
221
- sawContent = true;
222
- continue;
223
- }
224
- const xml = captureVerbatimXml(ch);
225
- if (sawContent) afterParts.push(xml);
226
- else beforeParts.push(xml);
227
- }
228
- return {
229
- before: beforeParts.join(""),
230
- after: afterParts.join("")
231
- };
232
- };
233
- const prependPendingBookmarkMarkers = (paragraph, pendingBookmarkMarkers) => {
234
- if (pendingBookmarkMarkers.length === 0) return;
235
- paragraph.content.unshift(...pendingBookmarkMarkers);
236
- pendingBookmarkMarkers.length = 0;
237
- };
238
210
  //#endregion
239
211
  export { parseBlockContent };
@@ -31,7 +31,9 @@ const collectBlockTexts = (blocks) => {
31
31
  case "blockSdt":
32
32
  texts.push(...collectBlockTexts(block.content));
33
33
  break;
34
- case "preservedBlock": break;
34
+ case "preservedBlock":
35
+ case "bookmarkStart":
36
+ case "bookmarkEnd": break;
35
37
  default: panic(`Unsupported block in plain-text extraction: ${JSON.stringify(block)}`);
36
38
  }
37
39
  return texts;
@@ -1,6 +1,8 @@
1
- import { BorderStyleSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
1
+ import { readAttributeBag } from "./attributeRemainder.js";
2
+ import { BORDER_ATTRIBUTES } from "./propertyElementAttributes.js";
3
+ import { parseThemeColorAttribute } from "./themeColorAttribute.js";
2
4
  import { getAttribute, parseNumericAttribute, parseOnOffAttribute } from "./xmlParser.js";
3
- import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
5
+ import { PARSE_WARNING_CODES, borderStyleFrom, isBorderStyle } from "@stll/docx-core/model";
4
6
  //#region src/docx/borderParser.ts
5
7
  /**
6
8
  * The one reader for `CT_Border`, shared by the paragraph (`w:pBdr`), style,
@@ -9,21 +11,27 @@ import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
9
11
  * `w:val` is `ST_Border`, whose 193 members include two distinct "no border"
10
12
  * tokens: `nil` and `none`. They are not interchangeable downstream, and an
11
13
  * explicit one overrides a border inherited from the container, so the member
12
- * the author wrote is preserved exactly. Members outside the model's known
13
- * union survive verbatim rather than collapsing to a default, which is how the
14
- * repo already treats `w:numFmt`, `w:suff` and `w:tab`.
14
+ * the author wrote is preserved exactly. A token outside the enumeration is
15
+ * kept verbatim and reported, which is how the repo already treats `w:numFmt`,
16
+ * `w:suff` and `w:tab`.
15
17
  */
16
- const parseBorderColor = (border) => {
18
+ /** `ST_HexColor`'s reserved "let the consumer decide" token, as `shadingParser` spells it. */
19
+ const AUTOMATIC_COLOR = "auto";
20
+ const parseBorderColor = (border, context) => {
17
21
  const rgb = getAttribute(border, "w", "color");
18
22
  const themeColor = getAttribute(border, "w", "themeColor");
19
23
  const themeTint = getAttribute(border, "w", "themeTint");
20
24
  const themeShade = getAttribute(border, "w", "themeShade");
21
25
  if (rgb === null && themeColor === null && themeTint === null && themeShade === null) return;
22
26
  const color = {};
23
- if (rgb === "auto") color.auto = true;
27
+ if (rgb === AUTOMATIC_COLOR) color.auto = true;
24
28
  else if (rgb) color.rgb = rgb;
25
- const validatedThemeColor = narrowEnum(themeColor, ThemeColorSlotSchema);
26
- if (validatedThemeColor) color.themeColor = validatedThemeColor;
29
+ const parsedThemeColor = parseThemeColorAttribute({
30
+ raw: themeColor,
31
+ element: border.name ?? "border",
32
+ context
33
+ });
34
+ if (parsedThemeColor !== void 0) color.themeColor = parsedThemeColor;
27
35
  if (themeTint) color.themeTint = themeTint;
28
36
  if (themeShade) color.themeShade = themeShade;
29
37
  return color;
@@ -44,8 +52,13 @@ function parseBorderSpec(border, context) {
44
52
  });
45
53
  return;
46
54
  }
47
- const spec = { style: narrowEnum(rawStyle, BorderStyleSchema) ?? rawStyle };
48
- const color = parseBorderColor(border);
55
+ if (!isBorderStyle(rawStyle)) context?.warn({
56
+ code: PARSE_WARNING_CODES.borderStyleOutsideEnum,
57
+ element: border.name ?? "border",
58
+ value: rawStyle
59
+ });
60
+ const spec = { style: borderStyleFrom(rawStyle) };
61
+ const color = parseBorderColor(border, context);
49
62
  if (color) spec.color = color;
50
63
  const size = parseNumericAttribute(border, "w", "sz");
51
64
  if (size !== void 0) spec.size = size;
@@ -65,6 +78,8 @@ function parseBorderSpec(border, context) {
65
78
  if (bottomLeftArtRelationshipId) spec.bottomLeftArtRelationshipId = bottomLeftArtRelationshipId;
66
79
  const bottomRightArtRelationshipId = getAttribute(border, "r", "bottomRight")?.trim();
67
80
  if (bottomRightArtRelationshipId) spec.bottomRightArtRelationshipId = bottomRightArtRelationshipId;
81
+ const preservedAttributes = readAttributeBag(border, BORDER_ATTRIBUTES);
82
+ if (preservedAttributes) spec.preservedAttributes = preservedAttributes;
68
83
  return spec;
69
84
  }
70
85
  //#endregion
@@ -1,24 +1,16 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
+ import { OutlineLevel } from "@stll/docx-core/model";
2
3
  //#region src/docx/builtInStyles.d.ts
3
4
  /**
4
- * The tenth `w:outlineLvl` value. 17.3.1.20: "the val attribute … can be from
5
- * 0 to 9, where 9 specifically indicates that there is no outline level
6
- * specifically applied to this paragraph." It is a deliberate "not a heading",
7
- * not a tenth level. Every range test goes through
8
- * {@link isHeadingOutlineLevel} so the reserved value keeps one meaning across
9
- * the codebase.
10
- *
11
- * The same clause adds that an omitted element "is assumed to be 9". That
5
+ * 17.3.1.20 adds that an omitted `w:outlineLvl` "is assumed to be 9". That
12
6
  * default cannot be applied to a *style* definition, because 17.7.1 tells
13
7
  * producers not to write a property "already been set by a previous level of
14
8
  * the style hierarchy": a document that names a style `heading 1` and omits
15
9
  * the level is inheriting the consumer's built-in definition, which carries
16
10
  * level 0. An absent level therefore means "unspecified, ask the name", and
17
- * only a written 9 means body text.
11
+ * only {@link BODY_TEXT_OUTLINE_LEVEL} means body text — which is why the
12
+ * model keeps absence and the body-text arm apart.
18
13
  */
19
- declare const BODY_TEXT_OUTLINE_LEVEL = 9;
20
- /** True when an outline level names a heading rather than body text. */
21
- declare const isHeadingOutlineLevel: (level: number | null | undefined) => level is number;
22
14
  /**
23
15
  * Compare style names the way producers actually write them. The corpus shows
24
16
  * both `heading 1` (Annex L, 94.8%) and `Heading 1` (5.2%), and LibreOffice
@@ -84,8 +76,8 @@ declare const builtInTableOfContentsStyleName: (level: number) => string;
84
76
  * quadratic.
85
77
  */
86
78
  type BuiltInStyleIndex = {
87
- /** The style's effective `w:outlineLvl`, including 9, or undefined. */
88
- outlineLevelOf: (styleId: string | null | undefined) => number | undefined;
79
+ /** The style's effective `w:outlineLvl`, body text included, or undefined. */
80
+ outlineLevelOf: (styleId: string | null | undefined) => OutlineLevel | undefined;
89
81
  /** The zero-based level a built-in heading *name* implies, or undefined. */
90
82
  headingLevelFromNameOf: (styleId: string | null | undefined) => number | undefined;
91
83
  /** The built-in this style is, by name, or undefined for a custom style. */
@@ -113,7 +105,7 @@ declare const EMPTY_BUILT_IN_STYLE_INDEX: BuiltInStyleIndex;
113
105
  */
114
106
  type ParagraphOutlineSource = {
115
107
  styleId?: string | null | undefined;
116
- outlineLevel?: number | null | undefined;
108
+ outlineLevel?: OutlineLevel | null | undefined;
117
109
  };
118
110
  /**
119
111
  * The heading level a paragraph carries, zero-based (`heading 1` is 0), or
@@ -162,4 +154,4 @@ declare const resolveHeadingLevel: (paragraph: ParagraphOutlineSource, index: Bu
162
154
  /** True when the paragraph's style is Word's `Quote` or `Intense Quote`. */
163
155
  declare const isQuoteStyle: (styleId: string | null | undefined, index: BuiltInStyleIndex) => boolean;
164
156
  //#endregion
165
- export { BODY_TEXT_OUTLINE_LEVEL, BUILT_IN_STYLE_NAME, BuiltInStyleIndex, EMPTY_BUILT_IN_STYLE_INDEX, ParagraphOutlineSource, builtInHeadingStyleName, builtInTableOfContentsStyleName, createBuiltInStyleIndex, isHeadingOutlineLevel, isQuoteStyle, normalizeStyleName, resolveHeadingLevel };
157
+ export { BUILT_IN_STYLE_NAME, BuiltInStyleIndex, EMPTY_BUILT_IN_STYLE_INDEX, ParagraphOutlineSource, builtInHeadingStyleName, builtInTableOfContentsStyleName, createBuiltInStyleIndex, isQuoteStyle, normalizeStyleName, resolveHeadingLevel };
@@ -1,26 +1,57 @@
1
1
  import { BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME, resolveDefaultParagraphStyle } from "./defaultParagraphStyle.js";
2
+ import { headingLevelOf } from "@stll/docx-core/model";
2
3
  //#region src/docx/builtInStyles.ts
3
4
  /**
4
- * The tenth `w:outlineLvl` value. 17.3.1.20: "the val attribute … can be from
5
- * 0 to 9, where 9 specifically indicates that there is no outline level
6
- * specifically applied to this paragraph." It is a deliberate "not a heading",
7
- * not a tenth level. Every range test goes through
8
- * {@link isHeadingOutlineLevel} so the reserved value keeps one meaning across
9
- * the codebase.
5
+ * Whether a paragraph is a heading, and of which level, without reading the
6
+ * style id.
10
7
  *
11
- * The same clause adds that an omitted element "is assumed to be 9". That
8
+ * A style id is opaque. ECMA-376 17.7.4.17 says a style id "can be assigned in
9
+ * any manner desired" and only requires it to be unique within the document,
10
+ * and Word fills it by stripping spaces and non-ASCII characters out of the
11
+ * *localized* UI name. The same built-in heading therefore arrives as
12
+ * `Heading1`, `berschrift1` (de), `Nadpis1` (cs), `Titre1` (fr), `Nagwek1`
13
+ * (pl), `Cmsor1` (hu), `Ttulo1` (es), `Overskrift1` (da) or a bare `1`.
14
+ * Matching the id finds English Word output and nothing else, the same trap
15
+ * `defaultParagraphStyle.ts` documents for `Normal`.
16
+ *
17
+ * Two signals survive localisation, in this order:
18
+ *
19
+ * 1. The effective `w:outlineLvl` — direct paragraph formatting, else the
20
+ * style chain (`styleParser` flattens `w:basedOn` into `style.pPr` per
21
+ * 17.7.1). 17.3.1.20 gives it the range 0..9 and says it "shall be used to
22
+ * calculate the TOC field", which is what a `TOC \u` field and the
23
+ * navigation pane read. So a custom style with an outline level *is* a
24
+ * heading, and a heading-named style reset to
25
+ * {@link BODY_TEXT_OUTLINE_LEVEL} is *not* (folio's own `TOCHeading`, based
26
+ * on `Heading1`, does exactly that).
27
+ * 2. The style's `w:name`. Part 1 has no normative list of built-in names, but
28
+ * it keys latent styles by name alone: a `w:lsdException` carries no style
29
+ * id, and 17.7.4.8 defines its `w:name` as "the primary name for the style
30
+ * which shall inherit this set of latent style property exceptions",
31
+ * ignored when "the current application does not know of an internal
32
+ * primary style with the current name". Annex L writes those names in
33
+ * English (`heading 1`…`heading 9`) with no locale qualification.
34
+ *
35
+ * The id is never a signal on its own.
36
+ *
37
+ * Measured over the 5,341-file public corpus: 207 files define a heading whose
38
+ * id is not `HeadingN` while the name is English, covering 123 distinct ids;
39
+ * only 4 documents localise the *name*, all ODF→OOXML exports (LibreOffice
40
+ * writing its ODF display names verbatim). Names are not case-stable (5.2% are
41
+ * `Heading 1` rather than the Annex L `heading 1`) and not space-stable
42
+ * (LibreOffice 25.8 writes `Heading1`, and `IntenseQuote` for `Intense
43
+ * Quote`), which is why {@link normalizeStyleName} ignores both.
44
+ */
45
+ /**
46
+ * 17.3.1.20 adds that an omitted `w:outlineLvl` "is assumed to be 9". That
12
47
  * default cannot be applied to a *style* definition, because 17.7.1 tells
13
48
  * producers not to write a property "already been set by a previous level of
14
49
  * the style hierarchy": a document that names a style `heading 1` and omits
15
50
  * the level is inheriting the consumer's built-in definition, which carries
16
51
  * level 0. An absent level therefore means "unspecified, ask the name", and
17
- * only a written 9 means body text.
52
+ * only {@link BODY_TEXT_OUTLINE_LEVEL} means body text — which is why the
53
+ * model keeps absence and the body-text arm apart.
18
54
  */
19
- const BODY_TEXT_OUTLINE_LEVEL = 9;
20
- /** The highest `w:outlineLvl` that still names a heading (outline level nine). */
21
- const MAX_HEADING_OUTLINE_LEVEL = 8;
22
- /** True when an outline level names a heading rather than body text. */
23
- const isHeadingOutlineLevel = (level) => typeof level === "number" && Number.isInteger(level) && level >= 0 && level <= MAX_HEADING_OUTLINE_LEVEL;
24
55
  /**
25
56
  * Compare style names the way producers actually write them. The corpus shows
26
57
  * both `heading 1` (Annex L, 94.8%) and `Heading 1` (5.2%), and LibreOffice
@@ -118,6 +149,11 @@ const inheritedOutlineLevel = (style, styleById) => {
118
149
  current = current.basedOn === void 0 ? void 0 : styleById.get(current.basedOn);
119
150
  }
120
151
  };
152
+ /** The level a heading style is indexed under, or undefined if it is not one. */
153
+ const headingLevelForIndex = (namedLevel, statedLevel) => {
154
+ if (namedLevel === void 0) return;
155
+ return statedLevel === void 0 ? namedLevel : headingLevelOf(statedLevel);
156
+ };
121
157
  const createBuiltInStyleIndex = (styles, docDefaults) => {
122
158
  const styleIdByHeadingLevel = /* @__PURE__ */ new Map();
123
159
  const styleIdByTableOfContentsLevel = /* @__PURE__ */ new Map();
@@ -136,8 +172,9 @@ const createBuiltInStyleIndex = (styles, docDefaults) => {
136
172
  for (const style of paragraphStyles) {
137
173
  if (style.name === void 0) continue;
138
174
  const namedLevel = headingOutlineLevelFromStyleName(style.name);
139
- const headingLevel = namedLevel === void 0 ? void 0 : inheritedOutlineLevel(style, styleById) ?? docDefaultOutlineLevel ?? namedLevel;
140
- if (headingLevel !== void 0 && isHeadingOutlineLevel(headingLevel) && !styleIdByHeadingLevel.has(headingLevel)) {
175
+ const statedLevel = inheritedOutlineLevel(style, styleById) ?? docDefaultOutlineLevel;
176
+ const headingLevel = headingLevelForIndex(namedLevel, statedLevel);
177
+ if (headingLevel !== void 0 && !styleIdByHeadingLevel.has(headingLevel)) {
141
178
  styleIdByHeadingLevel.set(headingLevel, style.styleId);
142
179
  continue;
143
180
  }
@@ -227,7 +264,7 @@ const EMPTY_BUILT_IN_STYLE_INDEX = createBuiltInStyleIndex([]);
227
264
  */
228
265
  const resolveHeadingLevel = (paragraph, index) => {
229
266
  const effective = paragraph.outlineLevel ?? index.outlineLevelOf(paragraph.styleId);
230
- if (effective !== null && effective !== void 0) return isHeadingOutlineLevel(effective) ? effective : void 0;
267
+ if (effective !== null && effective !== void 0) return headingLevelOf(effective);
231
268
  return index.headingLevelFromNameOf(paragraph.styleId) ?? index.undefinedBuiltInHeadingLevelOf(paragraph.styleId);
232
269
  };
233
270
  /** True when the paragraph's style is Word's `Quote` or `Intense Quote`. */
@@ -236,4 +273,4 @@ const isQuoteStyle = (styleId, index) => {
236
273
  return name === BUILT_IN_STYLE_NAME.quote || name === BUILT_IN_STYLE_NAME.intenseQuote;
237
274
  };
238
275
  //#endregion
239
- export { BODY_TEXT_OUTLINE_LEVEL, BUILT_IN_STYLE_NAME, EMPTY_BUILT_IN_STYLE_INDEX, builtInHeadingStyleName, builtInTableOfContentsStyleName, createBuiltInStyleIndex, isHeadingOutlineLevel, isQuoteStyle, normalizeStyleName, resolveHeadingLevel };
276
+ export { BUILT_IN_STYLE_NAME, EMPTY_BUILT_IN_STYLE_INDEX, builtInHeadingStyleName, builtInTableOfContentsStyleName, createBuiltInStyleIndex, isQuoteStyle, normalizeStyleName, resolveHeadingLevel };
@@ -19,7 +19,7 @@ const visitCommentMarkers = (blocks, visit) => {
19
19
  for (const row of block.rows) for (const cell of row.cells) visitBlocks(cell.content);
20
20
  return;
21
21
  }
22
- if (block.type === "preservedBlock") return;
22
+ if (block.type !== "blockSdt") return;
23
23
  visitBlocks(block.content);
24
24
  };
25
25
  const visitBlocks = (nested) => {
@@ -3,7 +3,7 @@ import { CAPTURE, dispatchChildren } from "./containerChildren.js";
3
3
  import { PARA_ID_NAMESPACE_URIS, paraIdAttribute, paraIdParentAttribute } from "./paraIdAttribute.js";
4
4
  import { parseParagraph } from "./paragraphParser.js";
5
5
  import { cloneParagraphWithPropertySource } from "./paragraphPropertySource.js";
6
- import { parseRunProperties } from "./runParser.js";
6
+ import { RUN_PROPERTY_OWNERS, parseRunProperties } from "./runParser.js";
7
7
  import { findChild, getAttribute, getAttributeByNamespaceUri, getChildElements, getLocalName, parseOnOffValue, parseXml } from "./xmlParser.js";
8
8
  import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
9
9
  //#region src/docx/commentParser.ts
@@ -36,7 +36,7 @@ const normalizeFirstCommentParagraph = (paragraphElement, paragraph, theme) => {
36
36
  const firstContentElement = getChildElements(paragraphElement).find((element) => getLocalName(element.name) !== "pPr");
37
37
  if (!firstContentElement || getLocalName(firstContentElement.name) !== "r" || !findChild(firstContentElement, "w", "annotationRef")) return { paragraph };
38
38
  const runProperties = findChild(firstContentElement, "w", "rPr");
39
- const annotationReferenceFormatting = normalizeAnnotationReferenceFormatting(runProperties ? parseRunProperties(runProperties, theme) : void 0);
39
+ const annotationReferenceFormatting = normalizeAnnotationReferenceFormatting(runProperties ? parseRunProperties(runProperties, theme, RUN_PROPERTY_OWNERS.standalone) : void 0);
40
40
  const firstParsedContent = paragraph.content.at(0);
41
41
  return {
42
42
  paragraph: firstParsedContent?.type === "run" && firstParsedContent.content.every((item) => item.type === "preservedXml" && item.text === "") ? cloneParagraphWithPropertySource(paragraph, { content: paragraph.content.slice(1) }) : paragraph,
@@ -140,7 +140,7 @@ function parseComments(commentsXml, styles, theme, rels, media, commentsExtensib
140
140
  const preserved = dispatchChildren({
141
141
  element: child,
142
142
  container: "w:comment",
143
- modelledCount: () => paragraphs.length,
143
+ capturePosition: () => paragraphs.length,
144
144
  handlers: {
145
145
  p: (contentChild) => {
146
146
  const paragraph = parseParagraph(contentChild, styles, theme, null, rels, media);
@@ -147,7 +147,7 @@ const withoutOrphanBlockMarkers = (blocks, validCommentIds) => {
147
147
  const withoutOrphanBlockMarker = (block, validCommentIds) => {
148
148
  if (block.type === "paragraph") return withoutOrphanParagraphMarkers(block, validCommentIds);
149
149
  if (block.type === "table") return withoutOrphanTableMarkers(block, validCommentIds);
150
- if (block.type === "preservedBlock") return block;
150
+ if (block.type !== "blockSdt") return block;
151
151
  const content = withoutOrphanBlockMarkers(block.content, validCommentIds);
152
152
  if (!content) return block;
153
153
  return {