@stll/folio-core 0.35.1 → 0.37.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 (236) hide show
  1. package/README.md +59 -1
  2. package/dist/ai-edits/apply.js +878 -377
  3. package/dist/ai-edits/block-identity.d.ts +4 -1
  4. package/dist/ai-edits/block-identity.js +4 -1
  5. package/dist/ai-edits/blockRange.js +14 -14
  6. package/dist/ai-edits/clean-text.d.ts +40 -1
  7. package/dist/ai-edits/clean-text.js +52 -2
  8. package/dist/ai-edits/headless.d.ts +3 -1
  9. package/dist/ai-edits/headless.js +141 -73
  10. package/dist/ai-edits/index.d.ts +3 -3
  11. package/dist/ai-edits/index.js +2 -2
  12. package/dist/ai-edits/read.js +38 -20
  13. package/dist/ai-edits/snapshot.d.ts +14 -6
  14. package/dist/ai-edits/snapshot.js +105 -20
  15. package/dist/ai-edits/table-cell-mutations.js +1 -1
  16. package/dist/ai-edits/table-row-column-mutations.js +7 -0
  17. package/dist/ai-edits/table-template.d.ts +11 -1
  18. package/dist/ai-edits/table-template.js +49 -17
  19. package/dist/ai-edits/types.d.ts +62 -61
  20. package/dist/ai-edits/word-diff.d.ts +18 -3
  21. package/dist/ai-edits/word-diff.js +556 -67
  22. package/dist/ai-suggestions/conflict.js +1 -4
  23. package/dist/ai-suggestions/text-positions.d.ts +8 -0
  24. package/dist/ai-suggestions/text-positions.js +27 -5
  25. package/dist/compare/__fixtures__/body-sequence.js +3 -4
  26. package/dist/compare/column-alignment.d.ts +13 -13
  27. package/dist/compare/column-alignment.js +78 -39
  28. package/dist/compare/compare.d.ts +4 -3
  29. package/dist/compare/compare.js +48 -21
  30. package/dist/compare/content-alignment.d.ts +95 -0
  31. package/dist/compare/content-alignment.js +1450 -0
  32. package/dist/compare/content-types.d.ts +100 -0
  33. package/dist/compare/content-types.js +0 -0
  34. package/dist/compare/content.d.ts +209 -0
  35. package/dist/compare/content.js +885 -0
  36. package/dist/compare/formatting.d.ts +5 -5
  37. package/dist/compare/formatting.js +6 -4
  38. package/dist/compare/plan.d.ts +6 -1
  39. package/dist/compare/plan.js +171 -566
  40. package/dist/compare/scenario.d.ts +2 -2
  41. package/dist/compare/types.d.ts +3 -3
  42. package/dist/compare/verification.d.ts +8 -9
  43. package/dist/compare/verification.js +72 -50
  44. package/dist/compat/eigenpal.d.ts +5 -3
  45. package/dist/compat/eigenpal.js +3 -2
  46. package/dist/controller/headerFooterEditorManager.js +18 -10
  47. package/dist/controller/hiddenEditorApi.js +1 -1
  48. package/dist/controller/hiddenEditorManager.d.ts +7 -2
  49. package/dist/controller/hiddenEditorManager.js +15 -6
  50. package/dist/controller/layoutPipeline.js +5 -3
  51. package/dist/controller/noteEditorManager.js +12 -7
  52. package/dist/display-list/build/headerFooterPrimitives.js +1 -0
  53. package/dist/display-list/build/storyPrimitives.d.ts +5 -2
  54. package/dist/display-list/build/storyPrimitives.js +60 -3
  55. package/dist/display-list/build/tablePrimitives.js +30 -0
  56. package/dist/display-list/primitives.d.ts +1 -1
  57. package/dist/document-operations.d.ts +8 -4
  58. package/dist/document-operations.js +104 -12
  59. package/dist/docx/blockContentParser.js +6 -27
  60. package/dist/docx/commentParser.js +2 -4
  61. package/dist/docx/commentRangeIntegrity.js +2 -4
  62. package/dist/docx/documentClone.d.ts +2 -0
  63. package/dist/docx/documentClone.js +2 -0
  64. package/dist/docx/ensureParaIds.js +9 -4
  65. package/dist/docx/headerFooterParser.js +2 -4
  66. package/dist/docx/normalizeBaseDirection.js +5 -7
  67. package/dist/docx/numberingParser.d.ts +3 -1
  68. package/dist/docx/numberingParser.js +4 -1
  69. package/dist/docx/paragraphParser.js +34 -35
  70. package/dist/docx/paragraphPropertySource.d.ts +49 -0
  71. package/dist/docx/paragraphPropertySource.js +113 -0
  72. package/dist/docx/paragraphTraversal.js +30 -34
  73. package/dist/docx/rezip.d.ts +0 -8
  74. package/dist/docx/rezip.js +41 -16
  75. package/dist/docx/runConsolidator.js +2 -4
  76. package/dist/docx/runParser.js +6 -17
  77. package/dist/docx/sectionParser.js +1 -15
  78. package/dist/docx/serializer/paragraphSerializer.js +289 -30
  79. package/dist/docx/serializer/runSerializer.js +6 -12
  80. package/dist/docx/serializer/sectionPropertiesSerializer.js +2 -10
  81. package/dist/docx/serializer/tableSerializer.js +4 -23
  82. package/dist/docx/serializer/trackedChangeAttributes.d.ts +11 -0
  83. package/dist/docx/serializer/trackedChangeAttributes.js +31 -0
  84. package/dist/docx/server/build.d.ts +1 -1
  85. package/dist/docx/server/createBilingualDocument.js +8 -10
  86. package/dist/docx/server/evaluateDocxXmlPatchProposal.js +22 -13
  87. package/dist/docx/server/validateDocxConformance.js +17 -13
  88. package/dist/docx/tableParser.js +1 -37
  89. package/dist/docx/trackedChangeInfo.d.ts +11 -0
  90. package/dist/docx/trackedChangeInfo.js +38 -0
  91. package/dist/docx/verbatimCapture.d.ts +20 -9
  92. package/dist/docx/verbatimCapture.js +208 -8
  93. package/dist/docx/xmlParser.d.ts +3 -1
  94. package/dist/docx/xmlParser.js +6 -1
  95. package/dist/docx/xmlSafety.d.ts +1 -1
  96. package/dist/docx/xmlSafety.js +157 -0
  97. package/dist/headless-layout.js +5 -4
  98. package/dist/index.d.ts +5 -3
  99. package/dist/index.js +3 -2
  100. package/dist/internal/headlessRevisionResolution.d.ts +23 -0
  101. package/dist/internal/headlessRevisionResolution.js +155 -0
  102. package/dist/internal/headlessRevisionResolutionGuard.d.ts +12 -0
  103. package/dist/internal/headlessRevisionResolutionGuard.js +28 -0
  104. package/dist/internal/pageBreakRunDescendantIndex.d.ts +9 -0
  105. package/dist/internal/pageBreakRunDescendantIndex.js +27 -0
  106. package/dist/internal/pageBreakRunPartition.d.ts +26 -0
  107. package/dist/internal/pageBreakRunPartition.js +35 -0
  108. package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +15 -0
  109. package/dist/internal/pageBreakRunSourceDescendantIndex.js +126 -0
  110. package/dist/internal/sectionEndpointResolution.d.ts +32 -0
  111. package/dist/internal/sectionEndpointResolution.js +38 -0
  112. package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
  113. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +16 -4
  114. package/dist/layout-bridge/convert/headerFooterLayout.js +52 -9
  115. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -0
  116. package/dist/layout-bridge/convert/toFlowBlocks.js +391 -82
  117. package/dist/layout-bridge/dom/clickToPositionDom.d.ts +8 -1
  118. package/dist/layout-bridge/dom/clickToPositionDom.js +114 -40
  119. package/dist/layout-bridge/dom/textStreamDom.d.ts +24 -0
  120. package/dist/layout-bridge/dom/textStreamDom.js +75 -0
  121. package/dist/layout-bridge/headerFooterLayout.js +16 -30
  122. package/dist/layout-engine/index.js +12 -3
  123. package/dist/layout-engine/measure/tableFragmentBorderGeometry.d.ts +17 -0
  124. package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +24 -0
  125. package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
  126. package/dist/layout-engine/types.d.ts +7 -0
  127. package/dist/layout-painter/imageLayout.d.ts +1 -1
  128. package/dist/layout-painter/renderTable.js +20 -0
  129. package/dist/markdown/renderBlock.js +7 -10
  130. package/dist/model.d.ts +1 -1
  131. package/dist/paged-layout/rangeProjection.js +6 -9
  132. package/dist/paged-layout/transactionDirtyRange.d.ts +3 -1
  133. package/dist/paged-layout/transactionDirtyRange.js +23 -1
  134. package/dist/prosemirror/attrs/index.d.ts +7 -3
  135. package/dist/prosemirror/attrs/index.js +128 -7
  136. package/dist/prosemirror/bookmarkBoundaryIntegrity.d.ts +9 -0
  137. package/dist/prosemirror/bookmarkBoundaryIntegrity.js +22 -0
  138. package/dist/prosemirror/commands/comments.d.ts +10 -1
  139. package/dist/prosemirror/commands/comments.js +551 -87
  140. package/dist/prosemirror/commands/formatPainter.d.ts +45 -10
  141. package/dist/prosemirror/commands/formatPainter.js +319 -63
  142. package/dist/prosemirror/commands/index.d.ts +2 -2
  143. package/dist/prosemirror/commands/pageBreak.d.ts +5 -2
  144. package/dist/prosemirror/commands/pageBreak.js +18 -36
  145. package/dist/prosemirror/commands/propertyChangeScope.d.ts +27 -3
  146. package/dist/prosemirror/commands/propertyChangeScope.js +85 -14
  147. package/dist/prosemirror/conversion/fromProseDoc.d.ts +8 -5
  148. package/dist/prosemirror/conversion/fromProseDoc.js +935 -223
  149. package/dist/prosemirror/conversion/runShadingMark.js +2 -2
  150. package/dist/prosemirror/conversion/toProseDoc.d.ts +26 -1
  151. package/dist/prosemirror/conversion/toProseDoc.js +439 -291
  152. package/dist/prosemirror/extensions/StarterKit.js +4 -0
  153. package/dist/prosemirror/extensions/core/ParagraphExtension.js +54 -6
  154. package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +7 -1
  155. package/dist/prosemirror/extensions/features/ListExtension.js +95 -123
  156. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +19 -6
  157. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +27 -1
  158. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +134 -30
  159. package/dist/prosemirror/extensions/features/pasteCleanup.js +9 -15
  160. package/dist/prosemirror/extensions/marks/BoldExtension.js +4 -3
  161. package/dist/prosemirror/extensions/marks/CharacterStyleExtension.d.ts +4 -7
  162. package/dist/prosemirror/extensions/marks/CharacterStyleExtension.js +5 -11
  163. package/dist/prosemirror/extensions/marks/FontSizeExtension.js +3 -3
  164. package/dist/prosemirror/extensions/marks/ItalicExtension.js +4 -3
  165. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.d.ts +13 -0
  166. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.js +39 -0
  167. package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.d.ts +7 -1
  168. package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +67 -21
  169. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
  170. package/dist/prosemirror/extensions/marks/markUtils.d.ts +8 -1
  171. package/dist/prosemirror/extensions/marks/markUtils.js +88 -2
  172. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +44 -3
  173. package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
  174. package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +15 -4
  175. package/dist/prosemirror/extensions/nodes/PageBreakExtension.d.ts +6 -0
  176. package/dist/prosemirror/extensions/nodes/PageBreakExtension.js +6 -0
  177. package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.d.ts +6 -0
  178. package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.js +36 -0
  179. package/dist/prosemirror/findReplaceSelection.js +8 -3
  180. package/dist/prosemirror/index.d.ts +3 -3
  181. package/dist/prosemirror/listMarker.d.ts +26 -1
  182. package/dist/prosemirror/listMarker.js +108 -14
  183. package/dist/prosemirror/pageBreakRunProjection.d.ts +28 -0
  184. package/dist/prosemirror/pageBreakRunProjection.js +47 -0
  185. package/dist/prosemirror/paraText.js +6 -0
  186. package/dist/prosemirror/paragraphAlignment.d.ts +12 -0
  187. package/dist/prosemirror/paragraphAlignment.js +13 -0
  188. package/dist/prosemirror/paragraphSpacing.d.ts +29 -0
  189. package/dist/prosemirror/paragraphSpacing.js +125 -0
  190. package/dist/prosemirror/plugins/documentNumbering.d.ts +8 -0
  191. package/dist/prosemirror/plugins/documentNumbering.js +18 -0
  192. package/dist/prosemirror/plugins/pmTextScan.d.ts +3 -2
  193. package/dist/prosemirror/plugins/pmTextScan.js +14 -4
  194. package/dist/prosemirror/plugins/suggestionMode.js +9 -11
  195. package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +16 -0
  196. package/dist/prosemirror/rebaseParagraphRunFormatting.js +61 -0
  197. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +64 -0
  198. package/dist/prosemirror/runFormattingInlineCarriers.js +121 -0
  199. package/dist/prosemirror/runFormattingProvenance.d.ts +12 -0
  200. package/dist/prosemirror/runFormattingProvenance.js +48 -0
  201. package/dist/prosemirror/runFormattingReconciliation.d.ts +25 -0
  202. package/dist/prosemirror/runFormattingReconciliation.js +54 -0
  203. package/dist/prosemirror/runPropertyChangeResolution.d.ts +18 -0
  204. package/dist/prosemirror/runPropertyChangeResolution.js +18 -0
  205. package/dist/prosemirror/runStyleFormatting.d.ts +50 -0
  206. package/dist/prosemirror/runStyleFormatting.js +105 -0
  207. package/dist/prosemirror/schema/index.d.ts +3 -3
  208. package/dist/prosemirror/schema/marks.d.ts +84 -9
  209. package/dist/prosemirror/schema/marks.js +73 -1
  210. package/dist/prosemirror/schema/nodes.d.ts +30 -6
  211. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +14 -2
  212. package/dist/prosemirror/styles/resolvedStyleAttrs.js +45 -23
  213. package/dist/prosemirror/styles/styleResolver.d.ts +10 -13
  214. package/dist/prosemirror/styles/styleResolver.js +3 -3
  215. package/dist/prosemirror/styles/styleToggleCascade.d.ts +8 -1
  216. package/dist/prosemirror/styles/styleToggleCascade.js +24 -1
  217. package/dist/prosemirror/tableGridMutation.d.ts +20 -0
  218. package/dist/prosemirror/tableGridMutation.js +30 -0
  219. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +31 -0
  220. package/dist/prosemirror/trackedRunInlineAtoms.js +39 -0
  221. package/dist/prosemirror/utils/visualLineNavigation.js +27 -31
  222. package/dist/prosemirror/validation.js +23 -4
  223. package/dist/redline.js +4 -1
  224. package/dist/render-dom/HeaderFooterSelectionOverlay.js +20 -20
  225. package/dist/render-dom/RenderedDomContext.js +17 -34
  226. package/dist/server.d.ts +4 -4
  227. package/dist/server.js +2 -2
  228. package/dist/style-engine/styleEngine.d.ts +1 -1
  229. package/dist/utils/clipboard.js +1 -1
  230. package/dist/utils/findReplace.js +38 -21
  231. package/dist/utils/mergeDocumentContent.js +3 -3
  232. package/dist/utils/replaceText.js +2 -1
  233. package/dist/version-comparison.d.ts +38 -44
  234. package/dist/version-comparison.js +270 -399
  235. package/dist/watermark/index.js +2 -4
  236. package/package.json +8 -2
