@stll/folio-core 0.36.0 → 0.37.1

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 (200) hide show
  1. package/README.md +59 -1
  2. package/dist/ai-edits/apply.js +689 -367
  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 +133 -71
  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 +99 -19
  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 +60 -57
  20. package/dist/ai-suggestions/conflict.js +1 -4
  21. package/dist/ai-suggestions/text-positions.d.ts +8 -0
  22. package/dist/ai-suggestions/text-positions.js +27 -5
  23. package/dist/compare/__fixtures__/body-sequence.js +3 -4
  24. package/dist/compare/column-alignment.d.ts +13 -13
  25. package/dist/compare/column-alignment.js +78 -39
  26. package/dist/compare/compare.d.ts +4 -3
  27. package/dist/compare/compare.js +41 -5
  28. package/dist/compare/content-alignment.d.ts +95 -0
  29. package/dist/compare/content-alignment.js +1450 -0
  30. package/dist/compare/content-types.d.ts +100 -0
  31. package/dist/compare/content-types.js +0 -0
  32. package/dist/compare/content.d.ts +209 -0
  33. package/dist/compare/content.js +885 -0
  34. package/dist/compare/formatting.d.ts +5 -5
  35. package/dist/compare/formatting.js +6 -4
  36. package/dist/compare/plan.d.ts +6 -1
  37. package/dist/compare/plan.js +201 -569
  38. package/dist/compare/scenario.d.ts +2 -2
  39. package/dist/compare/types.d.ts +3 -3
  40. package/dist/compare/verification.d.ts +2 -2
  41. package/dist/compare/verification.js +25 -8
  42. package/dist/compat/eigenpal.d.ts +5 -3
  43. package/dist/compat/eigenpal.js +3 -2
  44. package/dist/controller/headerFooterEditorManager.js +14 -6
  45. package/dist/controller/hiddenEditorManager.d.ts +7 -2
  46. package/dist/controller/hiddenEditorManager.js +15 -6
  47. package/dist/controller/layoutPipeline.js +5 -3
  48. package/dist/controller/noteEditorManager.js +12 -7
  49. package/dist/display-list/build/headerFooterPrimitives.js +1 -0
  50. package/dist/display-list/build/storyPrimitives.d.ts +5 -2
  51. package/dist/display-list/build/storyPrimitives.js +60 -3
  52. package/dist/display-list/build/tablePrimitives.js +30 -0
  53. package/dist/display-list/primitives.d.ts +1 -1
  54. package/dist/document-operations.d.ts +8 -6
  55. package/dist/document-operations.js +121 -26
  56. package/dist/docx/blockContentParser.js +6 -27
  57. package/dist/docx/ensureParaIds.js +9 -4
  58. package/dist/docx/numberingParser.d.ts +3 -1
  59. package/dist/docx/numberingParser.js +4 -1
  60. package/dist/docx/paragraphParser.js +7 -6
  61. package/dist/docx/paragraphTraversal.js +30 -34
  62. package/dist/docx/rezip.d.ts +0 -8
  63. package/dist/docx/rezip.js +41 -16
  64. package/dist/docx/runParser.js +4 -2
  65. package/dist/docx/serializer/paragraphSerializer.js +2 -0
  66. package/dist/docx/serializer/runSerializer.js +5 -3
  67. package/dist/docx/serializer/trackedChangeAttributes.d.ts +3 -1
  68. package/dist/docx/serializer/trackedChangeAttributes.js +11 -1
  69. package/dist/docx/server/build.d.ts +1 -1
  70. package/dist/headless-layout.js +5 -4
  71. package/dist/index.d.ts +5 -3
  72. package/dist/index.js +3 -2
  73. package/dist/internal/headlessRevisionResolution.d.ts +23 -0
  74. package/dist/internal/headlessRevisionResolution.js +176 -0
  75. package/dist/internal/headlessRevisionResolutionGuard.d.ts +12 -0
  76. package/dist/internal/headlessRevisionResolutionGuard.js +28 -0
  77. package/dist/internal/pageBreakRunDescendantIndex.d.ts +9 -0
  78. package/dist/internal/pageBreakRunDescendantIndex.js +27 -0
  79. package/dist/internal/pageBreakRunPartition.d.ts +26 -0
  80. package/dist/internal/pageBreakRunPartition.js +35 -0
  81. package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +15 -0
  82. package/dist/internal/pageBreakRunSourceDescendantIndex.js +126 -0
  83. package/dist/internal/sectionEndpointResolution.d.ts +32 -0
  84. package/dist/internal/sectionEndpointResolution.js +38 -0
  85. package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
  86. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +16 -4
  87. package/dist/layout-bridge/convert/headerFooterLayout.js +48 -5
  88. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -0
  89. package/dist/layout-bridge/convert/toFlowBlocks.js +379 -75
  90. package/dist/layout-bridge/dom/clickToPositionDom.d.ts +8 -1
  91. package/dist/layout-bridge/dom/clickToPositionDom.js +114 -40
  92. package/dist/layout-bridge/dom/textStreamDom.d.ts +24 -0
  93. package/dist/layout-bridge/dom/textStreamDom.js +75 -0
  94. package/dist/layout-bridge/headerFooterLayout.js +16 -30
  95. package/dist/layout-engine/index.js +12 -3
  96. package/dist/layout-engine/measure/tableFragmentBorderGeometry.d.ts +17 -0
  97. package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +24 -0
  98. package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
  99. package/dist/layout-engine/types.d.ts +7 -0
  100. package/dist/layout-painter/imageLayout.d.ts +1 -1
  101. package/dist/layout-painter/renderTable.js +20 -0
  102. package/dist/model.d.ts +1 -1
  103. package/dist/paged-layout/rangeProjection.js +6 -9
  104. package/dist/paged-layout/transactionDirtyRange.d.ts +3 -1
  105. package/dist/paged-layout/transactionDirtyRange.js +23 -1
  106. package/dist/prosemirror/attrs/index.d.ts +7 -3
  107. package/dist/prosemirror/attrs/index.js +113 -7
  108. package/dist/prosemirror/bookmarkBoundaryIntegrity.d.ts +9 -0
  109. package/dist/prosemirror/bookmarkBoundaryIntegrity.js +22 -0
  110. package/dist/prosemirror/commands/comments.d.ts +10 -1
  111. package/dist/prosemirror/commands/comments.js +167 -59
  112. package/dist/prosemirror/commands/formatPainter.d.ts +45 -10
  113. package/dist/prosemirror/commands/formatPainter.js +319 -63
  114. package/dist/prosemirror/commands/index.d.ts +2 -2
  115. package/dist/prosemirror/commands/pageBreak.d.ts +5 -2
  116. package/dist/prosemirror/commands/pageBreak.js +18 -36
  117. package/dist/prosemirror/commands/propertyChangeScope.d.ts +7 -5
  118. package/dist/prosemirror/commands/propertyChangeScope.js +27 -18
  119. package/dist/prosemirror/conversion/fromProseDoc.d.ts +7 -2
  120. package/dist/prosemirror/conversion/fromProseDoc.js +809 -209
  121. package/dist/prosemirror/conversion/runShadingMark.js +2 -2
  122. package/dist/prosemirror/conversion/toProseDoc.d.ts +26 -1
  123. package/dist/prosemirror/conversion/toProseDoc.js +416 -283
  124. package/dist/prosemirror/extensions/StarterKit.js +4 -0
  125. package/dist/prosemirror/extensions/core/ParagraphExtension.js +12 -8
  126. package/dist/prosemirror/extensions/features/ListExtension.js +95 -123
  127. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +1 -1
  128. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +27 -1
  129. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +134 -30
  130. package/dist/prosemirror/extensions/features/pasteCleanup.js +9 -15
  131. package/dist/prosemirror/extensions/marks/BoldExtension.js +4 -3
  132. package/dist/prosemirror/extensions/marks/CharacterStyleExtension.d.ts +4 -7
  133. package/dist/prosemirror/extensions/marks/CharacterStyleExtension.js +5 -11
  134. package/dist/prosemirror/extensions/marks/FontSizeExtension.js +3 -3
  135. package/dist/prosemirror/extensions/marks/ItalicExtension.js +4 -3
  136. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.d.ts +13 -0
  137. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.js +39 -0
  138. package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.d.ts +7 -1
  139. package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +67 -21
  140. package/dist/prosemirror/extensions/marks/markUtils.d.ts +8 -1
  141. package/dist/prosemirror/extensions/marks/markUtils.js +88 -2
  142. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +44 -3
  143. package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
  144. package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +15 -4
  145. package/dist/prosemirror/extensions/nodes/PageBreakExtension.d.ts +6 -0
  146. package/dist/prosemirror/extensions/nodes/PageBreakExtension.js +6 -0
  147. package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.d.ts +6 -0
  148. package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.js +36 -0
  149. package/dist/prosemirror/findReplaceSelection.js +8 -3
  150. package/dist/prosemirror/index.d.ts +3 -3
  151. package/dist/prosemirror/listMarker.d.ts +26 -1
  152. package/dist/prosemirror/listMarker.js +108 -14
  153. package/dist/prosemirror/pageBreakRunProjection.d.ts +28 -0
  154. package/dist/prosemirror/pageBreakRunProjection.js +47 -0
  155. package/dist/prosemirror/paraText.js +6 -0
  156. package/dist/prosemirror/paragraphSpacing.d.ts +29 -0
  157. package/dist/prosemirror/paragraphSpacing.js +125 -0
  158. package/dist/prosemirror/plugins/documentNumbering.d.ts +8 -0
  159. package/dist/prosemirror/plugins/documentNumbering.js +18 -0
  160. package/dist/prosemirror/plugins/pmTextScan.d.ts +3 -2
  161. package/dist/prosemirror/plugins/pmTextScan.js +14 -4
  162. package/dist/prosemirror/plugins/suggestionMode.js +8 -10
  163. package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +16 -0
  164. package/dist/prosemirror/rebaseParagraphRunFormatting.js +61 -0
  165. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +64 -0
  166. package/dist/prosemirror/runFormattingInlineCarriers.js +121 -0
  167. package/dist/prosemirror/runFormattingProvenance.d.ts +12 -0
  168. package/dist/prosemirror/runFormattingProvenance.js +48 -0
  169. package/dist/prosemirror/runFormattingReconciliation.d.ts +25 -0
  170. package/dist/prosemirror/runFormattingReconciliation.js +54 -0
  171. package/dist/prosemirror/runPropertyChangeResolution.d.ts +18 -0
  172. package/dist/prosemirror/runPropertyChangeResolution.js +18 -0
  173. package/dist/prosemirror/runStyleFormatting.d.ts +50 -0
  174. package/dist/prosemirror/runStyleFormatting.js +105 -0
  175. package/dist/prosemirror/schema/index.d.ts +3 -3
  176. package/dist/prosemirror/schema/marks.d.ts +82 -9
  177. package/dist/prosemirror/schema/marks.js +73 -1
  178. package/dist/prosemirror/schema/nodes.d.ts +18 -5
  179. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +14 -2
  180. package/dist/prosemirror/styles/resolvedStyleAttrs.js +44 -23
  181. package/dist/prosemirror/styles/styleResolver.d.ts +10 -13
  182. package/dist/prosemirror/styles/styleResolver.js +3 -3
  183. package/dist/prosemirror/styles/styleToggleCascade.d.ts +8 -1
  184. package/dist/prosemirror/styles/styleToggleCascade.js +24 -1
  185. package/dist/prosemirror/tableGridMutation.d.ts +20 -0
  186. package/dist/prosemirror/tableGridMutation.js +30 -0
  187. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +31 -0
  188. package/dist/prosemirror/trackedRunInlineAtoms.js +39 -0
  189. package/dist/prosemirror/utils/visualLineNavigation.js +27 -31
  190. package/dist/prosemirror/validation.js +23 -4
  191. package/dist/render-dom/HeaderFooterSelectionOverlay.js +20 -20
  192. package/dist/render-dom/RenderedDomContext.js +17 -34
  193. package/dist/server.d.ts +4 -4
  194. package/dist/server.js +2 -2
  195. package/dist/style-engine/styleEngine.d.ts +1 -1
  196. package/dist/utils/clipboard.js +1 -1
  197. package/dist/utils/findReplace.js +38 -21
  198. package/dist/version-comparison.d.ts +38 -44
  199. package/dist/version-comparison.js +270 -401
  200. package/package.json +3 -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) {
@@ -900,9 +1058,12 @@ function hasOnlyVisuallyEmptyTextRuns(runs) {
900
1058
  function hasOnlyHiddenTextRuns(runs) {
901
1059
  return runs.length > 0 && runs.every((run) => run.kind === "text" && run.hidden === true);
902
1060
  }
903
- 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) {
904
1065
  const pmAttrs = expectParagraphAttrs(node);
905
- const runs = paragraphToRuns(node, startPos, options);
1066
+ const runs = paragraphToRuns(node, startPos, options, pageBreaks);
906
1067
  const attrs = convertParagraphAttrs(pmAttrs, {
907
1068
  theme: options.theme,
908
1069
  fontAlternates: options.fontAlternates,
@@ -929,8 +1090,7 @@ function convertParagraph(node, startPos, options) {
929
1090
  if (isFullyHiddenParagraph && attrs.listMarker !== void 0) attrs.listMarkerHidden = true;
930
1091
  if (isFullyHiddenParagraph) attrs.suppressEmptyParagraphHeight = true;
931
1092
  if (runs.length === 0 && expectDetachedWatermarkHostAttr(node.attrs)) attrs.suppressEmptyParagraphHeight = false;
932
- 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;
933
- if (runs.length === 0 && pmAttrs._pageBreakCarrier === true && !hasVisibleParagraphPayload) attrs.suppressEmptyParagraphHeight = true;
1093
+ if (runs.length === 0 && pmAttrs._pageBreakCarrier === true && !hasVisibleParagraphPayload(attrs)) attrs.suppressEmptyParagraphHeight = true;
934
1094
  const bookmarkNames = pmAttrs.bookmarks?.map((b) => b.name);
935
1095
  const block = {
936
1096
  kind: "paragraph",
@@ -963,6 +1123,95 @@ function convertParagraph(node, startPos, options) {
963
1123
  });
964
1124
  return block;
965
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
+ }
966
1215
  /**
967
1216
  * Word keeps a final empty body paragraph after a table as an editable anchor,
968
1217
  * but that final anchor does not create a page of its own. Earlier authored
@@ -1079,6 +1328,8 @@ function extractCellBorders(borders, theme) {
1079
1328
  * Convert a table cell node.
1080
1329
  */
1081
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`);
1082
1333
  const blocks = [];
1083
1334
  let offset = startPos + 1;
1084
1335
  node.forEach((child) => {
@@ -1251,10 +1502,10 @@ function convertImage(node, startPos, pageContentHeight) {
1251
1502
  if (attrs.borderStyle) imgBlock.borderStyle = attrs.borderStyle;
1252
1503
  return imgBlock;
1253
1504
  }
1254
- /**
1255
- * Convert a textBox PM node to a TextBoxBlock.
1256
- */
1505
+ /** Convert a textBox PM node to a TextBoxBlock. */
1257
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`);
1258
1509
  const attrs = expectTextBoxAttrs(node);
1259
1510
  const contentBlocks = [];
1260
1511
  node.forEach((child, offset) => {
@@ -1332,6 +1583,32 @@ function applySectionStartsToBoundaries(blocks, finalSectionStart) {
1332
1583
  }
1333
1584
  return result;
1334
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
+ }
1335
1612
  function readFinalSectionStart(doc) {
1336
1613
  const sectionStart = doc.attrs["_finalSectionStart"];
1337
1614
  switch (sectionStart) {
@@ -1359,14 +1636,27 @@ function toFlowBlocks(doc, options = {}) {
1359
1636
  counters: listCounters,
1360
1637
  abstractCounters: options.listAbstractCounters ?? /* @__PURE__ */ new Map(),
1361
1638
  seenLevels: options.listSeenNumIds ?? /* @__PURE__ */ new Set(),
1639
+ restartedNumIds: /* @__PURE__ */ new Set(),
1640
+ previousList: {
1641
+ abstractNumId: null,
1642
+ fromStyle: false,
1643
+ numId: null
1644
+ },
1362
1645
  ...lastAdvancedNumId !== void 0 ? { lastAdvancedNumId } : {}
1363
1646
  };
1364
1647
  const originalListCounterState = {
1365
1648
  counters: originalListCounters,
1366
1649
  abstractCounters: options.originalListAbstractCounters ?? /* @__PURE__ */ new Map(),
1367
1650
  seenLevels: options.originalListSeenNumIds ?? /* @__PURE__ */ new Set(),
1651
+ restartedNumIds: /* @__PURE__ */ new Set(),
1652
+ previousList: {
1653
+ abstractNumId: null,
1654
+ fromStyle: false,
1655
+ numId: null
1656
+ },
1368
1657
  ...lastAdvancedOriginalNumId !== void 0 ? { lastAdvancedNumId: lastAdvancedOriginalNumId } : {}
1369
1658
  };
1659
+ const { firstPageBreakRunPosition } = buildPageBreakRunDescendantIndex(doc);
1370
1660
  const opts = {
1371
1661
  ...options,
1372
1662
  defaultFont: options.defaultFont ?? DEFAULT_FONT,
@@ -1381,7 +1671,9 @@ function toFlowBlocks(doc, options = {}) {
1381
1671
  final: listCounterState,
1382
1672
  original: originalListCounterState
1383
1673
  },
1674
+ firstPageBreakRunPosition,
1384
1675
  textBoxAnchorBlockIds: /* @__PURE__ */ new Map(),
1676
+ styleResolver: createStyleEngine(options.styles),
1385
1677
  numberedRefResults: resolveNumberedRefFields(doc, {
1386
1678
  listCounterState: cloneListCounterState(listCounterState),
1387
1679
  originalListCounterState: cloneListCounterState(originalListCounterState)
@@ -1410,6 +1702,20 @@ function toFlowBlocks(doc, options = {}) {
1410
1702
  tagBlockWithSdtStack(block);
1411
1703
  blocks.push(block);
1412
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
+ };
1413
1719
  const trailingPageBreakSectionPositions = /* @__PURE__ */ new Set();
1414
1720
  const consumedPageBreakPositions = /* @__PURE__ */ new Set();
1415
1721
  const collectTrailingPageBreakSections = (parent, contentStart) => {
@@ -1507,10 +1813,8 @@ function toFlowBlocks(doc, options = {}) {
1507
1813
  pmEnd: pos + 1 + firstChild.nodeSize
1508
1814
  };
1509
1815
  trackedPush(columnBreak);
1510
- const paragraph = convertParagraph(node, pos, opts);
1511
- if (paragraph.runs.at(0)?.kind === "lineBreak") paragraph.runs.shift();
1512
- trackedPush(paragraph);
1513
- } 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);
1514
1818
  if (hasSectionBreak) {
1515
1819
  if (trailingPageBreakSectionPositions.has(pos)) {
1516
1820
  const sourceParagraph = blocks.at(-1);
@@ -1619,10 +1923,10 @@ function toFlowBlocks(doc, options = {}) {
1619
1923
  suppressFinalParagraphInRepeatedEmptySuffix(blocks);
1620
1924
  const mergedBlocks = mergeRunInParagraphs(blocks);
1621
1925
  const tableCellLinePitch = doc.attrs["_adjustLineHeightInTable"] === true ? "sectionGrid" : void 0;
1622
- return groupParagraphFrames(applySectionStartsToBoundaries(applySectionDocumentGrid(mergedBlocks, {
1926
+ return groupParagraphFrames(coalesceTrailingPageBreakBeforeContinuousSection(applySectionStartsToBoundaries(applySectionDocumentGrid(mergedBlocks, {
1623
1927
  finalLinePitchTwips: opts.finalSectionDocumentGridLinePitchTwips,
1624
1928
  tableCellLinePitch
1625
- }), readFinalSectionStart(doc)), nextBlockId);
1929
+ }), readFinalSectionStart(doc)), options.splitPageBreakAndParagraphMark === true), nextBlockId);
1626
1930
  }
1627
1931
  function applySectionDocumentGrid(blocks, { finalLinePitchTwips, tableCellLinePitch }) {
1628
1932
  const result = [...blocks];