@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
@@ -40,7 +40,7 @@ function extractAllTemplateVariables(content) {
40
40
  } else if (block.type === "table") {
41
41
  const tableVars = extractTableVariables(block);
42
42
  for (const v of tableVars) if (!variables.includes(v)) variables.push(v);
43
- } else if (block.type === "blockSdt") {
43
+ } else if (block.type === "blockSdt" || block.type === "blockCustomXml") {
44
44
  for (const v of extractAllTemplateVariables(block.content)) if (!variables.includes(v)) variables.push(v);
45
45
  }
46
46
  return variables;
@@ -56,7 +56,7 @@ function extractTableVariables(table) {
56
56
  } else if (cellContent.type === "table") {
57
57
  const nestedVars = extractTableVariables(cellContent);
58
58
  for (const v of nestedVars) if (!variables.includes(v)) variables.push(v);
59
- } else if (cellContent.type === "blockSdt") {
59
+ } else if (cellContent.type === "blockSdt" || cellContent.type === "blockCustomXml") {
60
60
  for (const v of extractAllTemplateVariables(cellContent.content)) if (!variables.includes(v)) variables.push(v);
61
61
  }
62
62
  return variables;
@@ -153,7 +153,7 @@ function parseDocumentBackground(documentEl, context) {
153
153
  function parseDocumentBody(xml, styles = null, theme = null, numbering = null, rels = null, media = null, context, previews = standalonePreviewLedger()) {
154
154
  const result = { content: [] };
155
155
  if (!xml) return result;
156
- const documentEl = (parseXml(xml).elements ?? []).find((el) => el.type === "element" && (el.name === "w:document" || el.name?.endsWith(":document")));
156
+ const documentEl = (parseXml(xml).elements ?? []).find((el) => el.type === "element" && getLocalName(el.name ?? "") === "document");
157
157
  if (!documentEl) return result;
158
158
  const background = parseDocumentBackground(documentEl, context);
159
159
  if (background !== void 0) result.background = background;
@@ -177,14 +177,14 @@ function getAllParagraphs(body) {
177
177
  const paragraphs = [];
178
178
  for (const block of body.content) if (block.type === "paragraph") paragraphs.push(block);
179
179
  else if (block.type === "table") paragraphs.push(...getTableParagraphs(block));
180
- else if (block.type === "blockSdt") paragraphs.push(...getParagraphsFromBlocks(block.content));
180
+ else if (block.type === "blockSdt" || block.type === "blockCustomXml") paragraphs.push(...getParagraphsFromBlocks(block.content));
181
181
  return paragraphs;
182
182
  }
183
183
  const getParagraphsFromBlocks = (blocks) => {
184
184
  const paragraphs = [];
185
185
  for (const block of blocks) if (block.type === "paragraph") paragraphs.push(block);
186
186
  else if (block.type === "table") paragraphs.push(...getTableParagraphs(block));
187
- else if (block.type === "blockSdt") paragraphs.push(...getParagraphsFromBlocks(block.content));
187
+ else if (block.type === "blockSdt" || block.type === "blockCustomXml") paragraphs.push(...getParagraphsFromBlocks(block.content));
188
188
  return paragraphs;
189
189
  };
190
190
  /**
@@ -194,7 +194,7 @@ function getTableParagraphs(table) {
194
194
  const paragraphs = [];
195
195
  for (const row of table.rows) for (const cell of row.cells) for (const content of cell.content) if (content.type === "paragraph") paragraphs.push(content);
196
196
  else if (content.type === "table") paragraphs.push(...getTableParagraphs(content));
197
- else if (content.type === "blockSdt") paragraphs.push(...getParagraphsFromBlocks(content.content));
197
+ else if (content.type === "blockSdt" || content.type === "blockCustomXml") paragraphs.push(...getParagraphsFromBlocks(content.content));
198
198
  return paragraphs;
199
199
  }
200
200
  /**
@@ -205,13 +205,13 @@ function getAllTables(body) {
205
205
  for (const block of body.content) if (block.type === "table") {
206
206
  tables.push(block);
207
207
  tables.push(...getNestedTables(block));
208
- } else if (block.type === "blockSdt") tables.push(...getTablesFromBlocks(block.content));
208
+ } else if (block.type === "blockSdt" || block.type === "blockCustomXml") tables.push(...getTablesFromBlocks(block.content));
209
209
  return tables;
210
210
  }
211
211
  const getTablesFromBlocks = (blocks) => {
212
212
  const tables = [];
213
213
  for (const block of blocks) if (block.type === "table") tables.push(block, ...getNestedTables(block));
214
- else if (block.type === "blockSdt") tables.push(...getTablesFromBlocks(block.content));
214
+ else if (block.type === "blockSdt" || block.type === "blockCustomXml") tables.push(...getTablesFromBlocks(block.content));
215
215
  return tables;
216
216
  };
217
217
  /**
@@ -222,7 +222,7 @@ function getNestedTables(table) {
222
222
  for (const row of table.rows) for (const cell of row.cells) for (const content of cell.content) if (content.type === "table") {
223
223
  tables.push(content);
224
224
  tables.push(...getNestedTables(content));
225
- } else if (content.type === "blockSdt") tables.push(...getTablesFromBlocks(content.content));
225
+ } else if (content.type === "blockSdt" || content.type === "blockCustomXml") tables.push(...getTablesFromBlocks(content.content));
226
226
  return tables;
227
227
  }
228
228
  /**
@@ -232,13 +232,13 @@ function getDocumentText(body) {
232
232
  const lines = [];
233
233
  for (const block of body.content) if (block.type === "paragraph") lines.push(getParagraphText(block));
234
234
  else if (block.type === "table") lines.push(getTableText(block));
235
- else if (block.type === "blockSdt") lines.push(getTextFromBlocks(block.content));
235
+ else if (block.type === "blockSdt" || block.type === "blockCustomXml") lines.push(getTextFromBlocks(block.content));
236
236
  return lines.join("\n");
237
237
  }
238
238
  const getTextFromBlocks = (blocks) => blocks.flatMap((block) => {
239
239
  if (block.type === "paragraph") return [getParagraphText(block)];
240
240
  if (block.type === "table") return [getTableText(block)];
241
- return block.type === "blockSdt" ? [getTextFromBlocks(block.content)] : [];
241
+ return block.type === "blockSdt" || block.type === "blockCustomXml" ? [getTextFromBlocks(block.content)] : [];
242
242
  }).join("\n");
243
243
  /**
244
244
  * Get plain text from a table
@@ -251,7 +251,7 @@ function getTableText(table) {
251
251
  const cellTexts = [];
252
252
  for (const content of cell.content) if (content.type === "paragraph") cellTexts.push(getParagraphText(content));
253
253
  else if (content.type === "table") cellTexts.push(getTableText(content));
254
- else if (content.type === "blockSdt") cellTexts.push(getTextFromBlocks(content.content));
254
+ else if (content.type === "blockSdt" || content.type === "blockCustomXml") cellTexts.push(getTextFromBlocks(content.content));
255
255
  rowTexts.push(cellTexts.join("\n"));
256
256
  }
257
257
  lines.push(rowTexts.join(" "));
@@ -1,5 +1,7 @@
1
1
  import { DocxParagraphSurfaces } from "./paragraphTraversal.js";
2
2
  //#region src/docx/drawingIdNormalization.d.ts
3
+ /** Drawing IDs are package-local identifiers, not image content. */
4
+ declare const drawingXmlWithoutIdentity: (xml: string) => string;
3
5
  declare const normalizeDrawingIds: (surfaces: DocxParagraphSurfaces) => void;
4
6
  //#endregion
5
- export { normalizeDrawingIds };
7
+ export { drawingXmlWithoutIdentity, normalizeDrawingIds };
@@ -22,6 +22,11 @@ const reassignRawDrawingId = ({ xml, id }) => {
22
22
  visit(root);
23
23
  return foundDocPr ? (root.elements ?? []).map(captureVerbatimXml).join("") : null;
24
24
  };
25
+ /** Drawing IDs are package-local identifiers, not image content. */
26
+ const drawingXmlWithoutIdentity = (xml) => reassignRawDrawingId({
27
+ xml,
28
+ id: "0"
29
+ }) ?? xml;
25
30
  const needsGeneratedId = ({ id }) => id === void 0 || id === "" || id === "0";
26
31
  const normalizeDrawingIds = (surfaces) => {
27
32
  const entries = [];
@@ -73,4 +78,4 @@ const normalizeDrawingIds = (surfaces) => {
73
78
  }
74
79
  };
75
80
  //#endregion
76
- export { normalizeDrawingIds };
81
+ export { drawingXmlWithoutIdentity, normalizeDrawingIds };
@@ -1,6 +1,8 @@
1
1
  import { deterministicHexId } from "../utils/hexId.js";
2
2
  import { isXmlNameBoundary, spliceXml } from "./selectiveXmlPatch.js";
3
3
  import { loadDocxArchive } from "./server/boundedArchive.js";
4
+ import { matchCloseTag, matchOpenTag, resolveWordprocessingPrefixes } from "./wordprocessingPrefixes.js";
5
+ import { WORDPROCESSINGML_NAMESPACE_URIS, getChildElements, getLocalName, getNamespaceUri, parseXmlDocument } from "./xmlParser.js";
4
6
  import { TaggedError } from "better-result";
5
7
  import JSZip from "jszip";
6
8
  //#region src/docx/ensureParaIds.ts
@@ -48,8 +50,15 @@ import JSZip from "jszip";
48
50
  * declarations and a `mc:Ignorable` listing `w14` when missing — non-Word
49
51
  * producers declare neither, and absent `mc:Ignorable` handling is what
50
52
  * makes pre-2010 consumers choke on the new attributes.
53
+ * - Prefixes are aliases. Each part is scanned under the prefixes its root
54
+ * binds to WordprocessingML (a default namespace included), `w14` and `mc`
55
+ * (see `resolveWordprocessingPrefixes`), and a minted id is written under
56
+ * the part's own `w14` prefix, which is the one `mc:Ignorable` lists. A
57
+ * part whose bindings a string scan cannot follow (a nested element that
58
+ * rebinds one of them) is refused with {@link EnsureParaIdsError}.
51
59
  * - Idempotent: a document that already has full coverage is returned as the
52
- * original bytes, untouched (`alreadyComplete: true`).
60
+ * original bytes, untouched (`alreadyComplete: true`). A body with
61
+ * paragraphs the scan did not see is refused, never reported complete.
53
62
  * - Digitally signed packages are returned untouched when already complete.
54
63
  * When normalization would rewrite the package, it fails unless the caller
55
64
  * explicitly allows signature invalidation after warning the user.
@@ -70,9 +79,6 @@ const TARGET_PART_PATTERNS = [
70
79
  /^word\/footnotes\.xml$/u,
71
80
  /^word\/endnotes\.xml$/u
72
81
  ];
73
- const PARAGRAPH_OPEN = "<w:p";
74
- const FALLBACK_OPEN = "<mc:Fallback";
75
- const FALLBACK_CLOSE = "</mc:Fallback>";
76
82
  const OPAQUE_XML_REGIONS = [
77
83
  {
78
84
  open: "<!--",
@@ -88,15 +94,30 @@ const OPAQUE_XML_REGIONS = [
88
94
  }
89
95
  ];
90
96
  /**
91
- * The parser accepts the `w:` fallback prefix for paraId, and comment parts
92
- * link replies via `w15:paraId` — all three count toward uniqueness.
97
+ * Every prefixed `paraId` counts toward uniqueness: the parser accepts the
98
+ * WordprocessingML fallback, comment parts link replies via `w15:paraId`, and
99
+ * a producer may spell any of them under a prefix of its own. Over-collecting
100
+ * only steers a minted id away from a value; it never keeps one.
93
101
  */
94
- const ANY_PARA_ID_PATTERN = /\bw(?:14|15)?:paraId=(?<quote>["'])(?<id>[\s\S]*?)\k<quote>/gu;
95
- const OPEN_TAG_PARA_ID_PATTERN = /\sw(?:14)?:paraId=(?<quote>["'])(?<id>[\s\S]*?)\k<quote>/u;
96
- const OPEN_TAG_TEXT_ID_PATTERN = /\sw(?:14)?:textId=(?<quote>["'])(?<id>[\s\S]*?)\k<quote>/u;
97
- const XMLNS_W14_PATTERN = /\sxmlns:w14=(?<quote>["'])(?<value>[\s\S]*?)\k<quote>/u;
98
- const XMLNS_MC_PATTERN = /\sxmlns:mc=(?<quote>["'])(?<value>[\s\S]*?)\k<quote>/u;
99
- const MC_IGNORABLE_PATTERN = /\smc:Ignorable=(?<quote>["'])(?<value>[\s\S]*?)\k<quote>/u;
102
+ const ANY_PARA_ID_PATTERN = /\s[^\s=<>/"':]+:paraId=(?<quote>["'])(?<id>[\s\S]*?)\k<quote>/gu;
103
+ const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
104
+ /** An attribute `localName` under any of `prefixes`, with `quote` and `value` groups. */
105
+ const prefixedAttributePattern = (prefixes, localName) => {
106
+ const names = prefixes.filter((prefix) => prefix !== "").map(escapeRegExp);
107
+ return names.length === 0 ? /(?!)/u : new RegExp(`\\s(?:${names.join("|")}):${localName}=(?<quote>["'])(?<value>[\\s\\S]*?)\\k<quote>`, "u");
108
+ };
109
+ const partSpelling = (xml, partPath) => {
110
+ const resolution = resolveWordprocessingPrefixes(xml);
111
+ if (resolution.type === "unsupported") throw createEnsureParaIdsError(`Cannot normalize paragraph ids in ${partPath}: ${resolution.reason}`);
112
+ const { prefixes } = resolution;
113
+ const attributePrefixes = [...prefixes.w14, ...prefixes.main];
114
+ return {
115
+ prefixes,
116
+ paraId: prefixedAttributePattern(attributePrefixes, "paraId"),
117
+ textId: prefixedAttributePattern(attributePrefixes, "textId"),
118
+ w14Prefix: (prefixes.w14Declared ? prefixes.w14[0] : void 0) ?? MC_IGNORABLE_W14
119
+ };
120
+ };
100
121
  /**
101
122
  * Stamp the edits into the part through the splice owner, which refuses a
102
123
  * result that would leave a comment range with only one half. These edits
@@ -141,7 +162,12 @@ const collectExistingParaIds = (xml, into) => {
141
162
  if (id.length > 0) into.add(id.toUpperCase());
142
163
  }
143
164
  };
144
- const collectFallbackParaIds = (xml, partPath, into) => {
165
+ /**
166
+ * Every paragraph open tag of a part in document order, under whichever
167
+ * WordprocessingML prefix the part binds, with whether it sits in
168
+ * `mc:Fallback` (under the part's own `mc` prefix).
169
+ */
170
+ function* paragraphOpenTags(xml, partPath, { prefixes }) {
145
171
  let fallbackDepth = 0;
146
172
  let pos = 0;
147
173
  while (pos < xml.length) {
@@ -152,27 +178,40 @@ const collectFallbackParaIds = (xml, partPath, into) => {
152
178
  pos = opaqueEnd;
153
179
  continue;
154
180
  }
155
- if (xml.startsWith(FALLBACK_OPEN, tagStart) && isXmlNameBoundary(xml[tagStart + 12])) {
181
+ if (matchOpenTag(xml, tagStart, prefixes.mc, "Fallback") !== -1) {
156
182
  const tagEnd = xml.indexOf(">", tagStart);
157
- if (tagEnd === -1) throw createEnsureParaIdsError(`Unterminated <mc:Fallback> tag in ${partPath}`);
183
+ if (tagEnd === -1) throw createEnsureParaIdsError(`Unterminated mc:Fallback tag in ${partPath}`);
158
184
  if (xml[tagEnd - 1] !== "/") fallbackDepth += 1;
159
185
  pos = tagEnd + 1;
160
186
  continue;
161
187
  }
162
- if (xml.startsWith(FALLBACK_CLOSE, tagStart)) {
188
+ const fallbackClose = matchCloseTag(xml, tagStart, prefixes.mc, "Fallback");
189
+ if (fallbackClose !== -1) {
163
190
  fallbackDepth = Math.max(0, fallbackDepth - 1);
164
- pos = tagStart + 14;
191
+ pos = tagStart + fallbackClose;
165
192
  continue;
166
193
  }
167
- if (fallbackDepth === 0 || !xml.startsWith(PARAGRAPH_OPEN, tagStart) || !isXmlNameBoundary(xml[tagStart + 4])) {
194
+ const nameLength = matchOpenTag(xml, tagStart, prefixes.main, "p");
195
+ if (nameLength === -1) {
168
196
  pos = tagStart + 1;
169
197
  continue;
170
198
  }
171
199
  const tagEnd = xml.indexOf(">", tagStart);
172
- if (tagEnd === -1) throw createEnsureParaIdsError(`Unterminated <w:p> tag in ${partPath}`);
173
- const id = OPEN_TAG_PARA_ID_PATTERN.exec(xml.slice(tagStart, tagEnd + 1))?.groups?.["id"];
174
- if (id) into.add(id.toUpperCase());
200
+ if (tagEnd === -1) throw createEnsureParaIdsError(`Unterminated paragraph tag in ${partPath}`);
175
201
  pos = tagEnd + 1;
202
+ yield {
203
+ tagStart,
204
+ tagEnd,
205
+ nameEnd: tagStart + nameLength,
206
+ inFallback: fallbackDepth > 0
207
+ };
208
+ }
209
+ }
210
+ const collectFallbackParaIds = (xml, partPath, spelling, into) => {
211
+ for (const { tagStart, tagEnd, inFallback } of paragraphOpenTags(xml, partPath, spelling)) {
212
+ if (!inFallback) continue;
213
+ const id = spelling.paraId.exec(xml.slice(tagStart, tagEnd + 1))?.groups?.["value"];
214
+ if (id) into.add(id.toUpperCase());
176
215
  }
177
216
  };
178
217
  /**
@@ -187,74 +226,45 @@ const mintParaId = (context, partPath, ordinal) => {
187
226
  return id;
188
227
  };
189
228
  /**
190
- * One forward scan over a part: every `<w:p>` open tag outside `mc:Fallback`
191
- * either keeps its paraId (valid, first occurrence) or gets a splice edit
192
- * minting / replacing one. `seen` spans parts so the first-occurrence rule is
193
- * document-wide across the scan order.
229
+ * One forward scan over a part: every paragraph open tag outside
230
+ * `mc:Fallback` either keeps its paraId (valid, first occurrence) or gets a
231
+ * splice edit minting / replacing one. `seen` spans parts so the
232
+ * first-occurrence rule is document-wide across the scan order.
194
233
  */
195
- const scanPart = (xml, partPath, context, seen) => {
234
+ const scanPart = (xml, partPath, spelling, context, seen) => {
196
235
  const edits = [];
236
+ const w14 = spelling.w14Prefix;
197
237
  let assigned = 0;
198
238
  let deduplicated = 0;
199
239
  let ordinal = 0;
200
- let fallbackDepth = 0;
201
- let pos = 0;
202
- while (pos < xml.length) {
203
- const tagStart = xml.indexOf("<", pos);
204
- if (tagStart === -1) break;
205
- const opaqueEnd = skipOpaqueXmlRegion(xml, tagStart, partPath);
206
- if (opaqueEnd !== null) {
207
- pos = opaqueEnd;
208
- continue;
209
- }
210
- if (xml.startsWith(FALLBACK_OPEN, tagStart) && isXmlNameBoundary(xml[tagStart + 12])) {
211
- const tagEnd = xml.indexOf(">", tagStart);
212
- if (tagEnd === -1) throw createEnsureParaIdsError(`Unterminated <mc:Fallback> tag in ${partPath}`);
213
- if (xml[tagEnd - 1] !== "/") fallbackDepth += 1;
214
- pos = tagEnd + 1;
215
- continue;
216
- }
217
- if (xml.startsWith(FALLBACK_CLOSE, tagStart)) {
218
- fallbackDepth = Math.max(0, fallbackDepth - 1);
219
- pos = tagStart + 14;
220
- continue;
221
- }
222
- if (!xml.startsWith(PARAGRAPH_OPEN, tagStart) || !isXmlNameBoundary(xml[tagStart + 4])) {
223
- pos = tagStart + 1;
224
- continue;
225
- }
226
- const tagEnd = xml.indexOf(">", tagStart);
227
- if (tagEnd === -1) throw createEnsureParaIdsError(`Unterminated <w:p> tag in ${partPath}`);
228
- pos = tagEnd + 1;
229
- if (fallbackDepth > 0) continue;
240
+ for (const { tagStart, tagEnd, nameEnd, inFallback } of paragraphOpenTags(xml, partPath, spelling)) {
241
+ if (inFallback) continue;
230
242
  ordinal += 1;
231
243
  const openTag = xml.slice(tagStart, tagEnd + 1);
232
- const paraIdMatch = OPEN_TAG_PARA_ID_PATTERN.exec(openTag);
244
+ const paraIdMatch = spelling.paraId.exec(openTag);
233
245
  if (!paraIdMatch) {
234
246
  const id = mintParaId(context, partPath, ordinal);
235
- const insertAt = tagStart + 4;
236
- const textIdMatch = OPEN_TAG_TEXT_ID_PATTERN.exec(openTag);
247
+ const textIdMatch = spelling.textId.exec(openTag);
237
248
  if (textIdMatch) {
238
249
  edits.push({
239
- start: insertAt,
240
- end: insertAt,
241
- text: ` w14:paraId="${id}"`
250
+ start: nameEnd,
251
+ end: nameEnd,
252
+ text: ` ${w14}:paraId="${id}"`
242
253
  });
243
- const range = attributeValueRange(textIdMatch, tagStart, "id");
244
254
  edits.push({
245
- ...range,
255
+ ...attributeValueRange(textIdMatch, tagStart, "value"),
246
256
  text: id
247
257
  });
248
258
  } else edits.push({
249
- start: insertAt,
250
- end: insertAt,
251
- text: ` w14:paraId="${id}" w14:textId="${id}"`
259
+ start: nameEnd,
260
+ end: nameEnd,
261
+ text: ` ${w14}:paraId="${id}" ${w14}:textId="${id}"`
252
262
  });
253
263
  assigned += 1;
254
264
  seen.add(id);
255
265
  continue;
256
266
  }
257
- const value = paraIdMatch.groups["id"].toUpperCase();
267
+ const value = paraIdMatch.groups["value"].toUpperCase();
258
268
  const unassigned = RESERVED_ZERO_ID_PATTERN.test(value);
259
269
  if (!unassigned && !seen.has(value)) {
260
270
  seen.add(value);
@@ -262,22 +272,19 @@ const scanPart = (xml, partPath, context, seen) => {
262
272
  }
263
273
  const id = mintParaId(context, partPath, ordinal);
264
274
  edits.push({
265
- ...attributeValueRange(paraIdMatch, tagStart, "id"),
275
+ ...attributeValueRange(paraIdMatch, tagStart, "value"),
266
276
  text: id
267
277
  });
268
- const textIdMatch = OPEN_TAG_TEXT_ID_PATTERN.exec(openTag);
278
+ const textIdMatch = spelling.textId.exec(openTag);
269
279
  if (textIdMatch) edits.push({
270
- ...attributeValueRange(textIdMatch, tagStart, "id"),
280
+ ...attributeValueRange(textIdMatch, tagStart, "value"),
271
281
  text: id
272
282
  });
273
- else {
274
- const insertAt = tagStart + 4;
275
- edits.push({
276
- start: insertAt,
277
- end: insertAt,
278
- text: ` w14:textId="${id}"`
279
- });
280
- }
283
+ else edits.push({
284
+ start: nameEnd,
285
+ end: nameEnd,
286
+ text: ` ${w14}:textId="${id}"`
287
+ });
281
288
  if (unassigned) assigned += 1;
282
289
  else deduplicated += 1;
283
290
  seen.add(id);
@@ -285,7 +292,8 @@ const scanPart = (xml, partPath, context, seen) => {
285
292
  return {
286
293
  edits,
287
294
  assigned,
288
- deduplicated
295
+ deduplicated,
296
+ paragraphs: ordinal
289
297
  };
290
298
  };
291
299
  /**
@@ -293,7 +301,7 @@ const scanPart = (xml, partPath, context, seen) => {
293
301
  * `xmlns:mc` and lists `w14` in `mc:Ignorable`, so consumers that predate the
294
302
  * 2010 extensions skip the new attributes instead of rejecting the part.
295
303
  */
296
- const ensureRootNamespaces = (xml, partPath) => {
304
+ const ensureRootNamespaces = (xml, partPath, { prefixes, w14Prefix }) => {
297
305
  let pos = 0;
298
306
  let rootStart = -1;
299
307
  while (pos < xml.length) {
@@ -317,29 +325,26 @@ const ensureRootNamespaces = (xml, partPath) => {
317
325
  const rootEnd = xml.indexOf(">", rootStart);
318
326
  if (rootEnd === -1) throw createEnsureParaIdsError(`Unterminated root element in ${partPath}`);
319
327
  const rootTag = xml.slice(rootStart, rootEnd + 1);
328
+ if (!prefixes.mcDeclared && prefixes.mc.length === 0) throw createEnsureParaIdsError(`xmlns:mc has an unexpected namespace URI in ${partPath}`);
329
+ if (!prefixes.w14Declared && prefixes.w14.length === 0) throw createEnsureParaIdsError(`xmlns:w14 has an unexpected namespace URI in ${partPath}`);
320
330
  const edits = [];
321
331
  const declarations = [];
322
- const mcNamespace = XMLNS_MC_PATTERN.exec(rootTag);
323
- if (mcNamespace) {
324
- if (mcNamespace.groups["value"] !== MC_NAMESPACE_URI) throw createEnsureParaIdsError(`xmlns:mc has an unexpected namespace URI in ${partPath}`);
325
- } else declarations.push(` xmlns:mc="${MC_NAMESPACE_URI}"`);
326
- const w14Namespace = XMLNS_W14_PATTERN.exec(rootTag);
327
- if (w14Namespace) {
328
- if (w14Namespace.groups["value"] !== W14_NAMESPACE_URI) throw createEnsureParaIdsError(`xmlns:w14 has an unexpected namespace URI in ${partPath}`);
329
- } else declarations.push(` xmlns:w14="${W14_NAMESPACE_URI}"`);
330
- const ignorable = MC_IGNORABLE_PATTERN.exec(rootTag);
332
+ const mcPrefix = (prefixes.mcDeclared ? prefixes.mc[0] : void 0) ?? "mc";
333
+ if (!prefixes.mcDeclared) declarations.push(` xmlns:mc="${MC_NAMESPACE_URI}"`);
334
+ if (!prefixes.w14Declared) declarations.push(` xmlns:w14="${W14_NAMESPACE_URI}"`);
335
+ const ignorable = prefixedAttributePattern(prefixes.mcDeclared ? prefixes.mc : [mcPrefix], "Ignorable").exec(rootTag);
331
336
  if (ignorable) {
332
337
  const tokens = ignorable.groups["value"].split(/\s+/u).filter((token) => token.length > 0);
333
- if (!tokens.includes(MC_IGNORABLE_W14)) {
338
+ if (!tokens.includes(w14Prefix)) {
334
339
  const { end } = attributeValueRange(ignorable, rootStart, "value");
335
- const text = tokens.length === 0 ? MC_IGNORABLE_W14 : ` ${MC_IGNORABLE_W14}`;
340
+ const text = tokens.length === 0 ? w14Prefix : ` ${w14Prefix}`;
336
341
  edits.push({
337
342
  start: end,
338
343
  end,
339
344
  text
340
345
  });
341
346
  }
342
- } else declarations.push(` mc:Ignorable="${MC_IGNORABLE_W14}"`);
347
+ } else declarations.push(` ${mcPrefix}:Ignorable="${w14Prefix}"`);
343
348
  if (declarations.length > 0) {
344
349
  let nameEnd = rootStart + 1;
345
350
  while (nameEnd < xml.length && !isXmlNameBoundary(xml[nameEnd])) nameEnd += 1;
@@ -351,6 +356,17 @@ const ensureRootNamespaces = (xml, partPath) => {
351
356
  }
352
357
  return edits;
353
358
  };
359
+ const hasWordParagraph = (element) => getLocalName(element.name ?? "") === "p" && WORDPROCESSINGML_NAMESPACE_URIS.has(getNamespaceUri(element) ?? "") || getChildElements(element).some(hasWordParagraph);
360
+ /**
361
+ * A body the string scan saw no paragraph in is either genuinely empty or
362
+ * spelled in a way the scan missed. Only the namespace-aware parser can tell
363
+ * which, and it only has to be asked in that rare case: `alreadyComplete`
364
+ * must never describe paragraphs nobody looked at.
365
+ */
366
+ const assertNoUnscannedParagraphs = (xml, partPath) => {
367
+ const root = parseXmlDocument(xml);
368
+ if (root !== null && hasWordParagraph(root)) throw createEnsureParaIdsError(`Cannot normalize paragraph ids in ${partPath}: its paragraphs are not spelled in a way the scan can patch`);
369
+ };
354
370
  /** OPC part names are case-insensitive; compare lowercased. */
355
371
  const isTargetPart = (path) => TARGET_PART_PATTERNS.some((pattern) => pattern.test(path.toLowerCase()));
356
372
  const toUint8Array = (docx) => docx instanceof Uint8Array ? docx : new Uint8Array(docx);
@@ -380,19 +396,25 @@ const ensureParaIdsInternal = async (docx, options) => {
380
396
  docKey: deterministicHexId(partTexts.get(documentPartName))
381
397
  };
382
398
  const targetParts = [documentPartName, ...xmlPartNames.filter((name) => name !== documentPartName && isTargetPart(name)).sort((a, b) => a.localeCompare(b))];
399
+ const spellings = /* @__PURE__ */ new Map();
383
400
  const seen = /* @__PURE__ */ new Set();
384
- for (const [partPath, xml] of partTexts) if (isTargetPart(partPath)) collectFallbackParaIds(xml, partPath, seen);
385
- else collectExistingParaIds(xml, seen);
401
+ for (const [partPath, xml] of partTexts) if (isTargetPart(partPath)) {
402
+ const spelling = partSpelling(xml, partPath);
403
+ spellings.set(partPath, spelling);
404
+ collectFallbackParaIds(xml, partPath, spelling, seen);
405
+ } else collectExistingParaIds(xml, seen);
386
406
  const updates = /* @__PURE__ */ new Map();
387
407
  let assigned = 0;
388
408
  let deduplicated = 0;
389
409
  for (const partPath of targetParts) {
390
410
  const xml = partTexts.get(partPath);
391
- const scan = scanPart(xml, partPath, context, seen);
411
+ const spelling = spellings.get(partPath);
412
+ const scan = scanPart(xml, partPath, spelling, context, seen);
413
+ if (partPath === documentPartName && scan.paragraphs === 0) assertNoUnscannedParagraphs(xml, partPath);
392
414
  if (scan.edits.length === 0) continue;
393
415
  assigned += scan.assigned;
394
416
  deduplicated += scan.deduplicated;
395
- updates.set(partPath, applySplices(xml, [...scan.edits, ...ensureRootNamespaces(xml, partPath)], partPath));
417
+ updates.set(partPath, applySplices(xml, [...scan.edits, ...ensureRootNamespaces(xml, partPath, spelling)], partPath));
396
418
  }
397
419
  if (updates.size === 0) return {
398
420
  docx: toUint8Array(docx),
@@ -4,7 +4,8 @@ import { parseParagraph } from "./paragraphParser.js";
4
4
  import { standalonePreviewLedger } from "./previewBudget.js";
5
5
  import { captureSdtSiblingMarkers, parseSdtProperties } from "./sdtProperties.js";
6
6
  import { parseTable } from "./tableParser.js";
7
- import { findChildren, findWordprocessingChild, getAttributes, getChildElements, getLocalName, parseXml } from "./xmlParser.js";
7
+ import { captureVerbatimXml } from "./verbatimCapture.js";
8
+ import { WORDPROCESSINGML_NAMESPACE_URIS, findChildren, findWordprocessingChild, getAttributes, getChildElements, getLocalName, parseXml } from "./xmlParser.js";
8
9
  import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
9
10
  //#region src/docx/footnoteParser.ts
10
11
  /**
@@ -49,7 +50,10 @@ function parseNoteBlockContent(element, styles, theme, numbering, rels, media, p
49
50
  properties,
50
51
  content: sdtContent ? parseNoteBlockContent(sdtContent, styles, theme, numbering, rels, media, previews) : []
51
52
  });
52
- }
53
+ } else if (localName === "altChunk" && WORDPROCESSINGML_NAMESPACE_URIS.has(child.namespaceUri ?? "")) blocks.push({
54
+ type: "preservedBlock",
55
+ xml: captureVerbatimXml(child)
56
+ });
53
57
  }
54
58
  return blocks;
55
59
  }
@@ -79,7 +83,7 @@ function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = n
79
83
  const byId = /* @__PURE__ */ new Map();
80
84
  const footnotes = [];
81
85
  if (!footnotesXml) return createFootnoteMap(byId, footnotes);
82
- const rootElement = parseXml(footnotesXml).elements?.find((el) => el.type === "element" && (el.name === "w:footnotes" || el.name?.endsWith(":footnotes")));
86
+ const rootElement = parseXml(footnotesXml).elements?.find((el) => el.type === "element" && getLocalName(el.name ?? "") === "footnotes");
83
87
  if (!rootElement) return createFootnoteMap(byId, footnotes);
84
88
  const footnoteElements = findChildren(rootElement, "w", "footnote");
85
89
  for (const fnEl of footnoteElements) {
@@ -148,7 +152,7 @@ function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = nul
148
152
  const byId = /* @__PURE__ */ new Map();
149
153
  const endnotes = [];
150
154
  if (!endnotesXml) return createEndnoteMap(byId, endnotes);
151
- const rootElement = parseXml(endnotesXml).elements?.find((el) => el.type === "element" && (el.name === "w:endnotes" || el.name?.endsWith(":endnotes")));
155
+ const rootElement = parseXml(endnotesXml).elements?.find((el) => el.type === "element" && getLocalName(el.name ?? "") === "endnotes");
152
156
  if (!rootElement) return createEndnoteMap(byId, endnotes);
153
157
  const endnoteElements = findChildren(rootElement, "w", "endnote");
154
158
  for (const enEl of endnoteElements) {
@@ -5,7 +5,7 @@ import { assignHeaderFooterVerbatimXml } from "./headerFooterVerbatim.js";
5
5
  import { cloneParagraphWithPropertySource } from "./paragraphPropertySource.js";
6
6
  import { standalonePreviewLedger } from "./previewBudget.js";
7
7
  import { parseWatermark } from "./watermarkParser.js";
8
- import { collectXmlnsDeclarations, parseXml } from "./xmlParser.js";
8
+ import { collectXmlnsDeclarations, getLocalName, parseXml } from "./xmlParser.js";
9
9
  //#region src/docx/headerFooterParser.ts
10
10
  /**
11
11
  * Parse a header XML file (word/header*.xml)
@@ -28,7 +28,7 @@ function parseHeader(headerXml, hdrFtrType = "default", styles = null, theme = n
28
28
  content: []
29
29
  };
30
30
  if (!headerXml) return result;
31
- const rootElement = parseXml(headerXml).elements?.find((el) => el.type === "element" && (el.name === "w:hdr" || el.name?.endsWith(":hdr")));
31
+ const rootElement = parseXml(headerXml).elements?.find((el) => el.type === "element" && getLocalName(el.name ?? "") === "hdr");
32
32
  if (!rootElement) return result;
33
33
  const watermarkResult = parseWatermark(rootElement);
34
34
  if (watermarkResult) {
@@ -72,7 +72,7 @@ function parseFooter(footerXml, hdrFtrType = "default", styles = null, theme = n
72
72
  content: []
73
73
  };
74
74
  if (!footerXml) return result;
75
- const rootElement = parseXml(footerXml).elements?.find((el) => el.type === "element" && (el.name === "w:ftr" || el.name?.endsWith(":ftr")));
75
+ const rootElement = parseXml(footerXml).elements?.find((el) => el.type === "element" && getLocalName(el.name ?? "") === "ftr");
76
76
  if (!rootElement) return result;
77
77
  result.content = parseBlockContent(rootElement, styles, theme, numbering, rels, media, {
78
78
  inHeaderFooter: true,
@@ -13,5 +13,24 @@ type NormalizeHeaderFooterReferencesResult = {
13
13
  removedDanglingFooterReferences: number;
14
14
  };
15
15
  declare const normalizeHeaderFooterReferences: ({ documentBody, headers, footers }: NormalizeHeaderFooterReferencesInput) => NormalizeHeaderFooterReferencesResult;
16
+ type AssignHeaderFooterRolesInput = {
17
+ documentBody: document_d_exports.DocumentBody;
18
+ headers?: Map<string, document_d_exports.HeaderFooter>;
19
+ footers?: Map<string, document_d_exports.HeaderFooter>;
20
+ };
21
+ /**
22
+ * Give each header and footer part the role a section reference states for
23
+ * it.
24
+ *
25
+ * A part says nothing about which pages it serves: the `w:type` of the
26
+ * `w:headerReference` / `w:footerReference` naming it does (ECMA-376 Part 1
27
+ * §17.10.5, `ST_HdrFtr`). The parts are read from the document's
28
+ * relationships, before any section is consulted, so each is read as a
29
+ * default part and takes its role here, from the first section that
30
+ * references it. A part no section references stays default; one several
31
+ * sections reference in different roles keeps the first, and a reader that
32
+ * needs every role reads the section references themselves.
33
+ */
34
+ declare const assignHeaderFooterRoles: ({ documentBody, headers, footers }: AssignHeaderFooterRolesInput) => void;
16
35
  //#endregion
17
- export { DANGLING_FOOTER_REFERENCE_WARNING, DANGLING_HEADER_REFERENCE_WARNING, normalizeHeaderFooterReferences };
36
+ export { DANGLING_FOOTER_REFERENCE_WARNING, DANGLING_HEADER_REFERENCE_WARNING, assignHeaderFooterRoles, normalizeHeaderFooterReferences };