@@ -1,6 +1,8 @@
1
1
  import { convertBulletToUnicode } from "../../docx/bulletMarkers.js";
2
2
  import { resolveDocumentGridLinePitch } from "../../docx/documentGrid.js";
3
3
  import { getFontAlternate } from "../../fonts/fontAlternates.js";
4
+ import { buildPageBreakRunDescendantIndex } from "../../internal/pageBreakRunDescendantIndex.js";
5
+ import { partitionRunsAtPageBreaks } from "../../internal/pageBreakRunPartition.js";
4
6
  import { setHyperlinkInstanceIndex } from "../../layout-engine/measure/hyperlinkInstance.js";
5
7
  import { setParagraphFrame } from "../../layout-engine/paragraphFrame.js";
6
8
  import { setTextBoxGroupId } from "../../layout-engine/textBoxGroup.js";
@@ -11,10 +13,12 @@ import { autospacingMatchesBase } from "../../prosemirror/autospacingBase.js";
11
13
  import { runShadingAttrsToShading } from "../../prosemirror/conversion/runShadingMark.js";
12
14
  import { advanceListMarker, advanceVisibleListMarker, cloneListCounterState, formatCounter, resolveListTemplate } from "../../prosemirror/listMarker.js";
13
15
  import { resolveNumberedRefFields } from "../../prosemirror/numberedRefFields.js";
