@stll/folio-core 0.52.0 → 0.54.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 (389) hide show
  1. package/README.md +23 -0
  2. package/dist/ai-edits/apply.d.ts +26 -1
  3. package/dist/ai-edits/apply.js +1779 -141
  4. package/dist/ai-edits/batch-claims.d.ts +145 -0
  5. package/dist/ai-edits/batch-claims.js +275 -0
  6. package/dist/ai-edits/blockRange.js +9 -3
  7. package/dist/ai-edits/character-boundaries.d.ts +43 -0
  8. package/dist/ai-edits/character-boundaries.js +95 -0
  9. package/dist/ai-edits/clean-text.d.ts +33 -3
  10. package/dist/ai-edits/clean-text.js +52 -6
  11. package/dist/ai-edits/comment-lifecycle.d.ts +18 -0
  12. package/dist/ai-edits/comment-lifecycle.js +52 -0
  13. package/dist/ai-edits/headless.d.ts +91 -7
  14. package/dist/ai-edits/headless.js +520 -51
  15. package/dist/ai-edits/index.d.ts +2 -1
  16. package/dist/ai-edits/index.js +2 -1
  17. package/dist/ai-edits/minimal-replacement.d.ts +21 -6
  18. package/dist/ai-edits/minimal-replacement.js +134 -15
  19. package/dist/ai-edits/newListNumbering.d.ts +23 -0
  20. package/dist/ai-edits/newListNumbering.js +94 -0
  21. package/dist/ai-edits/note-references.d.ts +96 -0
  22. package/dist/ai-edits/note-references.js +139 -0
  23. package/dist/ai-edits/pending-suggestions.d.ts +79 -0
  24. package/dist/ai-edits/pending-suggestions.js +306 -0
  25. package/dist/ai-edits/read.d.ts +6 -4
  26. package/dist/ai-edits/read.js +113 -50
  27. package/dist/ai-edits/result-validation.d.ts +29 -0
  28. package/dist/ai-edits/result-validation.js +164 -0
  29. package/dist/ai-edits/revisionStretches.d.ts +17 -0
  30. package/dist/ai-edits/revisionStretches.js +80 -0
  31. package/dist/ai-edits/snapshot.d.ts +36 -3
  32. package/dist/ai-edits/snapshot.js +180 -25
  33. package/dist/ai-edits/table-cell-mutations.d.ts +4 -2
  34. package/dist/ai-edits/table-cell-mutations.js +6 -2
  35. package/dist/ai-edits/table-geometry.d.ts +1 -1
  36. package/dist/ai-edits/table-row-column-mutations.d.ts +44 -17
  37. package/dist/ai-edits/table-row-column-mutations.js +86 -34
  38. package/dist/ai-edits/types.d.ts +155 -16
  39. package/dist/compare/compare.d.ts +1 -1
  40. package/dist/compare/compare.js +65 -16
  41. package/dist/compare/content-alignment.d.ts +5 -1
  42. package/dist/compare/content-alignment.js +52 -34
  43. package/dist/compare/content-types.d.ts +7 -0
  44. package/dist/compare/content.d.ts +4 -1
  45. package/dist/compare/content.js +6 -1
  46. package/dist/compare/formatting.js +2 -1
  47. package/dist/compare/inline-atoms.d.ts +21 -4
  48. package/dist/compare/inline-atoms.js +138 -16
  49. package/dist/compare/inline-provenance.js +1 -1
  50. package/dist/compare/plan.js +10 -5
  51. package/dist/compare/scenario.js +14 -3
  52. package/dist/compare/section-boundary-properties.js +1 -1
  53. package/dist/compare/types.d.ts +4 -2
  54. package/dist/compare/types.js +2 -1
  55. package/dist/compare/verification.d.ts +1 -1
  56. package/dist/compare/verification.js +15 -3
  57. package/dist/controller/committedLayoutDiff.d.ts +25 -0
  58. package/dist/controller/committedLayoutDiff.js +71 -0
  59. package/dist/controller/contentControlWidgetController.d.ts +1 -1
  60. package/dist/controller/folioEditor.d.ts +1 -1
  61. package/dist/controller/fontReadiness.d.ts +70 -3
  62. package/dist/controller/fontReadiness.js +100 -10
  63. package/dist/controller/headerFooterEditorManager.js +6 -1
  64. package/dist/controller/layoutPipeline.d.ts +12 -10
  65. package/dist/controller/layoutPipeline.js +65 -11
  66. package/dist/controller/layoutRunOptions.d.ts +24 -0
  67. package/dist/controller/layoutRunOptions.js +17 -0
  68. package/dist/controller/layoutScheduler.d.ts +19 -14
  69. package/dist/controller/layoutScheduler.js +15 -12
  70. package/dist/controller/layoutSession.d.ts +26 -2
  71. package/dist/controller/layoutSession.js +1 -1
  72. package/dist/controller/noteEditorManager.js +8 -3
  73. package/dist/document-operations.d.ts +11 -2
  74. package/dist/document-operations.js +230 -21
  75. package/dist/docx/altChunk.d.ts +8 -0
  76. package/dist/docx/altChunk.js +17 -0
  77. package/dist/docx/archiveInflation.d.ts +127 -0
  78. package/dist/docx/archiveInflation.js +181 -0
  79. package/dist/docx/attributeRemainder.d.ts +1 -1
  80. package/dist/docx/blockContentParser.d.ts +64 -1
  81. package/dist/docx/blockContentParser.js +17 -4
  82. package/dist/docx/blockCustomXmlShell.d.ts +7 -0
  83. package/dist/docx/blockCustomXmlShell.js +14 -0
  84. package/dist/docx/blockPlainText.js +7 -0
  85. package/dist/docx/commentAnchorIndex.js +1 -1
  86. package/dist/docx/commentRangeIntegrity.js +8 -3
  87. package/dist/docx/commentReferenceNormalization.js +1 -1
  88. package/dist/docx/commentReplyMarkers.js +20 -1
  89. package/dist/docx/compatibility.d.ts +1 -1
  90. package/dist/docx/compatibility.js +34 -13
  91. package/dist/docx/containerChildren.gen.d.ts +1 -1
  92. package/dist/docx/containerChildren.gen.js +1 -0
  93. package/dist/docx/documentParser.js +12 -12
  94. package/dist/docx/drawingIdNormalization.d.ts +3 -1
  95. package/dist/docx/drawingIdNormalization.js +6 -1
  96. package/dist/docx/ensureParaIds.js +119 -97
  97. package/dist/docx/footnoteParser.js +8 -4
  98. package/dist/docx/headerFooterParser.js +3 -3
  99. package/dist/docx/headerFooterReferenceNormalization.d.ts +20 -1
  100. package/dist/docx/headerFooterReferenceNormalization.js +52 -27
  101. package/dist/docx/hyperlinkParser.d.ts +1 -1
  102. package/dist/docx/index.d.ts +1 -1
  103. package/dist/docx/listNumberingInstances.d.ts +59 -0
  104. package/dist/docx/listNumberingInstances.js +249 -0
  105. package/dist/docx/metadataPrivacy.js +24 -1
  106. package/dist/docx/normalizeBaseDirection.js +2 -1
  107. package/dist/docx/noteReferenceMark.d.ts +15 -0
  108. package/dist/docx/noteReferenceMark.js +48 -0
  109. package/dist/docx/opaqueCarrier.d.ts +7 -0
  110. package/dist/docx/opaqueCarrier.js +38 -0
  111. package/dist/docx/packageParts.js +4 -1
  112. package/dist/docx/paragraphParser.js +96 -27
  113. package/dist/docx/paragraphPropertySource.d.ts +4 -2
  114. package/dist/docx/paragraphPropertySource.js +10 -2
  115. package/dist/docx/paragraphTraversal.js +1 -0
  116. package/dist/docx/parseWarningMessage.js +4 -1
  117. package/dist/docx/parser.js +175 -22
  118. package/dist/docx/rezip.js +31 -7
  119. package/dist/docx/sdtProperties.js +1 -1
  120. package/dist/docx/sdtPropertiesPatch.js +3 -0
  121. package/dist/docx/selectiveSave.js +16 -9
  122. package/dist/docx/selectiveXmlPatch.d.ts +3 -1
  123. package/dist/docx/selectiveXmlPatch.js +186 -39
  124. package/dist/docx/serializer/blockCustomXmlSerializer.d.ts +5 -0
  125. package/dist/docx/serializer/blockCustomXmlSerializer.js +4 -0
  126. package/dist/docx/serializer/documentSerializer.js +2 -0
  127. package/dist/docx/serializer/headerFooterSerializer.js +2 -0
  128. package/dist/docx/serializer/noteSerializer.js +3 -1
  129. package/dist/docx/serializer/paragraphSerializer.js +33 -9
  130. package/dist/docx/serializer/tableSerializer.js +25 -38
  131. package/dist/docx/server/boundedArchive.d.ts +8 -13
  132. package/dist/docx/server/boundedArchive.js +70 -59
  133. package/dist/docx/server/createBilingualDocument.js +3 -3
  134. package/dist/docx/server/extractDocxText.d.ts +8 -2
  135. package/dist/docx/server/extractDocxText.js +2 -2
  136. package/dist/docx/server/validateDocxConformance.d.ts +1 -1
  137. package/dist/docx/server/validateDocxConformance.js +1 -0
  138. package/dist/docx/tableParser.d.ts +157 -1
  139. package/dist/docx/tableParser.js +89 -10
  140. package/dist/docx/textBoxParser.js +1 -1
  141. package/dist/docx/unzip.d.ts +20 -2
  142. package/dist/docx/unzip.js +136 -25
  143. package/dist/docx/wordprocessingPrefixes.d.ts +78 -0
  144. package/dist/docx/wordprocessingPrefixes.js +286 -0
  145. package/dist/fonts/embeddedFonts.js +1 -1
  146. package/dist/i18n/messages/catalogs.gen.d.ts +170 -34
  147. package/dist/i18n/messages/catalogs.gen.js +187 -51
  148. package/dist/i18n/messages/messages.gen.d.ts +10 -2
  149. package/dist/internal/compare/inline-presentation.d.ts +2 -1
  150. package/dist/internal/compare/inline-presentation.js +11 -10
  151. package/dist/internal/headlessRevisionResolutionGuard.d.ts +2 -8
  152. package/dist/internal/headlessRevisionResolutionGuard.js +2 -11
  153. package/dist/internal/indexedPositionMap.d.ts +11 -0
  154. package/dist/internal/indexedPositionMap.js +42 -0
  155. package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
  156. package/dist/internal/revisionResolutionEdits.d.ts +13 -0
  157. package/dist/internal/revisionResolutionEdits.js +19 -0
  158. package/dist/internal/revisionResolutionInline.d.ts +24 -0
  159. package/dist/internal/{headlessRevisionResolution.js → revisionResolutionInline.js} +61 -43
  160. package/dist/internal/revisionResolutionStep.d.ts +34 -0
  161. package/dist/internal/revisionResolutionStep.js +282 -0
  162. package/dist/internal/revisionResolutionTracking.d.ts +11 -0
  163. package/dist/internal/revisionResolutionTracking.js +124 -0
  164. package/dist/internal/wholeStoryRevisionResolution.d.ts +56 -0
  165. package/dist/internal/wholeStoryRevisionResolution.js +600 -0
  166. package/dist/layout-bridge/convert/markupViewFlow.d.ts +20 -0
  167. package/dist/layout-bridge/convert/markupViewFlow.js +123 -0
  168. package/dist/layout-bridge/convert/tableConversion.js +1 -1
  169. package/dist/layout-bridge/convert/toFlowBlocks.js +10 -1
  170. package/dist/layout-engine/layoutInstrumentation.d.ts +9 -1
  171. package/dist/layout-engine/layoutInstrumentation.js +4 -1
  172. package/dist/layout-engine/measure/cache.d.ts +18 -1
  173. package/dist/layout-engine/measure/cache.js +31 -1
  174. package/dist/layout-engine/measure/font-metrics.worker.js +3 -7
  175. package/dist/layout-engine/measure/measureContainer.js +7 -47
  176. package/dist/layout-engine/measure/measureHelpers.d.ts +6 -1
  177. package/dist/layout-engine/measure/measureHelpers.js +22 -2
  178. package/dist/layout-engine/measure/measureParagraph.js +2 -2
  179. package/dist/layout-engine/measure/measureWorker.js +2 -3
  180. package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +6 -7
  181. package/dist/layout-engine/measure/measureWorkerProtocol.js +1 -2
  182. package/dist/layout-engine/measure/paragraphMeasureShared.d.ts +12 -1
  183. package/dist/layout-engine/measure/paragraphMeasureShared.js +14 -1
  184. package/dist/layout-engine/types.d.ts +6 -0
  185. package/dist/layout-painter/renderPage.js +1 -0
  186. package/dist/layout-painter/renderParagraph.js +1 -1
  187. package/dist/managers/ContextMenuManager.js +5 -2
  188. package/dist/managers/types.d.ts +3 -0
  189. package/dist/markdown/escape.d.ts +2 -2
  190. package/dist/markdown/escape.js +4 -5
  191. package/dist/markdown/fromMarkdown.js +2 -1
  192. package/dist/markdown/internals.d.ts +11 -1
  193. package/dist/markdown/internals.js +24 -3
  194. package/dist/markdown/renderBlock.js +121 -25
  195. package/dist/markdown/renderParagraph.d.ts +13 -1
  196. package/dist/markdown/renderParagraph.js +85 -38
  197. package/dist/markdown/renderRuns.d.ts +10 -1
  198. package/dist/markdown/renderRuns.js +323 -69
  199. package/dist/markdown/renderTable.js +24 -12
  200. package/dist/markdown/trailers.js +2 -2
  201. package/dist/markdown/types.d.ts +29 -7
  202. package/dist/paged-layout/incrementalMeasure.d.ts +1 -2
  203. package/dist/paged-layout/incrementalMeasure.js +1 -9
  204. package/dist/paged-layout/transactionDirtyRange.d.ts +1 -3
  205. package/dist/paged-layout/transactionDirtyRange.js +29 -41
  206. package/dist/panel-layout.d.ts +83 -0
  207. package/dist/panel-layout.js +96 -0
  208. package/dist/prosemirror/anchoredTextBoxes.d.ts +37 -0
  209. package/dist/prosemirror/anchoredTextBoxes.js +156 -0
  210. package/dist/prosemirror/attrs/index.d.ts +6 -2
  211. package/dist/prosemirror/attrs/index.js +172 -1
  212. package/dist/prosemirror/clearRunColor.d.ts +6 -0
  213. package/dist/prosemirror/clearRunColor.js +46 -0
  214. package/dist/prosemirror/commands/comments.d.ts +7 -8
  215. package/dist/prosemirror/commands/comments.js +281 -212
  216. package/dist/prosemirror/commands/contentControls.d.ts +1 -1
  217. package/dist/prosemirror/commands/formatPainter.d.ts +1 -1
  218. package/dist/prosemirror/commands/formatPainter.js +1 -1
  219. package/dist/prosemirror/commands/formatting.d.ts +1 -1
  220. package/dist/prosemirror/commands/hyperlink.js +2 -1
  221. package/dist/prosemirror/commands/index.d.ts +2 -2
  222. package/dist/prosemirror/commands/index.js +2 -2
  223. package/dist/prosemirror/commands/paragraph.d.ts +7 -1
  224. package/dist/prosemirror/commands/paragraph.js +9 -1
  225. package/dist/prosemirror/commands/paragraphBookmarkJoin.d.ts +13 -0
  226. package/dist/prosemirror/commands/paragraphBookmarkJoin.js +22 -0
  227. package/dist/prosemirror/commands/pastePlainText.d.ts +1 -1
  228. package/dist/prosemirror/commands/propertyChangeScope.d.ts +3 -2
  229. package/dist/prosemirror/commands/propertyChangeScope.js +24 -3
  230. package/dist/prosemirror/commands/resolveAllTableChanges.d.ts +40 -0
  231. package/dist/prosemirror/commands/resolveAllTableChanges.js +620 -0
  232. package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.d.ts +15 -0
  233. package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.js +46 -0
  234. package/dist/prosemirror/commands/resolveParagraphProperties.d.ts +16 -0
  235. package/dist/prosemirror/commands/resolveParagraphProperties.js +73 -0
  236. package/dist/prosemirror/commands/sectionBreak.js +2 -1
  237. package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +15 -2
  238. package/dist/prosemirror/commands/tableCellMergeResolution.js +23 -7
  239. package/dist/prosemirror/containerFinalParagraph.d.ts +11 -5
  240. package/dist/prosemirror/containerFinalParagraph.js +7 -6
  241. package/dist/prosemirror/contentControlRevisions.d.ts +1 -1
  242. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
  243. package/dist/prosemirror/conversion/fromProseDoc.js +177 -605
  244. package/dist/prosemirror/conversion/toProseDoc.d.ts +4 -11
  245. package/dist/prosemirror/conversion/toProseDoc.js +70 -154
  246. package/dist/prosemirror/documentSchema.d.ts +8 -0
  247. package/dist/prosemirror/documentSchema.js +18 -0
  248. package/dist/prosemirror/emptyFieldResultRuns.d.ts +18 -0
  249. package/dist/prosemirror/emptyFieldResultRuns.js +33 -0
  250. package/dist/prosemirror/extensions/ExtensionManager.d.ts +1 -1
  251. package/dist/prosemirror/extensions/ExtensionManager.js +3 -1
  252. package/dist/prosemirror/extensions/StarterKit.js +5 -1
  253. package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
  254. package/dist/prosemirror/extensions/core/ParagraphExtension.js +116 -63
  255. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +4 -1
  256. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +24 -3
  257. package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.d.ts +20 -0
  258. package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.js +43 -0
  259. package/dist/prosemirror/extensions/features/ListExtension.js +167 -128
  260. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +19 -2
  261. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +33 -20
  262. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +31 -2
  263. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +270 -99
  264. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +3 -2
  265. package/dist/prosemirror/extensions/features/pasteCleanup.js +2 -1
  266. package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +1 -1
  267. package/dist/prosemirror/extensions/features/pastedHtmlLists.d.ts +12 -0
  268. package/dist/prosemirror/extensions/features/pastedHtmlLists.js +124 -0
  269. package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +33 -11
  270. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +8 -4
  271. package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +21 -18
  272. package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +37 -17
  273. package/dist/prosemirror/extensions/marks/StrikeExtension.js +2 -2
  274. package/dist/prosemirror/extensions/marks/SubscriptExtension.js +2 -2
  275. package/dist/prosemirror/extensions/marks/SuperscriptExtension.js +2 -2
  276. package/dist/prosemirror/extensions/marks/TextColorExtension.js +4 -3
  277. package/dist/prosemirror/extensions/marks/markUtils.d.ts +15 -8
  278. package/dist/prosemirror/extensions/marks/markUtils.js +25 -10
  279. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +12 -0
  280. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +46 -0
  281. package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.d.ts +6 -0
  282. package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.js +52 -0
  283. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +2 -2
  284. package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +3 -3
  285. package/dist/prosemirror/extensions/nodes/FieldExtension.js +50 -15
  286. package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +5 -3
  287. package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +4 -1
  288. package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
  289. package/dist/prosemirror/extensions/nodes/TableExtension.js +121 -226
  290. package/dist/prosemirror/extensions/types.d.ts +11 -1
  291. package/dist/prosemirror/findReplaceSelection.js +1 -1
  292. package/dist/prosemirror/hyperlinkRemoval.d.ts +9 -0
  293. package/dist/prosemirror/hyperlinkRemoval.js +129 -0
  294. package/dist/prosemirror/index.d.ts +5 -3
  295. package/dist/prosemirror/index.js +5 -3
  296. package/dist/prosemirror/indexedNodeLookup.d.ts +17 -0
  297. package/dist/prosemirror/indexedNodeLookup.js +103 -0
  298. package/dist/prosemirror/listAutoformatMarkers.d.ts +19 -0
  299. package/dist/prosemirror/listAutoformatMarkers.js +98 -0
  300. package/dist/prosemirror/listInstanceReferences.d.ts +12 -0
  301. package/dist/prosemirror/listInstanceReferences.js +72 -0
  302. package/dist/prosemirror/listLabels.d.ts +24 -0
  303. package/dist/prosemirror/listLabels.js +111 -0
  304. package/dist/prosemirror/listNumbering.d.ts +92 -0
  305. package/dist/prosemirror/listNumbering.js +330 -0
  306. package/dist/prosemirror/listRendering.d.ts +27 -0
  307. package/dist/prosemirror/listRendering.js +27 -0
  308. package/dist/prosemirror/listRenderingAttrs.d.ts +11 -2
  309. package/dist/prosemirror/listRenderingAttrs.js +8 -1
  310. package/dist/prosemirror/markupViewNotes.d.ts +8 -0
  311. package/dist/prosemirror/markupViewNotes.js +49 -0
  312. package/dist/prosemirror/markupViewProjection.d.ts +97 -0
  313. package/dist/prosemirror/markupViewProjection.js +88 -0
  314. package/dist/prosemirror/noteReferenceReview.d.ts +77 -0
  315. package/dist/prosemirror/noteReferenceReview.js +332 -0
  316. package/dist/prosemirror/numberingAttr.d.ts +9 -1
  317. package/dist/prosemirror/numberingAttr.js +9 -1
  318. package/dist/prosemirror/outlineLevelAttr.js +1 -1
  319. package/dist/prosemirror/paragraphIndentation.d.ts +10 -1
  320. package/dist/prosemirror/paragraphIndentation.js +32 -7
  321. package/dist/prosemirror/paragraphMarkJoin.d.ts +21 -0
  322. package/dist/prosemirror/paragraphMarkJoin.js +26 -0
  323. package/dist/prosemirror/paragraphPropertyCarry.d.ts +64 -0
  324. package/dist/prosemirror/paragraphPropertyCarry.js +158 -0
  325. package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +1 -1
  326. package/dist/prosemirror/plugins/documentNumbering.d.ts +27 -1
  327. package/dist/prosemirror/plugins/documentNumbering.js +97 -11
  328. package/dist/prosemirror/plugins/documentStyleState.d.ts +26 -0
  329. package/dist/prosemirror/plugins/documentStyleState.js +32 -0
  330. package/dist/prosemirror/plugins/documentStyles.d.ts +3 -13
  331. package/dist/prosemirror/plugins/documentStyles.js +67 -17
  332. package/dist/prosemirror/plugins/index.d.ts +2 -1
  333. package/dist/prosemirror/plugins/index.js +2 -1
  334. package/dist/prosemirror/plugins/paragraphStyleResolution.d.ts +15 -0
  335. package/dist/prosemirror/plugins/paragraphStyleResolution.js +230 -0
  336. package/dist/prosemirror/plugins/suggestionMode.d.ts +27 -3
  337. package/dist/prosemirror/plugins/suggestionMode.js +490 -63
  338. package/dist/prosemirror/plugins/templateDirectives.d.ts +1 -1
  339. package/dist/prosemirror/plugins/transactionInvariants.d.ts +32 -0
  340. package/dist/prosemirror/plugins/transactionInvariants.js +86 -0
  341. package/dist/prosemirror/positionSweep.d.ts +24 -0
  342. package/dist/prosemirror/positionSweep.js +222 -0
  343. package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +23 -3
  344. package/dist/prosemirror/rebaseParagraphRunFormatting.js +39 -13
  345. package/dist/prosemirror/rebaseParagraphRuns.d.ts +36 -0
  346. package/dist/prosemirror/rebaseParagraphRuns.js +99 -0
  347. package/dist/prosemirror/rejoinRunCarriers.d.ts +1 -1
  348. package/dist/prosemirror/replacedAnnotations.d.ts +33 -1
  349. package/dist/prosemirror/replacedAnnotations.js +170 -1
  350. package/dist/prosemirror/runFormattingFromMarks.d.ts +18 -0
  351. package/dist/prosemirror/runFormattingFromMarks.js +567 -0
  352. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +1 -1
  353. package/dist/prosemirror/runFormattingReconciliation.js +10 -9
  354. package/dist/prosemirror/schema/index.d.ts +2 -2
  355. package/dist/prosemirror/schema/index.js +3 -0
  356. package/dist/prosemirror/schema/nodes.d.ts +44 -11
  357. package/dist/prosemirror/sectionMarkEdits.d.ts +20 -0
  358. package/dist/prosemirror/sectionMarkEdits.js +59 -0
  359. package/dist/prosemirror/storyListNumbering.d.ts +17 -0
  360. package/dist/prosemirror/storyListNumbering.js +102 -0
  361. package/dist/prosemirror/styles/paragraphStyleCascade.d.ts +59 -0
  362. package/dist/prosemirror/styles/paragraphStyleCascade.js +145 -0
  363. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +21 -2
  364. package/dist/prosemirror/styles/resolvedStyleAttrs.js +38 -1
  365. package/dist/prosemirror/styles/tableStyleRegions.d.ts +31 -0
  366. package/dist/prosemirror/styles/tableStyleRegions.js +55 -0
  367. package/dist/prosemirror/tableCellPaste.d.ts +74 -0
  368. package/dist/prosemirror/tableCellPaste.js +525 -0
  369. package/dist/prosemirror/tableGridMutation.d.ts +87 -2
  370. package/dist/prosemirror/tableGridMutation.js +255 -2
  371. package/dist/prosemirror/tableRunIn.d.ts +51 -0
  372. package/dist/prosemirror/tableRunIn.js +165 -0
  373. package/dist/prosemirror/textInput.js +11 -2
  374. package/dist/prosemirror/trackedRevisionPath.d.ts +17 -0
  375. package/dist/prosemirror/trackedRevisionPath.js +32 -0
  376. package/dist/prosemirror/validation.js +5 -1
  377. package/dist/redline.js +93 -9
  378. package/dist/render-dom/BodySelectionOverlay.d.ts +4 -1
  379. package/dist/render-dom/BodySelectionOverlay.js +3 -2
  380. package/dist/server.d.ts +2 -2
  381. package/dist/utils/findReplace.js +2 -2
  382. package/dist/utils/mergeDocumentContent.js +1 -1
  383. package/dist/utils/noteReferenceLabels.d.ts +36 -0
  384. package/dist/utils/noteReferenceLabels.js +32 -0
  385. package/dist/utils/replaceText.js +1 -1
  386. package/dist/version-comparison.d.ts +1 -0
  387. package/dist/version-comparison.js +1 -0
  388. package/package.json +6 -5
  389. package/dist/internal/headlessRevisionResolution.d.ts +0 -23