16
+ import { pageBreakRunParagraphProjectionDisposition } from "../../prosemirror/pageBreakRunProjection.js";
14
17
  import { directionToBidi } from "../../prosemirror/paragraphDirection.js";
15
- import { cascadeStyleTextFormatting } from "../../prosemirror/styles/styleToggleCascade.js";
18
+ import { resolveEffectiveRunStyleFormatting } from "../../prosemirror/runStyleFormatting.js";
16
19
  import { expectTextBoxAnchorAttrs } from "../../prosemirror/textBoxAnchorAttrs.js";
17
20
  import { assertValidProseMirrorDocument } from "../../prosemirror/validation.js";
21
+ import { createStyleEngine } from "../../style-engine/styleEngine.js";
18
22
  import { normalizeShapeTextAnchor } from "../../types/documentEnumValues.js";
19
23
  import { resolveColor, resolveHighlightToCss } from "../../utils/colorResolver.js";
20
24
  import { resolveThemeFont } from "../../utils/fontResolver.js";
@@ -23,6 +27,7 @@ import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js"
23
27
  import { decodeOoxmlSymbolCharacter } from "../../utils/ooxmlSymbol.js";
24
28
  import { sanitizeImageSrc } from "../../utils/sanitizeImageSrc.js";
25
29
  import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
30
+ import { STYLE_TOGGLE_KEYS } from "../../utils/textFormattingMerge.js";
26
31
  import { AUTO_PARAGRAPH_SPACING_PX, halfPointsToPixels, halfPointsToPoints, pointsToPixels } from "../../utils/units.js";
27
32
  import { getColumns } from "../sectionColumns.js";
28
33
  import { groupParagraphFrames } from "./paragraphFrames.js";