@@ -14,7 +14,7 @@ import { serializeSdtWrapper } from "./sdtPropertiesSerializer.js";
14
14
  import { serializeSectionProperties } from "./sectionPropertiesSerializer.js";
15
15
  import { serializeTextFormatting } from "./textFormattingSerializer.js";
16
16
  import { serializeTrackedChangeAttributes, trackedChangeAttributeRecord } from "./trackedChangeAttributes.js";
17
- import { panic } from "better-result";
17
+ import { TaggedError, panic } from "better-result";
18
18
  import { escapeXmlAttribute, escapeXmlText } from "@stll/docx-core";
19
19
  import { PARAGRAPH_MARK_CHANGE_KINDS } from "@stll/docx-core/model";
20
20
  import { SEQUENCE_CHILDREN } from "@stll/docx-core/schema";
@@ -315,27 +315,51 @@ function serializeSimpleField(field) {
315
315
  }).join("");
316
316
  return `<w:fldSimple ${attrs.join(" ")}>${contentXml}</w:fldSimple>`;
317
317
  }
318
- /**
319
- * Serialize a complex field
320
- * Complex fields are represented by multiple runs with fldChar elements,
321
- * so we convert them back to that structure
322
- */
318
+ const replayableFormFieldDataXml = createCapturedXmlSanitizer({
319
+ allowedLocalNames: /* @__PURE__ */ new Set(["ffData"]),
320
+ allowedNamespaceUris: WORDPROCESSINGML_NAMESPACE,
321
+ inheritedNamespaceScope: OOXML_NAMESPACE_SCOPE
322
+ });
323
+ /** Serialize a complex field as structural fldChar runs and its content runs. */
323
324
  function serializeComplexField(field) {
324
325
  const parts = [];
325
326
  const structuralFormatting = field.formatting ?? (field.fieldResultIsFallback ? void 0 : field.fieldResult[0]?.formatting);
326
327
  const rPrXml = structuralFormatting ? serializeTextFormatting(structuralFormatting) : "";
327
328
  const beginAttrs = ["w:fldCharType=\"begin\"", ...fieldStateAttributes(field)];
328
- parts.push(`<w:r>${rPrXml}<w:fldChar ${beginAttrs.join(" ")}/></w:r>`);
329
+ const formFieldDataXml = replayableFormFieldDataXml(field.formFieldDataXml);
330
+ const begin = formFieldDataXml ? `<w:fldChar ${beginAttrs.join(" ")}>${formFieldDataXml}</w:fldChar>` : `<w:fldChar ${beginAttrs.join(" ")}/>`;
331
+ parts.push(`<w:r>${rPrXml}${begin}</w:r>`);
329
332
  if (field.fieldCode.length > 0) parts.push(...field.fieldCode.map((run) => serializeRun(run)));
330
333
  else if (field.instruction.length > 0) {
331
334
  const spaceAttr = field.instruction.startsWith(" ") || field.instruction.endsWith(" ") || field.instruction.includes(" ") ? " xml:space=\"preserve\"" : "";
332
335
  parts.push(`<w:r>${rPrXml}<w:instrText${spaceAttr}>${escapeXmlText(field.instruction)}</w:instrText></w:r>`);
333
336
  }
334
337
  parts.push(`<w:r>${rPrXml}<w:fldChar w:fldCharType="separate"/></w:r>`);
335
- if (!field.fieldResultIsFallback) parts.push(...field.fieldResult.map((run) => serializeRun(run)));
338
+ if (!field.fieldResultIsFallback || !formFieldDataXml) parts.push(...field.fieldResult.map((run) => serializeRun(run)));
336
339
  parts.push(`<w:r>${rPrXml}<w:fldChar w:fldCharType="end"/></w:r>`);
337
340
  return parts.join("");
338
341
  }