@@ -102,6 +107,7 @@ function resetBlockIdCounter() {
102
107
  function extractRunFormatting(marks, theme, fontAlternates) {
103
108
  const formatting = {};
104
109
  let hasNoteRef = false;
110
+ let runFormattingOverride;
105
111
  for (const mark of marks) switch (mark.type.name) {
106
112
  case "bold":
107
113
  formatting.bold = true;
@@ -216,7 +222,7 @@ function extractRunFormatting(marks, theme, fontAlternates) {
216
222
  formatting.textEffect = expectTextEffectMarkAttrs(mark).effect;
217
223
  break;
218
224
  case "runFormattingOverride":
219
- applyRunFormattingOverrides(formatting, expectRunFormattingOverrideMarkAttrs(mark));
225
+ runFormattingOverride = expectRunFormattingOverrideMarkAttrs(mark);
220
226
  break;
221
227
  case "emphasisMark":
222
228
  formatting.emphasisMark = expectEmphasisMarkAttrs(mark).type ?? "dot";
@@ -278,6 +284,7 @@ function extractRunFormatting(marks, theme, fontAlternates) {
278
284
  }
279
285
  default: break;
280
286
  }
287
+ if (runFormattingOverride) applyRunFormattingOverrides(formatting, runFormattingOverride);
281
288
  if (hasNoteRef && formatting.subscript) delete formatting.superscript;
282
289
  return formatting;
283
290
  }
@@ -314,54 +321,135 @@ function mergeRunFormatting(paraDefaults, formatting) {
314
321
  if (formatting.horizontalScale === 100 && paraDefaults.horizontalScale === void 0) delete merged.horizontalScale;
315
322
  return merged;
316
323
  }
324
+ const CHARACTER_STYLE_TOGGLE_LAYOUT_PROPERTIES = {
325
+ allCaps: "allCaps",
326
+ bold: "bold",
327
+ boldCs: "complexScriptBold",
328
+ emboss: "emboss",
329
+ hidden: "hidden",
330
+ imprint: "imprint",
331
+ italic: "italic",
332
+ italicCs: "complexScriptItalic",
333
+ outline: "textOutline",
334
+ shadow: "textShadow",
335
+ smallCaps: "smallCaps",
336
+ strike: "strike"
337
+ };
317
338
  /** Restore character-style toggle values that plain visual marks cannot represent. */
318
- function applyCharacterStyleToggleFormatting({ formatting, marks, paraDefaults }) {
339
+ function applyCharacterStyleToggleFormatting({ formatting, marks, paragraphFormatting, styleResolver }) {
319
340
  const characterStyleMark = marks.find((mark) => mark.type.name === "characterStyle");
320
- if (!characterStyleMark) return;
321
- const styleRPr = expectCharacterStyleMarkAttrs(characterStyleMark)._styleRPr;
341
+ const styleRPr = characterStyleMark ? styleResolver.getRunStyleOwnProperties(expectCharacterStyleMarkAttrs(characterStyleMark).styleId) : styleResolver.getDefaultCharacterStyle()?.rPr;
322
342
  if (!styleRPr) return;
323
- const effectiveStyleFormatting = cascadeStyleTextFormatting([{
324
- formatting: {
325
- bold: paraDefaults.bold ?? false,
326
- boldCs: paraDefaults.complexScriptBold ?? false,
327
- italic: paraDefaults.italic ?? false,
328
- italicCs: paraDefaults.complexScriptItalic ?? false
329
- },
330
- type: "direct"
331
- }, {
332
- formatting: styleRPr,
333
- type: "style"
334
- }]).formatting;
335
- if (styleRPr.bold !== void 0 && formatting.bold === void 0) formatting.bold = effectiveStyleFormatting?.bold ?? false;
336
- if (styleRPr.boldCs !== void 0 && formatting.complexScriptBold === void 0) formatting.complexScriptBold = effectiveStyleFormatting?.boldCs ?? false;
337
- if (styleRPr.italic !== void 0 && formatting.italic === void 0) formatting.italic = effectiveStyleFormatting?.italic ?? false;
338
- if (styleRPr.italicCs !== void 0 && formatting.complexScriptItalic === void 0) formatting.complexScriptItalic = effectiveStyleFormatting?.italicCs ?? false;
339
- if (styleRPr.allCaps === true && formatting.allCaps === void 0) formatting.allCaps = false;
340
- if (styleRPr.emboss === true && formatting.emboss === void 0) formatting.emboss = false;
341
- if (styleRPr.imprint === true && formatting.imprint === void 0) formatting.imprint = false;
342
- if (styleRPr.outline === true && formatting.textOutline === void 0) formatting.textOutline = false;
343
- if (styleRPr.shadow === true && formatting.textShadow === void 0) formatting.textShadow = false;
344
- if (styleRPr.smallCaps === true && formatting.smallCaps === void 0) formatting.smallCaps = false;
345
- if (styleRPr.strike === true && formatting.strike === void 0) formatting.strike = false;
346
- if (styleRPr.hidden === true && formatting.hidden === void 0) formatting.hidden = false;
343
+ const effectiveStyleFormatting = resolveEffectiveRunStyleFormatting({
344
+ marks,
345
+ paragraphFormatting,
346
+ styleResolver
347
+ });
348
+ for (const property of STYLE_TOGGLE_KEYS) {
349
+ if (styleRPr[property] === void 0) continue;
350
+ const layoutProperty = CHARACTER_STYLE_TOGGLE_LAYOUT_PROPERTIES[property];
351
+ if (formatting[layoutProperty] === void 0) Reflect.set(formatting, layoutProperty, effectiveStyleFormatting?.[property] ?? false);
352
+ }
347
353
  }
354
+ const suppressInheritedRunFormatting = (formatting, property) => {
355
+ Reflect.set(formatting, property, void 0);
356
+ };
357
+ const RUN_FORMATTING_OVERRIDE_HANDLER_ENTRIES = Object.entries({
358
+ _authoredOff() {},
359
+ _authoredOn() {},
360
+ _authoredValues() {},
361
+ allCaps(formatting, value) {
362
+ if (typeof value === "boolean") formatting.allCaps = value;
363
+ },
364
+ bold(formatting, value) {
365
+ if (typeof value === "boolean") formatting.bold = value;
366
+ },
367
+ boldCs(formatting, value) {
368
+ if (typeof value === "boolean") formatting.complexScriptBold = value;
369
+ },
370
+ color(formatting, value) {
371
+ if (value === "auto") {
372
+ suppressInheritedRunFormatting(formatting, "color");
373
+ suppressInheritedRunFormatting(formatting, "textColorSource");
374
+ }
375
+ },
376
+ complexScriptPropertyAbsences() {},
377
+ cs(formatting, value) {
378
+ if (typeof value === "boolean") formatting.forceComplexScript = value;
379
+ },
380
+ directFontProperties() {},
381
+ doubleStrike(formatting, value) {
382
+ if (value === false && formatting.strike === void 0) formatting.strike = false;
383
+ },
384
+ effect(formatting, value) {
385
+ if (value === "none") suppressInheritedRunFormatting(formatting, "textEffect");
386
+ },
387
+ emboss(formatting, value) {
388
+ if (typeof value === "boolean") formatting.emboss = value;
389
+ },
390
+ emphasisMark(formatting, value) {
391
+ if (value === "none") suppressInheritedRunFormatting(formatting, "emphasisMark");
392
+ },
393
+ fontSizeCs(formatting, value) {
394
+ if (typeof value === "number") formatting.complexScriptFontSize = value / 2;
395
+ },
396
+ hidden(formatting, value) {
397
+ if (typeof value === "boolean") formatting.hidden = value;
398
+ },
399
+ highlight(formatting, value) {
400
+ if (value === "none") suppressInheritedRunFormatting(formatting, "highlight");
401
+ },
402
+ imprint(formatting, value) {
403
+ if (typeof value === "boolean") formatting.imprint = value;
404
+ },
405
+ italic(formatting, value) {
406
+ if (typeof value === "boolean") formatting.italic = value;
407
+ },
408
+ italicCs(formatting, value) {
409
+ if (typeof value === "boolean") formatting.complexScriptItalic = value;
410
+ },
411
+ kerning(formatting, value) {
412
+ if (value === 0) formatting.kerningMinPt = 0;
413
+ },
414
+ outline(formatting, value) {
415
+ if (typeof value === "boolean") formatting.textOutline = value;
416
+ },
417
+ position(formatting, value) {
418
+ if (value === 0) formatting.positionPx = 0;
419
+ },
420
+ rtl(formatting, value) {
421
+ if (value === false) formatting.rtl = false;
422
+ },
423
+ scale(formatting, value) {
424
+ if (value === 100) formatting.horizontalScale = 100;
425
+ },
426
+ shading(formatting, value) {
427
+ if (typeof value === "object" && value !== null && Reflect.get(value, "pattern") === "nil") suppressInheritedRunFormatting(formatting, "shading");
428
+ },
429
+ shadow(formatting, value) {
430
+ if (typeof value === "boolean") formatting.textShadow = value;
431
+ },
432
+ smallCaps(formatting, value) {
433
+ if (typeof value === "boolean") formatting.smallCaps = value;
434
+ },
435
+ spacing(formatting, value) {
436
+ if (value === 0) formatting.letterSpacing = 0;
437
+ },
438
+ strike(formatting, value) {
439
+ if (typeof value === "boolean") formatting.strike = value;
440
+ },
441
+ underline(formatting, value) {
442
+ if (value === "none") formatting.underline = false;
443
+ },
444
+ vertAlign(formatting, value) {
445
+ if (value === "baseline") {
446
+ formatting.superscript = false;
447
+ formatting.subscript = false;
448
+ }
449
+ }
450
+ });
348
451
  function applyRunFormattingOverrides(formatting, attrs) {
349
- if (attrs.bold !== void 0) formatting.bold = attrs.bold;
350
- if (attrs.italic !== void 0) formatting.italic = attrs.italic;
351
- if (attrs.underline === "none") formatting.underline = false;
352
- if (attrs.strike !== void 0) formatting.strike = attrs.strike;
353
- if (attrs.allCaps !== void 0) formatting.allCaps = attrs.allCaps;
354
- if (attrs.smallCaps !== void 0) formatting.smallCaps = attrs.smallCaps;
355
- if (attrs.hidden !== void 0) formatting.hidden = attrs.hidden;
356
- if (attrs.emboss !== void 0) formatting.emboss = attrs.emboss;
357
- if (attrs.imprint !== void 0) formatting.imprint = attrs.imprint;
358
- if (attrs.shadow !== void 0) formatting.textShadow = attrs.shadow;
359
- if (attrs.outline !== void 0) formatting.textOutline = attrs.outline;
360
- if (attrs.rtl === false) formatting.rtl = false;
361
- if (attrs.boldCs !== void 0) formatting.complexScriptBold = attrs.boldCs;
362
- if (attrs.italicCs !== void 0) formatting.complexScriptItalic = attrs.italicCs;
363
- if (attrs.fontSizeCs !== void 0) formatting.complexScriptFontSize = attrs.fontSizeCs / 2;
364
- if (attrs.cs !== void 0) formatting.forceComplexScript = attrs.cs;
452
+ for (const [key, handler] of RUN_FORMATTING_OVERRIDE_HANDLER_ENTRIES) handler(formatting, Reflect.get(attrs, key));
365
453
  }
366
454
  function textFormattingToRunFormatting(defaultTextFormatting, theme, fontAlternates) {
367
455
  if (!defaultTextFormatting) return {};
@@ -483,10 +571,19 @@ function stripTocHyperlinkStyle(formatting) {
483
571
  delete formatting.color;
484
572
  delete formatting.underline;
485
573
  }
574
+ const isTrackedRunMark = ({ type }) => type.name === "insertion" || type.name === "deletion";
486
575
  /**
487
- * Convert a paragraph node to runs.
576
+ * Inline wrappers own marks that apply to every projected descendant. A
577
+ * descendant's mark of the same type is more specific, and any descendant
578
+ * revision replaces (rather than combines with) an inherited revision.
488
579
  */
489
- function paragraphToRuns(node, startPos, _options) {
580
+ const mergeProjectedInlineMarks = (inheritedMarks, ownMarks) => {
581
+ if (inheritedMarks.length === 0) return ownMarks;
582
+ const ownMarkTypes = new Set(ownMarks.map(({ type }) => type));
583
+ const hasOwnTrackedMark = ownMarks.some(isTrackedRunMark);
584
+ return [...inheritedMarks.filter((mark) => !ownMarkTypes.has(mark.type) && !(hasOwnTrackedMark && isTrackedRunMark(mark))), ...ownMarks];
585
+ };
586
+ function paragraphToRuns(node, startPos, _options, pageBreaks) {
490
587
  const runs = [];
491
588
  const offset = startPos + 1;
492
589
  const theme = _options.theme;
@@ -496,7 +593,7 @@ function paragraphToRuns(node, startPos, _options) {
496
593
  const paragraphStyleId = pmAttrs.styleId;
497
594
  const inTocParagraph = pmAttrs._tableOfContentsLevel !== void 0 || tableOfContentsStyleLevel({ styleId: paragraphStyleId }) !== void 0;
498
595
  let leadingRenderedPageBreakPending = pmAttrs.renderedPageBreakBefore === true;
499
- function pushRunsForChild(child, childPos) {
596
+ function pushRunsForChild(child, childPos, inheritedMarks = []) {
500
597
  if (child.type.name === "bookmarkBoundary") return;
501
598
  if (child.type.name === "renderedPageBreak") {
502
599
  if (leadingRenderedPageBreakPending) {
@@ -510,13 +607,46 @@ function paragraphToRuns(node, startPos, _options) {
510
607
  });
511
608
  return;
512
609
  }
610
+ const effectiveMarks = mergeProjectedInlineMarks(inheritedMarks, child.marks);
611
+ if (child.type.name === "pageBreakRun") {
612
+ const trackedChange = extractRunFormatting(effectiveMarks, theme, fontAlternates);
613
+ if (trackedChange.isDeletion) {
614
+ runs.push({
615
+ kind: "text",
616
+ text: "",
617
+ isDeletion: true,
618
+ ...trackedChange.changeAuthor !== void 0 ? { changeAuthor: trackedChange.changeAuthor } : {},
619
+ ...trackedChange.changeDate !== void 0 ? { changeDate: trackedChange.changeDate } : {},
620
+ ...trackedChange.changeRevisionId !== void 0 ? { changeRevisionId: trackedChange.changeRevisionId } : {},
621
+ ...trackedChange.isSuggestion === true ? { isSuggestion: true } : {},
622
+ ...trackedChange.suggestionId !== void 0 ? { suggestionId: trackedChange.suggestionId } : {},
623
+ pmStart: childPos,
624
+ pmEnd: childPos + child.nodeSize
625
+ });
626
+ return;
627
+ }
628
+ pageBreaks?.push({
629
+ pmStart: childPos,
630
+ pmEnd: childPos + child.nodeSize,
631
+ ...trackedChange.isInsertion ? { trackedChange: {
632
+ isInsertion: true,
633
+ ...trackedChange.changeAuthor !== void 0 ? { changeAuthor: trackedChange.changeAuthor } : {},
634
+ ...trackedChange.changeDate !== void 0 ? { changeDate: trackedChange.changeDate } : {},
635
+ ...trackedChange.changeRevisionId !== void 0 ? { changeRevisionId: trackedChange.changeRevisionId } : {},
636
+ ...trackedChange.isSuggestion === true ? { isSuggestion: true } : {},
637
+ ...trackedChange.suggestionId !== void 0 ? { suggestionId: trackedChange.suggestionId } : {}
638
+ } } : {}
639
+ });
640
+ return;
641
+ }
513
642
  if (child.type.name !== "sdt") leadingRenderedPageBreakPending = false;
514
643
  if (child.isText && child.text) {
515
- const formatting = extractRunFormatting(child.marks, theme, fontAlternates);
644
+ const formatting = extractRunFormatting(effectiveMarks, theme, fontAlternates);
516
645
  applyCharacterStyleToggleFormatting({
517
646
  formatting,
518
- marks: child.marks,
519
- paraDefaults
647
+ marks: effectiveMarks,
648
+ paragraphFormatting: pmAttrs.defaultTextFormatting,
649
+ styleResolver: _options.styleResolver
520
650
  });
521
651
  if (inTocParagraph) stripTocHyperlinkStyle(formatting);
522
652
  const run = {
@@ -533,11 +663,12 @@ function paragraphToRuns(node, startPos, _options) {
533
663
  const attrs = expectSymbolAttrs(child);
534
664
  const text = decodeOoxmlSymbolCharacter(attrs.char);
535
665
  if (text === null) return;
536
- const formatting = extractRunFormatting(child.marks, theme, fontAlternates);
666
+ const formatting = extractRunFormatting(effectiveMarks, theme, fontAlternates);
537
667
  applyCharacterStyleToggleFormatting({
538
668
  formatting,
539
- marks: child.marks,
540
- paraDefaults
669
+ marks: effectiveMarks,
670
+ paragraphFormatting: pmAttrs.defaultTextFormatting,
671
+ styleResolver: _options.styleResolver
541
672
  });
542
673
  if (inTocParagraph) stripTocHyperlinkStyle(formatting);
543
674
  const alternateFontFamily = getFontAlternate(attrs.font, fontAlternates);
@@ -561,11 +692,12 @@ function paragraphToRuns(node, startPos, _options) {
561
692
  return;
562
693
  }
563
694
  if (child.type.name === "tab") {
564
- const formatting = extractRunFormatting(child.marks, theme, fontAlternates);
695
+ const formatting = extractRunFormatting(effectiveMarks, theme, fontAlternates);
565
696
  applyCharacterStyleToggleFormatting({
566
697
  formatting,
567
- marks: child.marks,
568
- paraDefaults
698
+ marks: effectiveMarks,
699
+ paragraphFormatting: pmAttrs.defaultTextFormatting,
700
+ styleResolver: _options.styleResolver
569
701
  });
570
702
  const run = {
571
703
  kind: "tab",
@@ -580,11 +712,28 @@ function paragraphToRuns(node, startPos, _options) {
580
712
  const attrs = expectImageAttrs(child);
581
713
  if (!hasPaintableImageSource(attrs.src) && !hasRelationshipBackedImageBox(attrs)) return;
582
714
  const constrained = constrainImageToPage(attrs.width ?? 100, attrs.height ?? 100, _options.pageContentHeight);
583
- const trackedFmt = extractRunFormatting(child.marks, theme, fontAlternates);
715
+ const trackedFmt = extractRunFormatting(effectiveMarks, theme, fontAlternates);
584
716
  const run = buildImageRun(attrs, constrained, childPos, childPos + child.nodeSize, trackedFmt);
585
717
  runs.push(run);
586
718
  return;
587
719
  }
720
+ if (child.type.name === "structuredField") {
721
+ let containsPageBreak = false;
722
+ child.descendants((descendant) => {
723
+ if (descendant.type.name === "pageBreakRun") {
724
+ containsPageBreak = true;
725
+ return false;
726
+ }
727
+ return true;
728
+ });
729
+ if (containsPageBreak) {
730
+ const fieldContentStart = childPos + 1;
731
+ child.forEach((fieldChild, fieldChildOffset) => {
732
+ pushRunsForChild(fieldChild, fieldContentStart + fieldChildOffset, effectiveMarks);
733
+ });
734
+ return;
735
+ }
736
+ }
588
737
  if (child.type.name === "field" || child.type.name === "structuredField") {
589
738
  const attrs = expectFieldAttrs(child);
590
739
  const ft = attrs.fieldType;
@@ -593,11 +742,12 @@ function paragraphToRuns(node, startPos, _options) {
593
742
  else if (ft === "NUMPAGES") mappedType = "NUMPAGES";
594
743
  else if (ft === "DATE") mappedType = "DATE";
595
744
  else if (ft === "TIME") mappedType = "TIME";
596
- const extractedFieldFormatting = extractRunFormatting(child.marks, theme, fontAlternates);
745
+ const extractedFieldFormatting = extractRunFormatting(effectiveMarks, theme, fontAlternates);
597
746
  applyCharacterStyleToggleFormatting({
598
747
  formatting: extractedFieldFormatting,
599
- marks: child.marks,
600
- paraDefaults
748
+ marks: effectiveMarks,
749
+ paragraphFormatting: pmAttrs.defaultTextFormatting,
750
+ styleResolver: _options.styleResolver
601
751
  });
602
752
  if (inTocParagraph) stripTocHyperlinkStyle(extractedFieldFormatting);
603
753
  const fieldFormatting = markDefaultBlackTextColorSource(extractedFieldFormatting, paraDefaults);
@@ -632,7 +782,7 @@ function paragraphToRuns(node, startPos, _options) {
632
782
  if (child.type.name === "sdt") {
633
783
  const sdtInnerOffset = childPos + 1;
634
784
  child.forEach((sdtChild, sdtChildOffset) => {
635
- pushRunsForChild(sdtChild, sdtInnerOffset + sdtChildOffset);
785
+ pushRunsForChild(sdtChild, sdtInnerOffset + sdtChildOffset, effectiveMarks);
636
786
  });
637
787
  }
638
788
  }
@@ -676,6 +826,8 @@ function toPreviousListAttrs(previousFormatting) {
676
826
  if (listIsLegal !== void 0) attrs.listIsLegal = listIsLegal;
677
827
  const listMarker = previousFormatting.listMarker;
678
828
  if (listMarker !== void 0) attrs.listMarker = listMarker;
829
+ const listMarkerTemplate = previousFormatting.listMarkerTemplate;
830
+ if (listMarkerTemplate !== void 0) attrs.listMarkerTemplate = listMarkerTemplate;
679
831
  const listNumFmt = previousFormatting.listNumFmt;
680
832
  if (listNumFmt !== void 0) attrs.listNumFmt = listNumFmt;
681
833
  const listLevelNumFmts = previousFormatting.listLevelNumFmts;
@@ -694,6 +846,12 @@ function toPreviousListAttrs(previousFormatting) {
694
846
  if (listMarkerAlignment !== void 0) attrs.listMarkerAlignment = listMarkerAlignment;
695
847
  const listMarkerSuffix = previousFormatting.listMarkerSuffix;
696
848
  if (listMarkerSuffix !== void 0) attrs.listMarkerSuffix = listMarkerSuffix;
849
+ const listMarkerAllCaps = previousFormatting.listMarkerAllCaps;
850
+ if (listMarkerAllCaps !== void 0) attrs.listMarkerAllCaps = listMarkerAllCaps;
851
+ const listImplicitChildLevelAdvances = previousFormatting.listImplicitChildLevelAdvances;
852
+ if (listImplicitChildLevelAdvances !== void 0) attrs.listImplicitChildLevelAdvances = listImplicitChildLevelAdvances;
853
+ const listMarkerSecondSlotOffsetTwips = previousFormatting.listMarkerSecondSlotOffsetTwips;
854
+ if (listMarkerSecondSlotOffsetTwips !== void 0) attrs.listMarkerSecondSlotOffsetTwips = listMarkerSecondSlotOffsetTwips;
697
855
  return attrs;
698
856
  }
699
857
  function resolveDeletedListMarker(previousListAttrs, listCounterState) {
@@ -717,15 +875,20 @@ function applyDeletedListMarkerAttrs(attrs, change, listCounterState, theme, fon
717
875
  if (previousListAttrs.listMarkerAlignment) attrs.listMarkerAlignment = previousListAttrs.listMarkerAlignment;
718
876
  if (previousListAttrs.listMarkerSuffix) attrs.listMarkerSuffix = previousListAttrs.listMarkerSuffix;
719
877
  }
878
+ const FLOW_ALIGNMENT_BY_PARAGRAPH_ALIGNMENT = {
879
+ left: "left",
880
+ center: "center",
881
+ right: "right",
882
+ both: "justify",
883
+ distribute: "justify",
884
+ mediumKashida: "justify",
885
+ highKashida: "justify",
886
+ lowKashida: "justify",
887
+ thaiDistribute: "justify"
888
+ };
720
889
  function convertParagraphAttrs(pmAttrs, { theme, fontAlternates, listCounterStreams, defaultTabStopTwips }) {
721
890
  const attrs = {};
722
- if (pmAttrs.alignment) {
723
- const align = pmAttrs.alignment;
724
- if (align === "both" || align === "distribute") attrs.alignment = "justify";
725
- else if (align === "left") attrs.alignment = "left";
726
- else if (align === "center") attrs.alignment = "center";
727
- else if (align === "right") attrs.alignment = "right";
728
- }
891
+ if (pmAttrs.alignment) attrs.alignment = FLOW_ALIGNMENT_BY_PARAGRAPH_ALIGNMENT[pmAttrs.alignment];
729
892
  if (typeof pmAttrs.outlineLevel === "number") attrs.outlineLevel = pmAttrs.outlineLevel;
730
893
  const spaceBefore = pmAttrs.spaceBefore;
731
894
  const spaceAfter = pmAttrs.spaceAfter;
@@ -895,9 +1058,12 @@ function hasOnlyVisuallyEmptyTextRuns(runs) {
895
1058
  function hasOnlyHiddenTextRuns(runs) {
896
1059
  return runs.length > 0 && runs.every((run) => run.kind === "text" && run.hidden === true);
897
1060
  }
898
- function convertParagraph(node, startPos, options) {
1061
+ function hasVisibleParagraphPayload(attrs) {
1062
+ return attrs.listMarker !== void 0 && !attrs.listMarkerHidden || attrs.borders?.top !== void 0 || attrs.borders?.bottom !== void 0 || attrs.borders?.left !== void 0 || attrs.borders?.right !== void 0 || attrs.borders?.between !== void 0 || attrs.borders?.bar !== void 0 || attrs.shading !== void 0;
1063
+ }
1064
+ function convertParagraph(node, startPos, options, pageBreaks) {
899
1065
  const pmAttrs = expectParagraphAttrs(node);
900
- const runs = paragraphToRuns(node, startPos, options);
1066
+ const runs = paragraphToRuns(node, startPos, options, pageBreaks);
901
1067
  const attrs = convertParagraphAttrs(pmAttrs, {
902
1068
  theme: options.theme,
903
1069
  fontAlternates: options.fontAlternates,
@@ -924,8 +1090,7 @@ function convertParagraph(node, startPos, options) {
924
1090
  if (isFullyHiddenParagraph && attrs.listMarker !== void 0) attrs.listMarkerHidden = true;
925
1091
  if (isFullyHiddenParagraph) attrs.suppressEmptyParagraphHeight = true;
926
1092
  if (runs.length === 0 && expectDetachedWatermarkHostAttr(node.attrs)) attrs.suppressEmptyParagraphHeight = false;
927
- const hasVisibleParagraphPayload = attrs.listMarker !== void 0 && !attrs.listMarkerHidden || attrs.borders?.top !== void 0 || attrs.borders?.bottom !== void 0 || attrs.borders?.left !== void 0 || attrs.borders?.right !== void 0 || attrs.borders?.between !== void 0 || attrs.borders?.bar !== void 0 || attrs.shading !== void 0;
928
- if (runs.length === 0 && pmAttrs._pageBreakCarrier === true && !hasVisibleParagraphPayload) attrs.suppressEmptyParagraphHeight = true;
1093
+ if (runs.length === 0 && pmAttrs._pageBreakCarrier === true && !hasVisibleParagraphPayload(attrs)) attrs.suppressEmptyParagraphHeight = true;
929
1094
  const bookmarkNames = pmAttrs.bookmarks?.map((b) => b.name);
930
1095
  const block = {
931
1096
  kind: "paragraph",
@@ -958,6 +1123,95 @@ function convertParagraph(node, startPos, options) {
958
1123
  });
959
1124
  return block;
960
1125
  }
1126
+ function paragraphFragmentAttrs(source, index, count) {
1127
+ if (!source) return;
1128
+ const attrs = {
1129
+ ...source,
1130
+ ...source.indent ? { indent: { ...source.indent } } : {},
1131
+ ...source.spacing ? { spacing: { ...source.spacing } } : {},
1132
+ ...source.automaticSpacing ? { automaticSpacing: { ...source.automaticSpacing } } : {},
1133
+ ...source.spacingExplicit ? { spacingExplicit: { ...source.spacingExplicit } } : {}
1134
+ };
1135
+ if (index > 0) {
1136
+ delete attrs.listMarker;
1137
+ delete attrs.listIsBullet;
1138
+ delete attrs.listMarkerFormatting;
1139
+ delete attrs.listMarkerHidden;
1140
+ delete attrs.listMarkerAlignment;
1141
+ delete attrs.listMarkerSuffix;
1142
+ delete attrs.listMarkerRevision;
1143
+ delete attrs.listMarkerSecondSlotOffsetTwips;
1144
+ delete attrs.reserveEmptyOutlineHeight;
1145
+ delete attrs.pageBreakBefore;
1146
+ delete attrs.renderedPageBreakBefore;
1147
+ if (attrs.indent) {
1148
+ delete attrs.indent.firstLine;
1149
+ delete attrs.indent.hanging;
1150
+ }
1151
+ if (attrs.spacing) delete attrs.spacing.before;
1152
+ if (attrs.automaticSpacing) delete attrs.automaticSpacing.before;
1153
+ if (attrs.spacingExplicit) delete attrs.spacingExplicit.before;
1154
+ }
1155
+ if (index < count - 1) {
1156
+ delete attrs.keepNext;
1157
+ delete attrs.runInWithNext;
1158
+ delete attrs.listParagraphMarkFontSize;
1159
+ if (attrs.spacing) delete attrs.spacing.after;
1160
+ if (attrs.automaticSpacing) delete attrs.automaticSpacing.after;
1161
+ if (attrs.spacingExplicit) delete attrs.spacingExplicit.after;
1162
+ }
1163
+ return attrs;
1164
+ }
1165
+ function splitParagraphAtPageBreaks({ pageBreaks, paragraph, splitPageBreakAndParagraphMark }) {
1166
+ if (pageBreaks.length === 0) return [paragraph];
1167
+ const result = [];
1168
+ let fragmentStart = paragraph.pmStart ?? pageBreaks[0].pmStart;
1169
+ let emittedParagraph = false;
1170
+ const appendParagraph = (runs, pmStart, pmEnd) => {
1171
+ const fragment = {
1172
+ ...paragraph,
1173
+ id: emittedParagraph ? nextBlockId() : paragraph.id,
1174
+ runs,
1175
+ pmStart,
1176
+ pmEnd
1177
+ };
1178
+ if (emittedParagraph) delete fragment.bookmarks;
1179
+ result.push(fragment);
1180
+ emittedParagraph = true;
1181
+ };
1182
+ const partitioned = partitionRunsAtPageBreaks(paragraph.runs, pageBreaks);
1183
+ if (partitioned.type === "overlap") panic("An inline layout run overlaps an explicit page-break carrier");
1184
+ for (const { before, pageBreak } of partitioned.partitions) {
1185
+ if (before.length > 0) appendParagraph(before, fragmentStart, pageBreak.pmStart);
1186
+ result.push({
1187
+ kind: "pageBreak",
1188
+ id: nextBlockId(),
1189
+ pmStart: pageBreak.pmStart,
1190
+ pmEnd: pageBreak.pmEnd,
1191
+ ...pageBreak.trackedChange
1192
+ });
1193
+ fragmentStart = pageBreak.pmEnd;
1194
+ }
1195
+ const remainingRuns = partitioned.remaining;
1196
+ if (remainingRuns.length > 0) appendParagraph(remainingRuns, fragmentStart, paragraph.pmEnd ?? fragmentStart);
1197
+ else if (paragraph.runs.length === 0 || splitPageBreakAndParagraphMark && pageBreaks.at(-1)?.pmEnd === (paragraph.pmEnd ?? fragmentStart) - 1) {
1198
+ appendParagraph([], fragmentStart, paragraph.pmEnd ?? fragmentStart);
1199
+ const carrier = result.at(-1);
1200
+ if (carrier?.kind === "paragraph" && !splitPageBreakAndParagraphMark && !hasVisibleParagraphPayload(carrier.attrs ?? {})) carrier.attrs = {
1201
+ ...carrier.attrs,
1202
+ suppressEmptyParagraphHeight: true
1203
+ };
1204
+ }
1205
+ const fragments = result.filter((block) => block.kind === "paragraph");
1206
+ for (let index = 0; index < fragments.length; index += 1) {
1207
+ const fragment = fragments[index];
1208
+ if (!fragment) continue;
1209
+ const attrs = paragraphFragmentAttrs(fragment.attrs, index, fragments.length);
1210
+ if (attrs) fragment.attrs = attrs;
1211
+ else delete fragment.attrs;
1212
+ }
1213
+ return result;
1214
+ }
961
1215
  /**
962
1216
  * Word keeps a final empty body paragraph after a table as an editable anchor,
963
1217
  * but that final anchor does not create a page of its own. Earlier authored
@@ -1074,6 +1328,8 @@ function extractCellBorders(borders, theme) {
1074
1328
  * Convert a table cell node.
1075
1329
  */
1076
1330
  function convertTableCell(node, startPos, options, tableCellMargins) {
1331
+ const pageBreakPosition = options.firstPageBreakRunPosition(node);
1332
+ if (pageBreakPosition !== void 0) panic(`An explicit page-break run at ${String(pageBreakPosition)} cannot be projected inside a table cell`);
1077
1333
  const blocks = [];
1078
1334
  let offset = startPos + 1;
1079
1335
  node.forEach((child) => {
@@ -1246,10 +1502,10 @@ function convertImage(node, startPos, pageContentHeight) {
1246
1502
  if (attrs.borderStyle) imgBlock.borderStyle = attrs.borderStyle;
1247
1503
  return imgBlock;
1248
1504
  }
1249
- /**
1250
- * Convert a textBox PM node to a TextBoxBlock.
1251
- */
1505
+ /** Convert a textBox PM node to a TextBoxBlock. */
1252
1506
  function convertTextBoxNode(node, startPos, opts) {
1507
+ const pageBreakPosition = opts.firstPageBreakRunPosition(node);
1508
+ if (pageBreakPosition !== void 0) panic(`An explicit page-break run at ${String(pageBreakPosition)} cannot be projected inside a text box`);
1253
1509
  const attrs = expectTextBoxAttrs(node);
1254
1510
  const contentBlocks = [];
1255
1511
  node.forEach((child, offset) => {
@@ -1327,6 +1583,32 @@ function applySectionStartsToBoundaries(blocks, finalSectionStart) {
1327
1583
  }
1328
1584
  return result;
1329
1585
  }
1586
+ /**
1587
+ * A trailing page break belongs to its section-ending paragraph. When the
1588
+ * paragraph mark stays on the current page, an immediately following
1589
+ * continuous section resumes there too. Accept both the legacy generated
1590
+ * carrier and the inline atom's one-token paragraph-mark fragment; neither is
1591
+ * a physical layout boundary.
1592
+ */
1593
+ function coalesceTrailingPageBreakBeforeContinuousSection(blocks, splitPageBreakAndParagraphMark) {
1594
+ if (splitPageBreakAndParagraphMark) return [...blocks];
1595
+ const result = [];
1596
+ for (let index = 0; index < blocks.length; index += 1) {
1597
+ const block = blocks[index];
1598
+ const carrier = blocks[index + 1];
1599
+ const section = blocks[index + 2];
1600
+ const isLegacyGeneratedCarrier = block?.kind === "pageBreak" && carrier?.kind === "paragraph" && carrier.runs.length === 0 && block.pmStart !== void 0 && block.pmStart === carrier.pmStart && carrier.pmStart === carrier.pmEnd;
1601
+ const isInlineParagraphMarkCarrier = block?.kind === "pageBreak" && carrier?.kind === "paragraph" && carrier.runs.length === 0 && block.pmEnd !== void 0 && carrier.pmStart === block.pmEnd && carrier.pmEnd === block.pmEnd + 1;
1602
+ const isUnresolvedInsertion = block?.kind === "pageBreak" && block.isInsertion === true;
1603
+ if (block?.kind === "pageBreak" && !isUnresolvedInsertion && carrier?.kind === "sectionBreak" && carrier.type === "continuous") continue;
1604
+ if (block?.kind === "pageBreak" && !isUnresolvedInsertion && (isLegacyGeneratedCarrier || isInlineParagraphMarkCarrier) && section?.kind === "sectionBreak" && section.type === "continuous") {
1605
+ index += 1;
1606
+ continue;
1607
+ }
1608
+ if (block) result.push(block);
1609
+ }
1610
+ return result;
1611
+ }
1330
1612
  function readFinalSectionStart(doc) {
1331
1613
  const sectionStart = doc.attrs["_finalSectionStart"];
1332
1614
  switch (sectionStart) {
@@ -1354,14 +1636,27 @@ function toFlowBlocks(doc, options = {}) {
1354
1636
  counters: listCounters,
1355
1637
  abstractCounters: options.listAbstractCounters ?? /* @__PURE__ */ new Map(),
1356
1638
  seenLevels: options.listSeenNumIds ?? /* @__PURE__ */ new Set(),
1639
+ restartedNumIds: /* @__PURE__ */ new Set(),
1640
+ previousList: {
1641
+ abstractNumId: null,
1642
+ fromStyle: false,
1643
+ numId: null
1644
+ },
1357
1645
  ...lastAdvancedNumId !== void 0 ? { lastAdvancedNumId } : {}
1358
1646
  };
1359
1647
  const originalListCounterState = {
1360
1648
  counters: originalListCounters,
1361
1649
  abstractCounters: options.originalListAbstractCounters ?? /* @__PURE__ */ new Map(),
1362
1650
  seenLevels: options.originalListSeenNumIds ?? /* @__PURE__ */ new Set(),
1651
+ restartedNumIds: /* @__PURE__ */ new Set(),
1652
+ previousList: {
1653
+ abstractNumId: null,
1654
+ fromStyle: false,
1655
+ numId: null
1656
+ },
1363
1657
  ...lastAdvancedOriginalNumId !== void 0 ? { lastAdvancedNumId: lastAdvancedOriginalNumId } : {}
1364
1658
  };
1659
+ const { firstPageBreakRunPosition } = buildPageBreakRunDescendantIndex(doc);
1365
1660
  const opts = {
1366
1661
  ...options,
1367
1662
  defaultFont: options.defaultFont ?? DEFAULT_FONT,
@@ -1376,7 +1671,9 @@ function toFlowBlocks(doc, options = {}) {
1376
1671
  final: listCounterState,
1377
1672
  original: originalListCounterState
1378
1673
  },
1674
+ firstPageBreakRunPosition,
1379
1675
  textBoxAnchorBlockIds: /* @__PURE__ */ new Map(),
1676
+ styleResolver: createStyleEngine(options.styles),
1380
1677
  numberedRefResults: resolveNumberedRefFields(doc, {
1381
1678
  listCounterState: cloneListCounterState(listCounterState),
1382
1679
  originalListCounterState: cloneListCounterState(originalListCounterState)
@@ -1405,6 +1702,20 @@ function toFlowBlocks(doc, options = {}) {
1405
1702
  tagBlockWithSdtStack(block);
1406
1703
  blocks.push(block);
1407
1704
  };
1705
+ const pushParagraphProjection = (node, pos, stripLeadingLineBreak = false) => {
1706
+ if (opts.firstPageBreakRunPosition(node) !== void 0) {
1707
+ const disposition = pageBreakRunParagraphProjectionDisposition(node);
1708
+ if (disposition.status === "unsupported") panic(disposition.message);
1709
+ }
1710
+ const pageBreaks = [];
1711
+ const paragraph = convertParagraph(node, pos, opts, pageBreaks);
1712
+ if (stripLeadingLineBreak && paragraph.runs.at(0)?.kind === "lineBreak") paragraph.runs.shift();
1713
+ for (const block of splitParagraphAtPageBreaks({
1714
+ pageBreaks,
1715
+ paragraph,
1716
+ splitPageBreakAndParagraphMark: options.splitPageBreakAndParagraphMark === true
1717
+ })) trackedPush(block);
1718
+ };
1408
1719
  const trailingPageBreakSectionPositions = /* @__PURE__ */ new Set();
1409
1720
  const consumedPageBreakPositions = /* @__PURE__ */ new Set();
1410
1721
  const collectTrailingPageBreakSections = (parent, contentStart) => {
@@ -1502,10 +1813,8 @@ function toFlowBlocks(doc, options = {}) {
1502
1813
  pmEnd: pos + 1 + firstChild.nodeSize
1503
1814
  };
1504
1815
  trackedPush(columnBreak);
1505
- const paragraph = convertParagraph(node, pos, opts);
1506
- if (paragraph.runs.at(0)?.kind === "lineBreak") paragraph.runs.shift();
1507
- trackedPush(paragraph);
1508
- } else if (node.content.size > 0 || hasListFormatting || !hasSectionBreak) trackedPush(convertParagraph(node, pos, opts));
1816
+ pushParagraphProjection(node, pos, true);
1817
+ } else if (node.content.size > 0 || hasListFormatting || !hasSectionBreak) pushParagraphProjection(node, pos);
1509
1818
  if (hasSectionBreak) {
1510
1819
  if (trailingPageBreakSectionPositions.has(pos)) {
1511
1820
  const sourceParagraph = blocks.at(-1);
@@ -1614,10 +1923,10 @@ function toFlowBlocks(doc, options = {}) {
1614
1923
  suppressFinalParagraphInRepeatedEmptySuffix(blocks);
1615
1924
  const mergedBlocks = mergeRunInParagraphs(blocks);
1616
1925
  const tableCellLinePitch = doc.attrs["_adjustLineHeightInTable"] === true ? "sectionGrid" : void 0;
1617
- return groupParagraphFrames(applySectionStartsToBoundaries(applySectionDocumentGrid(mergedBlocks, {
1926
+ return groupParagraphFrames(coalesceTrailingPageBreakBeforeContinuousSection(applySectionStartsToBoundaries(applySectionDocumentGrid(mergedBlocks, {
1618
1927
  finalLinePitchTwips: opts.finalSectionDocumentGridLinePitchTwips,
1619
1928
  tableCellLinePitch
1620
- }), readFinalSectionStart(doc)), nextBlockId);
1929
+ }), readFinalSectionStart(doc)), options.splitPageBreakAndParagraphMark === true), nextBlockId);
1621
1930
  }
1622
1931
  function applySectionDocumentGrid(blocks, { finalLinePitchTwips, tableCellLinePitch }) {
1623
1932
  const result = [...blocks];