342
+ var UnrepresentableTrackedSimpleFieldError = class extends TaggedError("UnrepresentableTrackedSimpleFieldError") {};
343
+ /** A revision can contain run-level field characters, but not `w:fldSimple`. */
344
+ function serializeTrackedSimpleField(field) {
345
+ const fieldResult = [];
346
+ for (const item of field.content) {
347
+ if (item.type !== "run") throw new UnrepresentableTrackedSimpleFieldError({
348
+ message: `A tracked simple field with ${item.type} result content cannot be serialized as valid OOXML.`,
349
+ contentType: item.type
350
+ });
351
+ fieldResult.push(item);
352
+ }
353
+ return serializeComplexField({
354
+ type: "complexField",
355
+ instruction: field.instruction,
356
+ fieldType: field.fieldType,
357
+ fieldCode: [],
358
+ fieldResult,
359
+ ...field.fldLock !== void 0 && { fldLock: field.fldLock },
360
+ ...field.dirty !== void 0 && { dirty: field.dirty }
361
+ });
362
+ }
339
363
  /**
340
364
  * Serialize an inline SDT (w:sdt).
341
365
  *
@@ -413,7 +437,7 @@ function serializeTrackedChange(tag, change) {
413
437
  case "run": return serializeContentRun(item);
414
438
  case "simpleField":
415
439
  case "complexField": {
416
- const xml = item.type === "simpleField" ? serializeSimpleField(item) : serializeComplexField(item);
440
+ const xml = item.type === "simpleField" ? serializeTrackedSimpleField(item) : serializeComplexField(item);
417
441
  return disposition === "removed" ? rewriteRunTextAsDeleted(xml) : xml;
418
442
  }
419
443
  case "mathEquation": return item.ommlXml;
@@ -6,6 +6,7 @@ import { TRANSITIONAL_NAME_BY_STRICT_NAME } from "../strictNames.gen.js";
6
6
  import { TABLE_LOOK_FLAGS } from "../tableLook.js";
7
7
  import { parseTableCellProperties, parseTableGrid, parseTableProperties, parseTablePropertyExceptions, parseTableRowProperties } from "../tableParser.js";
8
8
  import { OOXML_NAMESPACE_SCOPE, parseXml } from "../xmlParser.js";
9
+ import { serializeBlockCustomXml } from "./blockCustomXmlSerializer.js";
9
10
  import { serializeBlockSdt } from "./blockSdtSerializer.js";
10
11
  import { serializeBorder } from "./borderSerializer.js";
11
12
  import { serializeBookmarkMarker } from "./markupRangeAttributes.js";
@@ -456,56 +457,40 @@ const serializeTableGridChange = ({ id, columnWidths }) => {
456
457
  const columns = columnWidths.map((width) => width === void 0 ? "<w:gridCol/>" : `<w:gridCol w:w="${intAttr(width)}"/>`).join("");
457
458
  return `<w:tblGridChange w:id="${intAttr(id)}"><w:tblGrid>${columns}</w:tblGrid></w:tblGridChange>`;
458
459
  };
459
- /**
460
- * What makes two rows members of the same control.
461
- *
462
- * The control's record is on every child it held, so the wrapper is rebuilt
463
- * by grouping consecutive children that name the same control. Equality is
464
- * the record's canonical spelling rather than object identity, because the
465
- * editor carries these records through JSON — a Yjs sync, a snapshot, a
466
- * structured clone — and hands back an equal record rather than the same one.
467
- * A wrapper that split in two there would mint a second `w:id` for one
468
- * control, which is the defect, not the fix.
469
- *
470
- * The cost is the other direction: two adjacent rows the author put in two
471
- * separate but identically spelled controls come back as one. Word mints a
472
- * distinct `w:id` per control, so that needs a producer that writes none; the
473
- * inline wrapper stack makes the same trade for the same reason.
474
- */
475
- const contentControlKey = (properties) => canonicalJson(properties);
476
- /**
477
- * Re-open each control around the run of children that named it, outermost
478
- * first.
479
- *
480
- * @param depth which layer of the stack this call is opening
481
- */
482
- const serializeControlledChildren = (children, depth) => {
460
+ const tableCarrierKey = (carrier) => carrier.type === "customXml" ? `customXml:${String(carrier.wrapper.id)}` : `sdt:${canonicalJson(carrier.properties)}`;
461
+ const serializeTableCarriers = (children, depth = 0) => {
483
462
  const parts = [];
484
463
  let index = 0;
485
464
  while (index < children.length) {
486
465
  const child = children[index];
487
- const control = child.controls[depth];
488
- if (control === void 0) {
466
+ if (!child) break;
467
+ const carrier = child.carriers[depth];
468
+ if (!carrier) {
489
469
  parts.push(child.xml);
490
470
  index += 1;
491
471
  continue;
492
472
  }
493
- const key = contentControlKey(control);
473
+ const carrierKey = tableCarrierKey(carrier);
494
474
  let end = index + 1;
495
475
  while (end < children.length) {
496
- const next = children[end]?.controls[depth];
497
- if (next === void 0 || contentControlKey(next) !== key) break;
476
+ const next = children[end]?.carriers[depth];
477
+ if ((next ? tableCarrierKey(next) : void 0) !== carrierKey) break;
498
478
  end += 1;
499
479
  }
500
- const inner = serializeControlledChildren(children.slice(index, end), depth + 1);
501
- parts.push(serializeSdtWrapper(control, inner));
480
+ const inner = serializeTableCarriers(children.slice(index, end), depth + 1);
481
+ if (carrier.type === "customXml") parts.push(`${carrier.wrapper.openingXml}${inner}${carrier.wrapper.closingXml}`);
482
+ else parts.push(serializeSdtWrapper(carrier.properties, inner));
502
483
  index = end;
503
484
  }
504
485
  return parts.join("");
505
486
  };
487
+ const carriersFor = (value) => value.carrierStack ?? [...(value.contentControls ?? []).map((properties) => ({
488
+ type: "sdt",
489
+ properties
490
+ }))];
506
491
  /** A capture from the sink, with the controls it sat inside when parsed. */
507
492
  const preservedChild = (xml, child) => ({
508
- controls: child.contentControls ?? [],
493
+ carriers: carriersFor(child),
509
494
  xml
510
495
  });
511
496
  /**
@@ -517,6 +502,7 @@ function serializeCellContent(content, serializeParagraph) {
517
502
  case "paragraph": return serializeParagraph(block);
518
503
  case "table": return serializeTable(block, serializeParagraph);
519
504
  case "blockSdt": return serializeBlockSdt(block, serializeCellBlock);
505
+ case "blockCustomXml": return serializeBlockCustomXml(block, serializeCellBlock);
520
506
  case "preservedBlock": return block.xml;
521
507
  case "bookmarkStart":
522
508
  case "bookmarkEnd": return serializeBookmarkMarker(block);
@@ -549,10 +535,11 @@ function serializeTableCell(cell, serializeParagraph) {
549
535
  */
550
536
  const positionedChildren = (preserved, bookmarks) => {
551
537
  if (bookmarks === void 0 || bookmarks.length === 0) return preserved;
552
- return { children: [...preserved?.children ?? [], ...bookmarks.map(({ index, marker, contentControls }) => ({
538
+ return { children: [...preserved?.children ?? [], ...bookmarks.map(({ index, marker, contentControls, carrierStack }) => ({
553
539
  index,
554
540
  xml: serializeBookmarkMarker(marker),
555
- ...contentControls === void 0 ? {} : { contentControls }
541
+ ...contentControls === void 0 ? {} : { contentControls },
542
+ ...carrierStack === void 0 ? {} : { carrierStack }
556
543
  }))] };
557
544
  };
558
545
  /**
@@ -564,8 +551,8 @@ function serializeTableRow(row, serializeParagraph) {
564
551
  if (tblPrExXml) parts.push(tblPrExXml);
565
552
  const trPrXml = serializeTableRowFormatting(row.formatting, row.propertyChanges, row.structuralChange);
566
553
  if (trPrXml) parts.push(trPrXml);
567
- parts.push(serializeControlledChildren(withPreservedChildren(row.cells.map((cell) => ({
568
- controls: cell.contentControls ?? [],
554
+ parts.push(serializeTableCarriers(withPreservedChildren(row.cells.map((cell) => ({
555
+ carriers: carriersFor(cell),
569
556
  xml: serializeTableCell(cell, serializeParagraph)
570
557
  })), positionedChildren(row.preserved, row.bookmarks), preservedChild), 0));
571
558
  const attrs = serializePreservedAttributes([], row.preservedAttributes);
@@ -581,8 +568,8 @@ function serializeTable(table, serializeParagraph) {
581
568
  return `<w:tbl>${[
582
569
  serializeTableFormatting(table.formatting, table.propertyChanges) || "<w:tblPr/>",
583
570
  serializeTableGrid(table),
584
- serializeControlledChildren(withPreservedChildren(table.rows.map((row) => ({
585
- controls: row.contentControls ?? [],
571
+ serializeTableCarriers(withPreservedChildren(table.rows.map((row) => ({
572
+ carriers: carriersFor(row),
586
573
  xml: serializeTableRow(row, serializeParagraph)
587
574
  })), positionedChildren(table.preserved, table.bookmarks), preservedChild), 0)
588
575
  ].join("")}</w:tbl>`;
@@ -1,17 +1,5 @@
1
1
  import { XmlResourceLimits } from "../xmlResourceLimits.js";
2
- import JSZip from "jszip";
3
2
  //#region src/docx/server/boundedArchive.d.ts
4
- declare module "jszip" {
5
- interface JSZipObject {
6
- /**
7
- * Chunked read of the entry content, missing from the published typings.
8
- * `nodeStream` is this stream wrapped in a Node.js `Readable`, which
9
- * browsers and web workers cannot provide; the stream itself is
10
- * platform-neutral.
11
- */
12
- internalStream(type: "uint8array"): JSZip.JSZipStreamHelper<Uint8Array>;
13
- }
14
- }
15
3
  declare const DOCX_MAX_ENTRY_BYTES: number;
16
4
  declare const DOCX_MAX_TOTAL_BYTES: number;
17
5
  declare const DOCX_MAX_ENTRIES = 4096;
@@ -20,7 +8,7 @@ declare const DocxArchiveError_base: import("better-result").TaggedErrorClass<"D
20
8
  /** Error raised when a DOCX archive cannot be loaded within configured limits. */
21
9
  declare class DocxArchiveError extends DocxArchiveError_base<{
22
10
  message: string;
23
- reason: "load-failed" | "input-too-large" | "too-many-entries" | "entry-too-large" | "total-too-large" | "invalid-options";
11
+ reason: "load-failed" | "input-too-large" | "too-many-entries" | "entry-too-large" | "total-too-large" | "compression-ratio-exceeded" | "invalid-options";
24
12
  cause?: unknown;
25
13
  }> {}
26
14
  type DocxArchiveOptions = {
@@ -28,6 +16,13 @@ type DocxArchiveOptions = {
28
16
  maxEntryBytes?: number;
29
17
  maxTotalBytes?: number;
30
18
  maxEntries?: number;
19
+ /**
20
+ * Most inflated bytes allowed per compressed byte, for each markup or text
21
+ * entry and for the package as a whole. Binary entries are bounded by the
22
+ * byte limits and the package ratio only, and entries and packages under
23
+ * 4 MiB inflated are exempt. Defaults to 200.
24
+ */
25
+ maxCompressionRatio?: number;
31
26
  /**
32
27
  * Bounds on parsed XML structure, applied to every XML part this archive
33
28
  * hands out as a string.
@@ -1,3 +1,4 @@
1
+ import { compressionRatioLimitFor, countCentralDirectoryRecords, createInflationBudget, exceedsCompressionRatio, getZipEntrySizes, inflateEntryWithinLimits } from "../archiveInflation.js";
1
2
  import { FOLIO_XML_RESOURCE_LIMITS, assertXmlResourceLimits, createXmlPackageBudget } from "../xmlResourceLimits.js";
2
3
  import { TaggedError } from "better-result";
3
4
  import JSZip from "jszip";
@@ -8,49 +9,26 @@ const DOCX_MAX_ENTRIES = 4096;
8
9
  const DOCX_MAX_INPUT_BYTES = 50 * 1024 * 1024;
9
10
  /** Error raised when a DOCX archive cannot be loaded within configured limits. */
10
11
  var DocxArchiveError = class extends TaggedError("DocxArchiveError") {};
11
- const concatChunks = (chunks) => {
12
- let totalBytes = 0;
13
- for (const chunk of chunks) totalBytes += chunk.length;
14
- const merged = new Uint8Array(totalBytes);
15
- let offset = 0;
16
- for (const chunk of chunks) {
17
- merged.set(chunk, offset);
18
- offset += chunk.length;
12
+ const readLimitError = ({ limit, path, maxEntryBytes, maxTotalBytes, maxCompressionRatio }) => {
13
+ switch (limit) {
14
+ case "declared-size": return new DocxArchiveError({
15
+ message: `DOCX entry "${path}" inflated past its declared size`,
16
+ reason: "entry-too-large"
17
+ });
18
+ case "compression-ratio": return new DocxArchiveError({
19
+ message: `DOCX entry "${path}" exceeded the ${maxCompressionRatio}:1 compression ratio limit`,
20
+ reason: "compression-ratio-exceeded"
21
+ });
22
+ case "entry": return new DocxArchiveError({
23
+ message: `DOCX entry "${path}" exceeded the ${maxEntryBytes}-byte limit`,
24
+ reason: "entry-too-large"
25
+ });
26
+ case "total":
27
+ case "aborted": return new DocxArchiveError({
28
+ message: `DOCX archive exceeded the ${maxTotalBytes}-byte cumulative limit while reading "${path}"`,
29
+ reason: "total-too-large"
30
+ });
19
31
  }
20
- return merged;
21
- };
22
- /**
23
- * Accumulate an entry chunk by chunk, checking both caps before each chunk is
24
- * retained. Pausing the stream abandons a decompression bomb mid-inflate, so
25
- * the caps bound memory instead of merely reporting the overrun afterwards.
26
- */
27
- const collectStream = async ({ stream, maxEntryBytes, remainingBytes, maxTotalBytes, path }) => await new Promise((resolve, reject) => {
28
- const chunks = [];
29
- let entryBytes = 0;
30
- const fail = (reason, message) => {
31
- stream.pause();
32
- reject(new DocxArchiveError({
33
- message,
34
- reason
35
- }));
36
- };
37
- stream.on("data", (chunk) => {
38
- entryBytes += chunk.length;
39
- if (entryBytes > maxEntryBytes) {
40
- fail("entry-too-large", `DOCX entry "${path}" exceeded the ${maxEntryBytes}-byte limit`);
41
- return;
42
- }
43
- if (entryBytes > remainingBytes) {
44
- fail("total-too-large", `DOCX archive exceeded the ${maxTotalBytes}-byte cumulative limit while reading "${path}"`);
45
- return;
46
- }
47
- chunks.push(chunk);
48
- }).on("end", () => resolve(concatChunks(chunks))).on("error", reject).resume();
49
- });
50
- const getDeclaredUncompressedBytes = (entry) => {
51
- const data = "_data" in entry ? entry._data : void 0;
52
- const declaredBytes = typeof data === "object" && data !== null && "uncompressedSize" in data ? data.uncompressedSize : void 0;
53
- return typeof declaredBytes === "number" && Number.isFinite(declaredBytes) ? declaredBytes : null;
54
32
  };
55
33
  const resolveByteLimit = ({ value, fallback, name }) => {
56
34
  const limit = value ?? fallback;
@@ -60,6 +38,7 @@ const resolveByteLimit = ({ value, fallback, name }) => {
60
38
  });
61
39
  return limit;
62
40
  };
41
+ const asBytes = (bytes) => bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
63
42
  const loadDocxArchive = async (bytes, options = {}) => {
64
43
  const maxInputBytes = resolveByteLimit({
65
44
  value: options.maxInputBytes,
@@ -81,10 +60,19 @@ const loadDocxArchive = async (bytes, options = {}) => {
81
60
  fallback: DOCX_MAX_ENTRIES,
82
61
  name: "DOCX entry limit"
83
62
  });
63
+ const maxCompressionRatio = resolveByteLimit({
64
+ value: options.maxCompressionRatio,
65
+ fallback: 200,
66
+ name: "DOCX compression ratio limit"
67
+ });
84
68
  if (bytes.byteLength > maxInputBytes) throw new DocxArchiveError({
85
69
  message: `DOCX input contains ${bytes.byteLength} bytes (max ${maxInputBytes})`,
86
70
  reason: "input-too-large"
87
71
  });
72
+ if (countCentralDirectoryRecords(asBytes(bytes), maxEntries) > maxEntries) throw new DocxArchiveError({
73
+ message: `DOCX archive holds more than ${maxEntries} entries`,
74
+ reason: "too-many-entries"
75
+ });
88
76
  let zip;
89
77
  try {
90
78
  zip = await JSZip.loadAsync(bytes);
@@ -101,30 +89,47 @@ const loadDocxArchive = async (bytes, options = {}) => {
101
89
  reason: "too-many-entries"
102
90
  });
103
91
  let declaredTotalBytes = 0;
92
+ let declaredTotalKnown = true;
104
93
  for (const entry of archiveEntries) {
105
94
  if (entry.dir) continue;
106
- const declaredBytes = getDeclaredUncompressedBytes(entry);
107
- if (declaredBytes === null) {
108
- declaredTotalBytes = NaN;
109
- break;
95
+ const { compressedBytes, uncompressedBytes } = getZipEntrySizes(entry);
96
+ if (uncompressedBytes === null) {
97
+ declaredTotalKnown = false;
98
+ continue;
110
99
  }
111
- if (declaredBytes > maxEntryBytes) throw new DocxArchiveError({
112
- message: `DOCX entry "${entry.name}" declares ${declaredBytes} bytes (max ${maxEntryBytes})`,
100
+ if (uncompressedBytes > maxEntryBytes) throw new DocxArchiveError({
101
+ message: `DOCX entry "${entry.name}" declares ${uncompressedBytes} bytes (max ${maxEntryBytes})`,
113
102
  reason: "entry-too-large"
114
103
  });
115
- declaredTotalBytes += declaredBytes;
104
+ if (exceedsCompressionRatio({
105
+ inflatedBytes: uncompressedBytes,
106
+ compressedBytes,
107
+ maxRatio: compressionRatioLimitFor(entry.name, maxCompressionRatio)
108
+ })) throw new DocxArchiveError({
109
+ message: `DOCX entry "${entry.name}" declares more than ${maxCompressionRatio} bytes per compressed byte`,
110
+ reason: "compression-ratio-exceeded"
111
+ });
112
+ declaredTotalBytes += uncompressedBytes;
116
113
  }
117
- if (Number.isFinite(declaredTotalBytes) && declaredTotalBytes > maxTotalBytes) throw new DocxArchiveError({
114
+ if (declaredTotalKnown && declaredTotalBytes > maxTotalBytes) throw new DocxArchiveError({
118
115
  message: `DOCX archive declares ${declaredTotalBytes} cumulative bytes (max ${maxTotalBytes})`,
119
116
  reason: "total-too-large"
120
117
  });
118
+ if (exceedsCompressionRatio({
119
+ inflatedBytes: declaredTotalBytes,
120
+ compressedBytes: bytes.byteLength,
121
+ maxRatio: maxCompressionRatio
122
+ })) throw new DocxArchiveError({
123
+ message: `DOCX archive declares more than ${maxCompressionRatio} bytes per archive byte`,
124
+ reason: "compression-ratio-exceeded"
125
+ });
121
126
  const xmlLimits = {
122
127
  ...FOLIO_XML_RESOURCE_LIMITS,
123
128
  ...options.xmlLimits
124
129
  };
125
130
  const xmlBudget = createXmlPackageBudget();
126
131
  const countedParts = /* @__PURE__ */ new Set();
127
- let totalBytesRead = 0;
132
+ const inflationBudget = createInflationBudget(maxTotalBytes);
128
133
  let readChain = Promise.resolve();
129
134
  const readEntry = async (path, readOptions = {}) => {
130
135
  const requestedMaxBytes = resolveByteLimit({
@@ -135,15 +140,21 @@ const loadDocxArchive = async (bytes, options = {}) => {
135
140
  const work = async () => {
136
141
  const entry = zip.file(path);
137
142
  if (!entry) return null;
138
- const content = await collectStream({
139
- stream: entry.internalStream("uint8array"),
140
- maxEntryBytes: Math.min(requestedMaxBytes, maxEntryBytes),
141
- remainingBytes: maxTotalBytes - totalBytesRead,
143
+ const entryLimit = Math.min(requestedMaxBytes, maxEntryBytes);
144
+ const result = await inflateEntryWithinLimits({
145
+ entry,
146
+ maxEntryBytes: entryLimit,
147
+ maxCompressionRatio: compressionRatioLimitFor(path, maxCompressionRatio),
148
+ budget: inflationBudget
149
+ });
150
+ if (!result.ok) throw readLimitError({
151
+ limit: result.limit,
152
+ path,
153
+ maxEntryBytes: entryLimit,
142
154
  maxTotalBytes,
143
- path
155
+ maxCompressionRatio
144
156
  });
145
- totalBytesRead += content.length;
146
- return content;
157
+ return result.bytes;
147
158
  };
148
159
  const next = readChain.then(work, work);
149
160
  readChain = next.then(() => void 0, () => void 0);
@@ -154,7 +165,7 @@ const loadDocxArchive = async (bytes, options = {}) => {
154
165
  entryMetadata: Object.freeze(archiveEntries.map((entry) => ({
155
166
  path: entry.name,
156
167
  directory: entry.dir,
157
- declaredUncompressedBytes: getDeclaredUncompressedBytes(entry)
168
+ declaredUncompressedBytes: getZipEntrySizes(entry).uncompressedBytes
158
169
  }))),
159
170
  async readEntryString(path) {
160
171
  const content = await readEntry(path);
@@ -203,7 +203,7 @@ const flattenBlocks = (content) => {
203
203
  out.push(block);
204
204
  return;
205
205
  }
206
- if (block.type !== "blockSdt") return;
206
+ if (block.type !== "blockSdt" && block.type !== "blockCustomXml") return;
207
207
  for (const child of block.content) visit(child);
208
208
  };
209
209
  for (const block of content) visit(block);
@@ -467,7 +467,7 @@ const collectTableParagraphs = (table) => {
467
467
  const collectBlocks = (blocks) => {
468
468
  for (const item of blocks) if (item.type === "paragraph") out.push(item);
469
469
  else if (item.type === "table") out.push(...collectTableParagraphs(item));
470
- else if (item.type === "blockSdt") collectBlocks(item.content);
470
+ else if (item.type === "blockSdt" || item.type === "blockCustomXml") collectBlocks(item.content);
471
471
  };
472
472
  for (const row of table.rows) for (const cell of row.cells) collectBlocks(cell.content);
473
473
  return out;
@@ -476,7 +476,7 @@ const cloneTableForTarget = ({ table, editableParagraphIds, paraIds, styleCloner
476
476
  const paragraphs = [];
477
477
  const cloneBlocks = (blocks) => blocks.map((item) => {
478
478
  if (item.type === "table") return cloneTable(item);
479
- if (item.type === "blockSdt") return {
479
+ if (item.type === "blockSdt" || item.type === "blockCustomXml") return {
480
480
  ...structuredClone(item),
481
481
  content: cloneBlocks(item.content)
482
482
  };
@@ -1,3 +1,4 @@
1
+ import { DocxArchiveOptions } from "./boundedArchive.js";
1
2
  //#region src/docx/server/extractDocxText.d.ts
2
3
  /** Document part containing an extracted paragraph. */
3
4
  type DocxParagraphSource = "header" | "body" | "footer";
@@ -59,7 +60,12 @@ type ExtractedDocxText = {
59
60
  charCount: number;
60
61
  view: "accepted";
61
62
  };
63
+ /** Options for {@link extractDocxText}. */
64
+ type ExtractDocxTextOptions = {
65
+ /** Archive limits, applied before and while each part is inflated. */
66
+ readonly archive?: DocxArchiveOptions;
67
+ };
62
68
  /** Extract paragraph text and formatting metadata from a DOCX archive. */
63
- declare const extractDocxText: (bytes: ArrayBuffer | Uint8Array) => Promise<ExtractedDocxText>;
69
+ declare const extractDocxText: (bytes: ArrayBuffer | Uint8Array, options?: ExtractDocxTextOptions) => Promise<ExtractedDocxText>;
64
70
  //#endregion
65
- export { DocxParagraphSource, DocxTableRowKind, DocxTableRowPosition, ExtractedDocxParagraph, ExtractedDocxTableCell, ExtractedDocxTableCellParagraph, ExtractedDocxText, extractDocxText };
71
+ export { DocxParagraphSource, DocxTableRowKind, DocxTableRowPosition, ExtractDocxTextOptions, ExtractedDocxParagraph, ExtractedDocxTableCell, ExtractedDocxTableCellParagraph, ExtractedDocxText, extractDocxText };
@@ -504,8 +504,8 @@ const createEmptyResult = () => ({
504
504
  view: "accepted"
505
505
  });
506
506
  /** Extract paragraph text and formatting metadata from a DOCX archive. */
507
- const extractDocxText = async (bytes) => {
508
- const archive = await loadDocxArchive(bytes);
507
+ const extractDocxText = async (bytes, options = {}) => {
508
+ const archive = await loadDocxArchive(bytes, options.archive);
509
509
  const documentXml = await archive.readEntryString("word/document.xml");
510
510
  if (documentXml === null) return createEmptyResult();
511
511
  const root = parseXml(documentXml);
@@ -4,7 +4,7 @@ import { DocxArchiveOptions } from "./boundedArchive.js";
4
4
  declare const FOLIO_DOCX_CONFORMANCE_REPORT_VERSION: 1;
5
5
  declare const FOLIO_DOCX_CONFORMANCE_PROFILE: "folio-supported-v1";
6
6
  declare const FOLIO_DOCX_CONFORMANCE_CHECKS: readonly ["archive-safety", "required-parts", "xml-well-formedness", "package-roots", "conformance-class", "canonical-model"];
7
- declare const FOLIO_DOCX_CONFORMANCE_ISSUE_CODES: readonly ["archive-load-failed", "archive-invalid-options", "archive-input-too-large", "archive-too-many-entries", "archive-entry-too-large", "archive-total-too-large", "required-part-missing", "xml-doctype-forbidden", "xml-not-well-formed", "xml-read-failed", "required-xml-unreadable", "package-root-invalid", "conformance-class-unknown", "model-invalid", "model-warning", "parser-recovery", "parser-unsupported", "parser-failed", "encrypted-container", "container-not-zip"];
7
+ declare const FOLIO_DOCX_CONFORMANCE_ISSUE_CODES: readonly ["archive-load-failed", "archive-invalid-options", "archive-input-too-large", "archive-too-many-entries", "archive-entry-too-large", "archive-total-too-large", "archive-compression-ratio-exceeded", "required-part-missing", "xml-doctype-forbidden", "xml-not-well-formed", "xml-read-failed", "required-xml-unreadable", "package-root-invalid", "conformance-class-unknown", "model-invalid", "model-warning", "parser-recovery", "parser-unsupported", "parser-failed", "encrypted-container", "container-not-zip"];
8
8
  type FolioDocxConformanceCheckId = (typeof FOLIO_DOCX_CONFORMANCE_CHECKS)[number];
9
9
  type FolioDocxConformanceIssueCode = (typeof FOLIO_DOCX_CONFORMANCE_ISSUE_CODES)[number];
10
10
  type FolioDocxConformanceCheckStatus = "passed" | "failed" | "indeterminate" | "not-run";
@@ -25,6 +25,7 @@ const FOLIO_DOCX_CONFORMANCE_ISSUE_CODES = Object.freeze([
25
25
  "archive-too-many-entries",
26
26
  "archive-entry-too-large",
27
27
  "archive-total-too-large",
28
+ "archive-compression-ratio-exceeded",
28
29
  "required-part-missing",
29
30
  "xml-doctype-forbidden",
30
31
  "xml-not-well-formed",