@stll/folio-core 0.23.1 → 0.25.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 (45) hide show
  1. package/dist/controller/fontReadiness.js +12 -7
  2. package/dist/controller/layoutPipeline.js +3 -4
  3. package/dist/docx/fieldParser.d.ts +1 -1
  4. package/dist/docx/fieldParser.js +2 -9
  5. package/dist/docx/numberingParser.d.ts +2 -1
  6. package/dist/docx/numberingParser.js +24 -80
  7. package/dist/docx/paragraphParser.js +3 -4
  8. package/dist/docx/paragraphTextBoxEnrichment.js +1 -0
  9. package/dist/docx/sectionParser.js +2 -2
  10. package/dist/docx/serializer/runSerializer.js +1 -0
  11. package/dist/docx/textBoxParser.js +4 -0
  12. package/dist/fields/fieldContext.d.ts +2 -1
  13. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +9 -1
  14. package/dist/layout-bridge/convert/headerFooterLayout.js +27 -2
  15. package/dist/layout-bridge/convert/toFlowBlocks.js +12 -16
  16. package/dist/layout-bridge/engine/selectionRects.js +3 -5
  17. package/dist/layout-engine/index.d.ts +2 -2
  18. package/dist/layout-engine/index.js +3 -5
  19. package/dist/layout-engine/measure/cache.js +4 -0
  20. package/dist/layout-engine/measure/listMarkerWidth.d.ts +3 -1
  21. package/dist/layout-engine/measure/listMarkerWidth.js +25 -21
  22. package/dist/layout-engine/measure/measureBlocks.js +27 -11
  23. package/dist/layout-engine/measure/measureParagraph.js +7 -1
  24. package/dist/layout-engine/measure/tableCellFloating.js +2 -3
  25. package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
  26. package/dist/layout-engine/tableRowBreak.js +2 -2
  27. package/dist/layout-engine/types.d.ts +16 -11
  28. package/dist/layout-engine/types.js +15 -1
  29. package/dist/layout-painter/renderParagraph.d.ts +9 -1
  30. package/dist/layout-painter/renderParagraph.js +65 -52
  31. package/dist/layout-painter/renderTable.js +2 -5
  32. package/dist/layout-painter/renderTextBox.js +1 -1
  33. package/dist/layout-painter/renderUtils.d.ts +2 -1
  34. package/dist/prosemirror/attrs/index.js +4 -6
  35. package/dist/prosemirror/conversion/fromProseDoc.js +2 -3
  36. package/dist/prosemirror/conversion/toProseDoc.js +3 -3
  37. package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -3
  38. package/dist/prosemirror/extensions/features/ListExtension.js +1 -3
  39. package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +2 -0
  40. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +7 -0
  41. package/dist/prosemirror/schema/nodes.d.ts +5 -7
  42. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -3
  43. package/dist/utils/paragraphBaseDirection.d.ts +6 -0
  44. package/dist/utils/paragraphBaseDirection.js +12 -0
  45. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { expectFontFamilyMarkAttrs } from "../prosemirror/attrs/index.js";
1
+ import { expectFontFamilyMarkAttrs, expectParagraphAttrs } from "../prosemirror/attrs/index.js";
2
2
  import { parseFontFamilyList, resolveFontFamily } from "../utils/fontResolver.js";
3
3
  //#region src/controller/fontReadiness.ts
4
4
  function getDocumentFontSet() {
@@ -62,13 +62,15 @@ function collectInitialLayoutFontFaces(documentModel, pmDoc) {
62
62
  return Array.from(faces.values());
63
63
  }
64
64
  function addTextFormattingFontFaces(faces, formatting) {
65
- addLayoutFontFamilyFace(faces, formatting?.fontFamily, layoutDescriptorFromFormatting(formatting));
65
+ const standardDescriptor = layoutDescriptorFromFormatting(formatting);
66
+ const complexScriptDescriptor = layoutDescriptorFromEmphasis(formatting?.boldCs ?? formatting?.bold, formatting?.italicCs ?? formatting?.italic);
67
+ addLayoutFontFamilyFace(faces, formatting?.fontFamily, standardDescriptor, complexScriptDescriptor);
66
68
  }
67
69
  function collectProseMirrorFontFaces(faces, node, inheritedTextFormatting) {
68
70
  const paragraphDefaults = readParagraphDefaultTextFormatting(node);
69
71
  const textFormatting = paragraphDefaults ?? inheritedTextFormatting;
70
72
  if (paragraphDefaults) addTextFormattingFontFaces(faces, paragraphDefaults);
71
- if (node.attrs["listMarkerFontFamily"]) addLayoutFontFamilyFace(faces, node.attrs["listMarkerFontFamily"], REGULAR_LAYOUT_FONT_DESCRIPTOR);
73
+ if (node.type.name === "paragraph") addTextFormattingFontFaces(faces, expectParagraphAttrs(node).listMarkerFormatting);
72
74
  if (node.isText) {
73
75
  const descriptor = layoutDescriptorFromFormattingAndMarks(textFormatting, node.marks);
74
76
  addLayoutFontFamilyFace(faces, readFontFamilyMarkAttrs(node.marks) ?? textFormatting?.fontFamily ?? DEFAULT_LAYOUT_FONT_FAMILY, descriptor);
@@ -86,9 +88,12 @@ function readFontFamilyMarkAttrs(marks) {
86
88
  for (const mark of marks) if (mark.type.name === "fontFamily") return expectFontFamilyMarkAttrs(mark);
87
89
  }
88
90
  function layoutDescriptorFromFormatting(formatting) {
91
+ return layoutDescriptorFromEmphasis(formatting?.bold, formatting?.italic);
92
+ }
93
+ function layoutDescriptorFromEmphasis(bold, italic) {
89
94
  return {
90
- style: formatting?.italic ? "italic" : "normal",
91
- weight: formatting?.bold ? 700 : 400
95
+ style: italic ? "italic" : "normal",
96
+ weight: bold ? 700 : 400
92
97
  };
93
98
  }
94
99
  function layoutDescriptorFromFormattingAndMarks(formatting, marks) {
@@ -103,7 +108,7 @@ function layoutDescriptorFromFormattingAndMarks(formatting, marks) {
103
108
  weight: bold ? 700 : 400
104
109
  };
105
110
  }
106
- function addLayoutFontFamilyFace(faces, value, descriptor) {
111
+ function addLayoutFontFamilyFace(faces, value, descriptor, complexScriptDescriptor = descriptor) {
107
112
  if (typeof value === "string") {
108
113
  addLayoutFontFamilyNameFace(faces, value, descriptor);
109
114
  return;
@@ -112,7 +117,7 @@ function addLayoutFontFamilyFace(faces, value, descriptor) {
112
117
  const fontFamily = value;
113
118
  addLayoutFontFamilyFace(faces, fontFamily.ascii, descriptor);
114
119
  addLayoutFontFamilyFace(faces, fontFamily.hAnsi, descriptor);
115
- addLayoutFontFamilyFace(faces, fontFamily.cs, descriptor);
120
+ addLayoutFontFamilyFace(faces, fontFamily.cs, complexScriptDescriptor);
116
121
  addLayoutFontFamilyFace(faces, fontFamily.eastAsia, descriptor);
117
122
  }
118
123
  function addLayoutFontFamilyNameFace(faces, family, descriptor) {
@@ -26,11 +26,12 @@ function bodyMarginsClearHeaderFooter({ authoredMargins, preparedHeader, prepare
26
26
  const headerBottom = preparedHeader ? (authoredMargins.header ?? 0) + (preparedHeader.marginPushBottom ?? preparedHeader.height) : authoredMargins.top;
27
27
  const footerClearance = preparedFooter ? (authoredMargins.footer ?? 0) + (preparedFooter.marginPushBottom ?? preparedFooter.height) : authoredMargins.bottom;
28
28
  const top = Math.max(authoredMargins.top, headerBottom);
29
+ const clearedTop = Math.max(top, preparedHeader?.bodyTopClearance ?? 0);
29
30
  const bottom = Math.max(authoredMargins.bottom, footerClearance);
30
- if (top === authoredMargins.top && bottom === authoredMargins.bottom) return authoredMargins;
31
+ if (clearedTop === authoredMargins.top && bottom === authoredMargins.bottom) return authoredMargins;
31
32
  return {
32
33
  ...authoredMargins,
33
- top,
34
+ top: clearedTop,
34
35
  bottom
35
36
  };
36
37
  }
@@ -255,7 +256,6 @@ function runLayoutPipeline(deps, state, options = {}) {
255
256
  let newLayout;
256
257
  let pageFootnoteMap = /* @__PURE__ */ new Map();
257
258
  let footnoteContentMap = /* @__PURE__ */ new Map();
258
- const bodyBreakType = finalSectionProperties?.sectionStart;
259
259
  const buildLayoutOpts = () => {
260
260
  const nextLayoutOpts = {
261
261
  pageSize,
@@ -279,7 +279,6 @@ function runLayoutPipeline(deps, state, options = {}) {
279
279
  nextLayoutOpts.finalPageNumbering = finalLayoutConfig.pageNumbering;
280
280
  }
281
281
  if (columns !== void 0) nextLayoutOpts.columns = columns;
282
- if (bodyBreakType !== void 0) nextLayoutOpts.bodyBreakType = bodyBreakType;
283
282
  if (sectionHeaderFooterRefs !== void 0) nextLayoutOpts.sectionHeaderFooterRefs = sectionHeaderFooterRefs;
284
283
  if (sectionEvenPageMargins !== void 0) nextLayoutOpts.sectionEvenPageMargins = sectionEvenPageMargins;
285
284
  return nextLayoutOpts;
@@ -188,7 +188,7 @@ declare function isTocField(field: document_d_exports.Field): boolean;
188
188
  * @param instruction - Parsed instruction for format switches
189
189
  * @returns Formatted page number string
190
190
  */
191
- declare function computePageNumber(pageNumber: number, instruction?: ParsedFieldInstruction, sectionFormat?: string): string;
191
+ declare function computePageNumber(pageNumber: number, instruction?: ParsedFieldInstruction, sectionFormat?: document_d_exports.NumberFormat): string;
192
192
  /**
193
193
  * Format a date according to a format string
194
194
  *
@@ -1,3 +1,4 @@
1
+ import { formatOoxmlCounter } from "./ooxmlCounterFormatter.js";
1
2
  import { FieldTypeSchema, narrowEnum } from "./parserEnums.js";
2
3
  import { parseRun } from "./runParser.js";
3
4
  import { findChildren, getAttribute } from "./xmlParser.js";
@@ -354,15 +355,7 @@ function computePageNumber(pageNumber, instruction, sectionFormat) {
354
355
  default: return String(pageNumber);
355
356
  }
356
357
  }
357
- function formatSectionPageNumber(pageNumber, format) {
358
- switch (format) {
359
- case "upperRoman": return toRoman(pageNumber);
360
- case "lowerRoman": return toRoman(pageNumber).toLowerCase();
361
- case "upperLetter": return toLetter(pageNumber);
362
- case "lowerLetter": return toLetter(pageNumber).toLowerCase();
363
- default: return String(pageNumber);
364
- }
365
- }
358
+ const formatSectionPageNumber = (pageNumber, format) => formatOoxmlCounter(pageNumber, format);
366
359
  /**
367
360
  * Convert number to uppercase Roman numerals
368
361
  */
@@ -24,6 +24,7 @@ type NumberingMap = {
24
24
  * @returns NumberingMap with definitions and helper functions
25
25
  */
26
26
  declare function parseNumbering(numberingXml: string | null): NumberingMap;
27
+ declare const markerFormattingFromLevel: (formatting: document_d_exports.TextFormatting | undefined) => document_d_exports.ListMarkerFormatting | undefined;
27
28
  declare function getCachedNumberingMap(definitions: document_d_exports.NumberingDefinitions): NumberingMap;
28
29
  /**
29
30
  * Create a NumberingMap with helper functions
@@ -80,4 +81,4 @@ declare function getBulletCharacter(level: document_d_exports.ListLevel): string
80
81
  */
81
82
  declare function isBulletLevel(level: document_d_exports.ListLevel): boolean;
82
83
  //#endregion
83
- export { NumberingMap, computeListRendering, createNumberingMap, formatOoxmlCounter as formatNumber, getBulletCharacter, getCachedNumberingMap, isBulletLevel, numPrEqual, padDecimal, parseNumbering, renderListMarker };
84
+ export { NumberingMap, computeListRendering, createNumberingMap, formatOoxmlCounter as formatNumber, getBulletCharacter, getCachedNumberingMap, isBulletLevel, markerFormattingFromLevel, numPrEqual, padDecimal, parseNumbering, renderListMarker };
@@ -1,5 +1,6 @@
1
1
  import { formatOoxmlCounter, padDecimal } from "./ooxmlCounterFormatter.js";
2
- import { FontHintSchema, LevelSuffixSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
2
+ import { LevelSuffixSchema, narrowEnum } from "./parserEnums.js";
3
+ import { parseRunProperties } from "./runParser.js";
3
4
  import { findChild, findChildren, getAttribute, parseBooleanElement, parseNumericAttribute, parseXmlDocument } from "./xmlParser.js";
4
5
  //#region src/docx/numberingParser.ts
5
6
  const NUMBER_FORMAT_MAP = {
@@ -315,7 +316,10 @@ function parseListLevel(element) {
315
316
  };
316
317
  }
317
318
  if (pPrEl) level.pPr = parseLevelParagraphProps(pPrEl);
318
- if (rPrEl) level.rPr = parseLevelRunProps(rPrEl);
319
+ if (rPrEl) {
320
+ const runProperties = parseRunProperties(rPrEl, null);
321
+ if (runProperties) level.rPr = runProperties;
322
+ }
319
323
  return level;
320
324
  }
321
325
  /**
@@ -428,79 +432,21 @@ function parseTabLeader(val) {
428
432
  default: return;
429
433
  }
430
434
  }
431
- /**
432
- * Parse run properties for a list level (subset of full rPr)
433
- * Main concern: fonts for bullet characters
434
- */
435
- function parseLevelRunProps(rPr) {
436
- const formatting = {};
437
- let rFontsEl;
438
- let szEl;
439
- let colorEl;
440
- let bEl;
441
- let iEl;
442
- let vanishEl;
443
- for (const child of rPr.elements ?? []) {
444
- if (child.type !== "element") continue;
445
- switch (child.name) {
446
- case "w:rFonts":
447
- rFontsEl ??= child;
448
- break;
449
- case "w:sz":
450
- szEl ??= child;
451
- break;
452
- case "w:color":
453
- colorEl ??= child;
454
- break;
455
- case "w:b":
456
- bEl ??= child;
457
- break;
458
- case "w:i":
459
- iEl ??= child;
460
- break;
461
- case "w:vanish":
462
- vanishEl ??= child;
463
- break;
464
- default: break;
465
- }
466
- }
467
- if (rFontsEl) {
468
- const ascii = getAttribute(rFontsEl, "w", "ascii");
469
- const hAnsi = getAttribute(rFontsEl, "w", "hAnsi");
470
- const eastAsia = getAttribute(rFontsEl, "w", "eastAsia");
471
- const cs = getAttribute(rFontsEl, "w", "cs");
472
- const hint = narrowEnum(getAttribute(rFontsEl, "w", "hint"), FontHintSchema);
473
- formatting.fontFamily = {
474
- ...ascii != null ? { ascii } : {},
475
- ...hAnsi != null ? { hAnsi } : {},
476
- ...eastAsia != null ? { eastAsia } : {},
477
- ...cs != null ? { cs } : {},
478
- ...hint !== void 0 ? { hint } : {}
479
- };
480
- }
481
- if (szEl) {
482
- const size = parseNumericAttribute(szEl, "w", "val");
483
- if (size !== void 0) formatting.fontSize = size;
484
- }
485
- if (colorEl) {
486
- const val = getAttribute(colorEl, "w", "val");
487
- const validatedThemeColor = narrowEnum(getAttribute(colorEl, "w", "themeColor"), ThemeColorSlotSchema);
488
- if (val === "auto") formatting.color = { auto: true };
489
- else if (validatedThemeColor) {
490
- const themeTint = getAttribute(colorEl, "w", "themeTint");
491
- const themeShade = getAttribute(colorEl, "w", "themeShade");
492
- formatting.color = {
493
- themeColor: validatedThemeColor,
494
- ...themeTint != null ? { themeTint } : {},
495
- ...themeShade != null ? { themeShade } : {}
496
- };
497
- } else if (val) formatting.color = { rgb: val };
498
- }
499
- if (bEl) formatting.bold = parseBooleanElement(bEl);
500
- if (iEl) formatting.italic = parseBooleanElement(iEl);
501
- if (vanishEl) formatting.hidden = parseBooleanElement(vanishEl);
502
- return formatting;
503
- }
435
+ const markerFormattingFromLevel = (formatting) => {
436
+ if (!formatting) return;
437
+ const markerFormatting = {
438
+ ...formatting.fontFamily !== void 0 ? { fontFamily: formatting.fontFamily } : {},
439
+ ...formatting.fontSize !== void 0 ? { fontSize: formatting.fontSize } : {},
440
+ ...formatting.fontSizeCs !== void 0 ? { fontSizeCs: formatting.fontSizeCs } : {},
441
+ ...formatting.bold !== void 0 ? { bold: formatting.bold } : {},
442
+ ...formatting.boldCs !== void 0 ? { boldCs: formatting.boldCs } : {},
443
+ ...formatting.italic !== void 0 ? { italic: formatting.italic } : {},
444
+ ...formatting.italicCs !== void 0 ? { italicCs: formatting.italicCs } : {},
445
+ ...formatting.rtl !== void 0 ? { rtl: formatting.rtl } : {},
446
+ ...formatting.cs !== void 0 ? { cs: formatting.cs } : {}
447
+ };
448
+ return Object.keys(markerFormatting).length > 0 ? markerFormatting : void 0;
449
+ };
504
450
  /**
505
451
  * Per-definitions cache for `createNumberingMap`. Style application rebuilds
506
452
  * the lookup map on every picker click otherwise; the definitions object is
@@ -603,10 +549,8 @@ function computeListRendering(numPr, numbering) {
603
549
  };
604
550
  if (level.isLgl) rendering.isLegal = true;
605
551
  if (level.rPr?.hidden) rendering.markerHidden = true;
606
- const markerFont = level.rPr?.fontFamily?.ascii || level.rPr?.fontFamily?.hAnsi;
607
- if (markerFont) rendering.markerFontFamily = markerFont;
608
- if (level.rPr?.fontSize) rendering.markerFontSize = level.rPr.fontSize / 2;
609
- if (level.rPr?.bold !== void 0) rendering.markerBold = level.rPr.bold;
552
+ const markerFormatting = markerFormattingFromLevel(level.rPr);
553
+ if (markerFormatting) rendering.markerFormatting = markerFormatting;
610
554
  if (level.rPr?.allCaps) rendering.markerAllCaps = true;
611
555
  if (level.lvlJc) rendering.markerAlignment = level.lvlJc;
612
556
  if (level.suffix) rendering.markerSuffix = level.suffix;
@@ -666,4 +610,4 @@ function isBulletLevel(level) {
666
610
  return level.numFmt === "bullet" || level.numFmt === "none";
667
611
  }
668
612
  //#endregion
669
- export { computeListRendering, createNumberingMap, formatOoxmlCounter as formatNumber, getBulletCharacter, getCachedNumberingMap, isBulletLevel, numPrEqual, padDecimal, parseNumbering, renderListMarker };
613
+ export { computeListRendering, createNumberingMap, formatOoxmlCounter as formatNumber, getBulletCharacter, getCachedNumberingMap, isBulletLevel, markerFormattingFromLevel, numPrEqual, padDecimal, parseNumbering, renderListMarker };
@@ -2,6 +2,7 @@ import { isValidHexId } from "../utils/hexId.js";
2
2
  import { parseBookmarkEnd as parseBookmarkEnd$1, parseBookmarkStart as parseBookmarkStart$1 } from "./bookmarkParser.js";
3
3
  import { parseFieldType } from "./fieldParser.js";
4
4
  import { parseHyperlink as parseHyperlink$1 } from "./hyperlinkParser.js";
5
+ import { markerFormattingFromLevel } from "./numberingParser.js";
5
6
  import { BorderStyleSchema, FrameWrapSchema, FrameXAlignSchema, FrameYAlignSchema, LineSpacingRuleSchema, ParagraphAlignmentSchema, ShadingPatternSchema, TabLeaderSchema, TabStopAlignmentSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
6
7
  import { consolidateParagraphContent } from "./runConsolidator.js";
7
8
  import { parseRun, parseRunProperties } from "./runParser.js";
@@ -1016,10 +1017,8 @@ function parseParagraph(node, styles, theme, numbering, rels = null, media = nul
1016
1017
  if (level.isLgl) listRendering.isLegal = true;
1017
1018
  listRendering.numFmt = level.isLgl ? "decimal" : level.numFmt;
1018
1019
  if (level.rPr?.hidden) listRendering.markerHidden = true;
1019
- const markerFont = level.rPr?.fontFamily?.ascii || level.rPr?.fontFamily?.hAnsi;
1020
- if (markerFont) listRendering.markerFontFamily = markerFont;
1021
- if (level.rPr?.fontSize) listRendering.markerFontSize = level.rPr.fontSize / 2;
1022
- if (level.rPr?.bold !== void 0) listRendering.markerBold = level.rPr.bold;
1020
+ const markerFormatting = markerFormattingFromLevel(level.rPr);
1021
+ if (markerFormatting) listRendering.markerFormatting = markerFormatting;
1023
1022
  if (level.rPr?.allCaps) listRendering.markerAllCaps = true;
1024
1023
  if (level.lvlJc) listRendering.markerAlignment = level.lvlJc;
1025
1024
  if (level.suffix) listRendering.markerSuffix = level.suffix;
@@ -158,6 +158,7 @@ const enrichTextBoxRuns = ({ content, xmlChildren, styles, theme, numbering, rel
158
158
  textBody: {
159
159
  content: textBox.content,
160
160
  ...textBox.autoFit !== void 0 ? { autoFit: textBox.autoFit } : {},
161
+ ...textBox.textWrap !== void 0 ? { textWrap: textBox.textWrap } : {},
161
162
  ...textBox.margins !== void 0 ? { margins: textBox.margins } : {}
162
163
  }
163
164
  };
@@ -1,6 +1,6 @@
1
1
  import { parseFooterReference, parseHeaderReference } from "./headerFooterRefParser.js";
2
2
  import { parseEndnoteProperties, parseFootnoteProperties } from "./notePropertiesParser.js";
3
- import { BorderStyleSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
3
+ import { BorderStyleSchema, NumberFormatSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
4
4
  import { findChild, findChildren, getAttribute, getChildElements, getLocalName, parseBooleanElement, parseNumericAttribute } from "./xmlParser.js";
5
5
  import { normalizeRevisionId } from "@stll/docx-core/model";
6
6
  //#region src/docx/sectionParser.ts
@@ -272,7 +272,7 @@ function parseSectionProperties(sectPr) {
272
272
  const pgNumType = findChild(sectPr, "w", "pgNumType");
273
273
  if (pgNumType) {
274
274
  const pageNumbering = {};
275
- const format = getAttribute(pgNumType, "w", "fmt");
275
+ const format = narrowEnum(getAttribute(pgNumType, "w", "fmt"), NumberFormatSchema);
276
276
  if (format) pageNumbering.format = format;
277
277
  const start = parseNumericAttribute(pgNumType, "w", "start");
278
278
  if (start !== void 0) pageNumbering.start = start;
@@ -479,6 +479,7 @@ function serializeShapeContent(content) {
479
479
  if (shape.textBody) {
480
480
  const tb = shape.textBody;
481
481
  const bpAttrs = ["rot=\"0\"", "vert=\"horz\""];
482
+ if (tb.textWrap) bpAttrs.push(`wrap="${tb.textWrap}"`);
482
483
  if (tb.anchor) bpAttrs.push(`anchor="${tb.anchor === "middle" ? "ctr" : tb.anchor}"`);
483
484
  if (tb.anchorCenter) bpAttrs.push("anchorCtr=\"1\"");
484
485
  if (tb.margins) {
@@ -11,6 +11,8 @@ const DEFAULT_MARGIN_EMU = 91440;
11
11
  function parseBodyProperties(bodyPr) {
12
12
  if (!bodyPr) return {};
13
13
  const result = {};
14
+ const textWrap = getAttribute(bodyPr, null, "wrap");
15
+ if (textWrap === "none" || textWrap === "square") result.textWrap = textWrap;
14
16
  if (findChildByLocalName(bodyPr, "spAutoFit")) result.autoFit = "shape";
15
17
  else if (findChildByLocalName(bodyPr, "normAutofit")) result.autoFit = "normal";
16
18
  else if (findChildByLocalName(bodyPr, "noAutofit")) result.autoFit = "none";
@@ -128,6 +130,7 @@ function parseTextBox(drawingEl) {
128
130
  if (outline) textBox.outline = outline;
129
131
  if (bodyProps.margins) textBox.margins = bodyProps.margins;
130
132
  if (bodyProps.autoFit) textBox.autoFit = bodyProps.autoFit;
133
+ if (bodyProps.textWrap) textBox.textWrap = bodyProps.textWrap;
131
134
  if (isAnchor) {
132
135
  const position = parseAnchorPosition(container);
133
136
  if (position) textBox.position = position;
@@ -170,6 +173,7 @@ function parseTextBoxFromShape(wsp, size, position, wrap) {
170
173
  if (outline) textBox.outline = outline;
171
174
  if (bodyProps.margins) textBox.margins = bodyProps.margins;
172
175
  if (bodyProps.autoFit) textBox.autoFit = bodyProps.autoFit;
176
+ if (bodyProps.textWrap) textBox.textWrap = bodyProps.textWrap;
173
177
  if (position) textBox.position = position;
174
178
  if (wrap) textBox.wrap = wrap;
175
179
  return textBox;
@@ -1,3 +1,4 @@
1
+ import { document_d_exports } from "../types/document.js";
1
2
  //#region src/fields/fieldContext.d.ts
2
3
  /**
3
4
  * Resolution context for evaluating dynamic DOCX fields against a laid-out
@@ -10,7 +11,7 @@ type FieldContext = {
10
11
  /** 1-indexed page the field is on (PAGE). */
11
12
  pageNumber: number;
12
13
  /** OOXML section-level format used when PAGE has no explicit format switch. */
13
- pageNumberFormat?: string;
14
+ pageNumberFormat?: document_d_exports.NumberFormat;
14
15
  /** Total pages in the document (NUMPAGES). */
15
16
  totalPages: number;
16
17
  /** Pages in the field's current section (SECTIONPAGES); omit until the
@@ -30,6 +30,14 @@ declare function calculateHeaderFooterMarginPushBounds(blocks: FlowBlock[], meas
30
30
  top: number;
31
31
  bottom: number;
32
32
  };
33
+ /**
34
+ * Find the lower page edge of header `wrapTopAndBottom` artwork that overlaps
35
+ * the authored body start. Unlike ordinary anchored artwork, this wrap mode
36
+ * reserves a full-width horizontal band even when the drawing paints behind
37
+ * text. Bands wholly below the body start need page-local flow support and are
38
+ * intentionally not flattened into a top margin here.
39
+ */
40
+ declare function calculateHeaderFooterBodyTopClearance(blocks: FlowBlock[], flowHeight: number, metrics: HeaderFooterMetrics): number | undefined;
33
41
  type ConvertHeaderFooterOptions = {
34
42
  styles?: document_d_exports.StyleDefinitions | null;
35
43
  theme?: document_d_exports.Theme | null;
@@ -74,4 +82,4 @@ declare function convertHeaderFooterToContent(headerFooter: document_d_exports.H
74
82
  */
75
83
  declare function convertHeaderFooterPmDocToContent(pmDoc: Node | null | undefined, contentWidth: number, metrics: HeaderFooterMetrics, options: Omit<ConvertHeaderFooterOptions, "styles">): HeaderFooterContent | undefined;
76
84
  //#endregion
77
- export { ConvertHeaderFooterOptions, HeaderFooterMetrics, calculateHeaderFooterMarginPushBounds, calculateHeaderFooterVisualBounds, convertHeaderFooterPmDocToContent, convertHeaderFooterToContent, normalizeHeaderFooterMeasureBlocks, resolveHeaderFooterPositionedVisualTop, resolveHeaderFooterVisualTop };
85
+ export { ConvertHeaderFooterOptions, HeaderFooterMetrics, calculateHeaderFooterBodyTopClearance, calculateHeaderFooterMarginPushBounds, calculateHeaderFooterVisualBounds, convertHeaderFooterPmDocToContent, convertHeaderFooterToContent, normalizeHeaderFooterMeasureBlocks, resolveHeaderFooterPositionedVisualTop, resolveHeaderFooterVisualTop };
@@ -290,6 +290,29 @@ function calculateHeaderFooterMarginPushBounds(blocks, measures, flowHeight, met
290
290
  };
291
291
  }
292
292
  /**
293
+ * Find the lower page edge of header `wrapTopAndBottom` artwork that overlaps
294
+ * the authored body start. Unlike ordinary anchored artwork, this wrap mode
295
+ * reserves a full-width horizontal band even when the drawing paints behind
296
+ * text. Bands wholly below the body start need page-local flow support and are
297
+ * intentionally not flattened into a top margin here.
298
+ */
299
+ function calculateHeaderFooterBodyTopClearance(blocks, flowHeight, metrics) {
300
+ if (metrics.section !== "header") return;
301
+ const flowTop = metrics.margins.header ?? 48;
302
+ let clearance = 0;
303
+ for (const block of blocks) {
304
+ if (block.kind !== "paragraph") continue;
305
+ for (const run of block.runs) {
306
+ if (run.kind !== "image" || run.wrapType !== "topAndBottom" || run.position?.vertical?.relativeTo !== "page" && run.position?.vertical?.relativeTo !== "margin") continue;
307
+ const pageTop = flowTop + resolveHeaderFooterVisualTop(run, 0, flowHeight, metrics) - (run.distTop ?? 0);
308
+ if (pageTop > metrics.margins.top) continue;
309
+ const pageBottom = Math.min(metrics.pageSize.h, pageTop + (run.distTop ?? 0) + run.height + (run.distBottom ?? 0));
310
+ clearance = Math.max(clearance, pageBottom);
311
+ }
312
+ }
313
+ return clearance > 0 ? clearance : void 0;
314
+ }
315
+ /**
293
316
  * Convert HeaderFooter (document type) to HeaderFooterContent (render type).
294
317
  *
295
318
  * Routes through the same pipeline as the body: HF.content ->
@@ -350,6 +373,7 @@ function finalizeHeaderFooterContent(blocks, contentWidth, metrics, options) {
350
373
  }
351
374
  const { visualTop, visualBottom } = calculateHeaderFooterVisualBounds(blocks, measures, flowHeight, metrics);
352
375
  const { top: marginPushTop, bottom: marginPushBottom } = calculateHeaderFooterMarginPushBounds(blocks, measures, flowHeight, metrics);
376
+ const bodyTopClearance = calculateHeaderFooterBodyTopClearance(blocks, flowHeight, metrics);
353
377
  return {
354
378
  blocks,
355
379
  measures,
@@ -358,6 +382,7 @@ function finalizeHeaderFooterContent(blocks, contentWidth, metrics, options) {
358
382
  visualBottom,
359
383
  marginPushTop,
360
384
  marginPushBottom,
385
+ ...bodyTopClearance !== void 0 ? { bodyTopClearance } : {},
361
386
  textSig: computeHeaderFooterTextSig(blocks),
362
387
  ...options.rId ? { rId: options.rId } : {}
363
388
  };
@@ -442,7 +467,7 @@ function serializeParagraphAttrs(attrs) {
442
467
  "listMarker",
443
468
  "listIsBullet",
444
469
  "listMarkerHidden",
445
- "listMarkerBold",
470
+ "listMarkerFormatting",
446
471
  "listMarkerAlignment",
447
472
  "listMarkerSuffix",
448
473
  "tabs"
@@ -489,4 +514,4 @@ function serializeRunFmt(run) {
489
514
  return JSON.stringify(out);
490
515
  }
491
516
  //#endregion
492
- export { calculateHeaderFooterMarginPushBounds, calculateHeaderFooterVisualBounds, convertHeaderFooterPmDocToContent, convertHeaderFooterToContent, normalizeHeaderFooterMeasureBlocks, resolveHeaderFooterPositionedVisualTop, resolveHeaderFooterVisualTop };
517
+ export { calculateHeaderFooterBodyTopClearance, calculateHeaderFooterMarginPushBounds, calculateHeaderFooterVisualBounds, convertHeaderFooterPmDocToContent, convertHeaderFooterToContent, normalizeHeaderFooterMeasureBlocks, resolveHeaderFooterPositionedVisualTop, resolveHeaderFooterVisualTop };
@@ -362,8 +362,7 @@ function applyRunFormattingOverrides(formatting, attrs) {
362
362
  if (attrs.fontSizeCs !== void 0) formatting.complexScriptFontSize = attrs.fontSizeCs / 2;
363
363
  if (attrs.cs !== void 0) formatting.forceComplexScript = attrs.cs;
364
364
  }
365
- function paragraphRunDefaults(pmAttrs, theme) {
366
- const defaultTextFormatting = pmAttrs.defaultTextFormatting;
365
+ function textFormattingToRunFormatting(defaultTextFormatting, theme) {
367
366
  if (!defaultTextFormatting) return {};
368
367
  const result = {};
369
368
  const fontFamily = defaultTextFormatting.fontFamily ? resolveWesternThemeFont(defaultTextFormatting.fontFamily, theme) : void 0;
@@ -379,6 +378,7 @@ function paragraphRunDefaults(pmAttrs, theme) {
379
378
  if (defaultTextFormatting.boldCs !== void 0) result.complexScriptBold = defaultTextFormatting.boldCs;
380
379
  if (defaultTextFormatting.italic !== void 0) result.italic = defaultTextFormatting.italic;
381
380
  if (defaultTextFormatting.italicCs !== void 0) result.complexScriptItalic = defaultTextFormatting.italicCs;
381
+ if (defaultTextFormatting.rtl !== void 0) result.rtl = defaultTextFormatting.rtl;
382
382
  if (defaultTextFormatting.cs !== void 0) result.forceComplexScript = defaultTextFormatting.cs;
383
383
  if (defaultTextFormatting.underline && defaultTextFormatting.underline.style !== "none") {
384
384
  result.underline = { style: defaultTextFormatting.underline.style };
@@ -408,6 +408,9 @@ function paragraphRunDefaults(pmAttrs, theme) {
408
408
  if (defaultTextFormatting.emphasisMark && defaultTextFormatting.emphasisMark !== "none") result.emphasisMark = defaultTextFormatting.emphasisMark;
409
409
  return result;
410
410
  }
411
+ function paragraphRunDefaults(pmAttrs, theme) {
412
+ return textFormattingToRunFormatting(pmAttrs.defaultTextFormatting, theme);
413
+ }
411
414
  /**
412
415
  * Build an ImageRun from ProseMirror node attrs, applying conditional property assignment
413
416
  * to satisfy exactOptionalPropertyTypes.
@@ -653,12 +656,8 @@ function toPreviousListAttrs(previousFormatting) {
653
656
  if (listStartOverride !== void 0) attrs.listStartOverride = listStartOverride;
654
657
  const listMarkerHidden = previousFormatting.listMarkerHidden;
655
658
  if (listMarkerHidden !== void 0) attrs.listMarkerHidden = listMarkerHidden;
656
- const listMarkerFontFamily = previousFormatting.listMarkerFontFamily;
657
- if (listMarkerFontFamily !== void 0) attrs.listMarkerFontFamily = listMarkerFontFamily;
658
- const listMarkerFontSize = previousFormatting.listMarkerFontSize;
659
- if (listMarkerFontSize !== void 0) attrs.listMarkerFontSize = listMarkerFontSize;
660
- const listMarkerBold = previousFormatting.listMarkerBold;
661
- if (listMarkerBold !== void 0) attrs.listMarkerBold = listMarkerBold;
659
+ const listMarkerFormatting = previousFormatting.listMarkerFormatting;
660
+ if (listMarkerFormatting !== void 0) attrs.listMarkerFormatting = listMarkerFormatting;
662
661
  const listMarkerAlignment = previousFormatting.listMarkerAlignment;
663
662
  if (listMarkerAlignment !== void 0) attrs.listMarkerAlignment = listMarkerAlignment;
664
663
  const listMarkerSuffix = previousFormatting.listMarkerSuffix;
@@ -674,7 +673,7 @@ function resolveDeletedListMarker(previousListAttrs, listCounters, listAbstractC
674
673
  if (previousListAttrs.listIsBullet) return "•";
675
674
  return null;
676
675
  }
677
- function applyDeletedListMarkerAttrs(attrs, change, listCounters, listAbstractCounters, listSeenNumIds) {
676
+ function applyDeletedListMarkerAttrs(attrs, change, listCounters, listAbstractCounters, listSeenNumIds, theme) {
678
677
  const previousListAttrs = toPreviousListAttrs(change.previousFormatting);
679
678
  const marker = resolveDeletedListMarker(previousListAttrs, listCounters, listAbstractCounters, listSeenNumIds);
680
679
  if (!marker) return;
@@ -682,9 +681,7 @@ function applyDeletedListMarkerAttrs(attrs, change, listCounters, listAbstractCo
682
681
  attrs.listMarkerRevision = toListMarkerRevision("del", change.info);
683
682
  if (previousListAttrs.listIsBullet !== void 0) attrs.listIsBullet = previousListAttrs.listIsBullet;
684
683
  if (previousListAttrs.listMarkerHidden !== void 0) attrs.listMarkerHidden = previousListAttrs.listMarkerHidden;
685
- if (previousListAttrs.listMarkerFontFamily) attrs.listMarkerFontFamily = previousListAttrs.listMarkerFontFamily;
686
- if (previousListAttrs.listMarkerFontSize) attrs.listMarkerFontSize = previousListAttrs.listMarkerFontSize;
687
- if (previousListAttrs.listMarkerBold !== void 0) attrs.listMarkerBold = previousListAttrs.listMarkerBold;
684
+ if (previousListAttrs.listMarkerFormatting) attrs.listMarkerFormatting = textFormattingToRunFormatting(previousListAttrs.listMarkerFormatting, theme);
688
685
  if (previousListAttrs.listMarkerAlignment) attrs.listMarkerAlignment = previousListAttrs.listMarkerAlignment;
689
686
  if (previousListAttrs.listMarkerSuffix) attrs.listMarkerSuffix = previousListAttrs.listMarkerSuffix;
690
687
  }
@@ -820,15 +817,13 @@ function convertParagraphAttrs(pmAttrs, theme, listCounters, listAbstractCounter
820
817
  else if (pmAttrs.listMarker) attrs.listMarker = pmAttrs.listIsBullet ? convertBulletToUnicode(pmAttrs.listMarker) : pmAttrs.listMarker;
821
818
  if (pmAttrs.listIsBullet !== void 0) attrs.listIsBullet = pmAttrs.listIsBullet;
822
819
  if (pmAttrs.listMarkerHidden) attrs.listMarkerHidden = true;
823
- if (pmAttrs.listMarkerFontFamily) attrs.listMarkerFontFamily = pmAttrs.listMarkerFontFamily;
824
- if (pmAttrs.listMarkerFontSize) attrs.listMarkerFontSize = pmAttrs.listMarkerFontSize;
825
- if (pmAttrs.listMarkerBold !== null && pmAttrs.listMarkerBold !== void 0) attrs.listMarkerBold = pmAttrs.listMarkerBold;
820
+ if (pmAttrs.listMarkerFormatting) attrs.listMarkerFormatting = textFormattingToRunFormatting(pmAttrs.listMarkerFormatting, theme);
826
821
  if (pmAttrs.listMarkerAlignment) attrs.listMarkerAlignment = pmAttrs.listMarkerAlignment;
827
822
  if (pmAttrs.listMarkerSuffix) attrs.listMarkerSuffix = pmAttrs.listMarkerSuffix;
828
823
  if (pmAttrs.listMarkerSecondSlotOffsetTwips !== void 0) attrs.listMarkerSecondSlotOffsetTwips = pmAttrs.listMarkerSecondSlotOffsetTwips;
829
824
  if (!pmAttrs.numPr) {
830
825
  const numberingRemovedChange = propertyChanges.find(isRemovedNumberingChange);
831
- if (numberingRemovedChange) applyDeletedListMarkerAttrs(attrs, numberingRemovedChange, originalListCounters, originalListAbstractCounters, originalListSeenNumIds);
826
+ if (numberingRemovedChange) applyDeletedListMarkerAttrs(attrs, numberingRemovedChange, originalListCounters, originalListAbstractCounters, originalListSeenNumIds, theme);
832
827
  }
833
828
  if (defaultTabStopTwips !== void 0) attrs.defaultTabStopTwips = defaultTabStopTwips;
834
829
  const dtf = pmAttrs.defaultTextFormatting;
@@ -1226,6 +1221,7 @@ function convertTextBoxNode(node, startPos, opts) {
1226
1221
  };
1227
1222
  if (attrs.height !== void 0) textBox.height = attrs.height;
1228
1223
  if (attrs.autoFit !== void 0) textBox.autoFit = attrs.autoFit;
1224
+ if (attrs.textWrap !== void 0) textBox.textWrap = attrs.textWrap;
1229
1225
  if (attrs.fillColor !== void 0) textBox.fillColor = attrs.fillColor;
1230
1226
  if (attrs.outlineWidth !== void 0) textBox.outlineWidth = attrs.outlineWidth;
1231
1227
  if (attrs.outlineColor !== void 0) textBox.outlineColor = attrs.outlineColor;
@@ -4,7 +4,7 @@ import { buildRunFontStyle } from "../../layout-engine/measure/measureHelpers.js
4
4
  import { measureParagraph } from "../../layout-engine/measure/measureParagraph.js";
5
5
  import { measureRun } from "../../layout-engine/measure/measureProvider.js";
6
6
  import { buildTableCellFloatingZones, getTableCellContentWidth, getTableCellFloatingImages } from "../../layout-engine/measure/tableCellFloating.js";
7
- import { getTableRowLeadingWidth } from "../../layout-engine/types.js";
7
+ import { getTableRowLeadingWidth, resolveTableCellPadding } from "../../layout-engine/types.js";
8
8
  import { inlineImageBoundingBox } from "../../utils/rotationBoundingBox.js";
9
9
  import { getPageTop } from "./hitTest.js";
10
10
  //#region src/layout-bridge/engine/selectionRects.ts
@@ -24,8 +24,6 @@ import { getPageTop } from "./hitTest.js";
24
24
  * across blank lines visible (eigenpal/docx-editor#836).
25
25
  */
26
26
  const EMPTY_PARAGRAPH_SLIVER_WIDTH = 4;
27
- const DEFAULT_TABLE_CELL_PADDING_LEFT = 7;
28
- const DEFAULT_TABLE_CELL_PADDING_TOP = 1;
29
27
  /**
30
28
  * Extract FontStyle from a run for measurement.
31
29
  */
@@ -49,14 +47,14 @@ function findBlockById(blocks, blockId) {
49
47
  return blocks.findIndex((block) => block.id === blockId);
50
48
  }
51
49
  function getCellContentOffsetY(cell, cellMeasure, rowHeight) {
52
- const padTop = cell.padding?.top ?? DEFAULT_TABLE_CELL_PADDING_TOP;
50
+ const { top: padTop } = resolveTableCellPadding(cell);
53
51
  const spareHeight = Math.max(0, rowHeight - cellMeasure.height);
54
52
  if (cell.verticalAlign === "bottom") return padTop + spareHeight;
55
53
  if (cell.verticalAlign === "center") return padTop + spareHeight / 2;
56
54
  return padTop;
57
55
  }
58
56
  function getCellContentOffsetX(cell) {
59
- return cell.padding?.left ?? DEFAULT_TABLE_CELL_PADDING_LEFT;
57
+ return resolveTableCellPadding(cell).left;
60
58
  }
61
59
  function getMeasuredBlockHeight(measure) {
62
60
  if (!measure) return 0;
@@ -1,4 +1,4 @@
1
- import { BlockId, BorderStyle, CellBorderSpec, CellBorders, ColumnBreakBlock, ColumnBreakMeasure, ColumnLayout, DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, DocumentPosition, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, FieldRun, FloatingTablePosition, FlowBlock, FootnoteContent, Fragment, FragmentBase, HeaderFooterContent, HeaderFooterContentHeights, HeaderFooterLayout, HitTestResult, HyperlinkInfo, ImageBlock, ImageFragment, ImageMeasure, ImageRun, ImageRunPosition, Layout, LayoutOptions, LineBreakRun, ListNumPr, MathRun, Measure, MeasuredLine, Page, PageBreakBlock, PageBreakMeasure, PageHeaderFooterRefs, PageMargins, ParagraphAttrs, ParagraphBlock, ParagraphBorders, ParagraphFragment, ParagraphIndent, ParagraphMeasure, ParagraphSpacing, RenderedPageBreakRun, Run, RunFormatting, SdtGroup, SectionBreakBlock, SectionBreakMeasure, SectionPageNumbering, TabAlignment, TabRun, TabStop, TableBlock, TableCell, TableCellMeasure, TableFragment, TableMeasure, TableRow, TableRowMeasure, TextBoxBlock, TextBoxFlowAttrs, TextBoxFragment, TextBoxMeasure, TextRun, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, tableColumnsArePinned } from "./types.js";
1
+ import { BlockId, BorderStyle, CellBorderSpec, CellBorders, ColumnBreakBlock, ColumnBreakMeasure, ColumnLayout, DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, DocumentPosition, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, FieldRun, FloatingTablePosition, FlowBlock, FootnoteContent, Fragment, FragmentBase, HeaderFooterContent, HeaderFooterContentHeights, HeaderFooterLayout, HitTestResult, HyperlinkInfo, ImageBlock, ImageFragment, ImageMeasure, ImageRun, ImageRunPosition, Layout, LayoutOptions, LineBreakRun, ListMarkerFormatting, ListNumPr, MathRun, Measure, MeasuredLine, Page, PageBreakBlock, PageBreakMeasure, PageHeaderFooterRefs, PageMargins, ParagraphAttrs, ParagraphBlock, ParagraphBorders, ParagraphFragment, ParagraphIndent, ParagraphMeasure, ParagraphSpacing, RenderedPageBreakRun, Run, RunFormatting, SdtGroup, SectionBreakBlock, SectionBreakMeasure, SectionPageNumbering, TabAlignment, TabRun, TabStop, TableBlock, TableCell, TableCellMeasure, TableFragment, TableMeasure, TableRow, TableRowMeasure, TextBoxBlock, TextBoxFlowAttrs, TextBoxFragment, TextBoxMeasure, TextRun, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, resolveTableCellPadding, tableColumnsArePinned } from "./types.js";
2
2
  import { PageState, Paginator, PaginatorOptions, createPaginator } from "./paginator.js";
3
3
  import { KeepNextChain, calculateChainHeight, computeKeepNextChains, getMidChainIndices, hasKeepLines, hasPageBreakBefore } from "./keep-together.js";
4
4
  import { resolveSectionHeaderFooterRefs } from "./headerFooterRefs.js";
@@ -44,4 +44,4 @@ declare function layoutDocument(blocks: FlowBlock[], measures: Measure[], option
44
44
  */
45
45
  declare function getHeaderRowsHeight(measure: TableMeasure, headerRowCount: number): number;
46
46
  //#endregion
47
- export { BlockId, BorderStyle, type BreakDecision, CellBorderSpec, CellBorders, ColumnBreakBlock, ColumnBreakMeasure, ColumnLayout, DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, DocumentPosition, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, FieldRun, FloatingTablePosition, FlowBlock, FootnoteContent, Fragment, FragmentBase, HeaderFooterContent, HeaderFooterContentHeights, HeaderFooterLayout, HitTestResult, HyperlinkInfo, ImageBlock, ImageFragment, ImageMeasure, ImageRun, ImageRunPosition, type KeepNextChain, Layout, LayoutOptions, LineBreakRun, ListNumPr, MathRun, Measure, MeasuredLine, Page, PageBreakBlock, PageBreakMeasure, PageHeaderFooterRefs, PageMargins, type PageState, type Paginator, type PaginatorOptions, ParagraphAttrs, ParagraphBlock, ParagraphBorders, ParagraphFragment, ParagraphIndent, ParagraphMeasure, ParagraphSpacing, RenderedPageBreakRun, Run, RunFormatting, SdtGroup, SectionBreakBlock, SectionBreakMeasure, SectionLayoutConfig, SectionPageNumbering, type SectionState, TabAlignment, TabRun, TabStop, TableBlock, TableCell, TableCellMeasure, TableFragment, TableMeasure, TableRow, TableRowMeasure, TextBoxBlock, TextBoxFlowAttrs, TextBoxFragment, TextBoxMeasure, TextRun, applyContextualSpacing, applyPendingToActive, assertExhaustiveFlowBlock, calculateChainHeight, collectSectionConfigs, computeKeepNextChains, createInitialSectionState, createPaginator, findPageIndexContainingPmPos, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getEffectiveColumns, getEffectiveMargins, getEffectivePageSize, getHeaderRowsHeight, getMidChainIndices, getTableRowLeadingWidth, hasKeepLines, hasPageBreakBefore, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, layoutDocument, resolveSectionHeaderFooterRefs, scheduleSectionBreak, tableColumnsArePinned };
47
+ export { BlockId, BorderStyle, type BreakDecision, CellBorderSpec, CellBorders, ColumnBreakBlock, ColumnBreakMeasure, ColumnLayout, DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, DocumentPosition, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, FieldRun, FloatingTablePosition, FlowBlock, FootnoteContent, Fragment, FragmentBase, HeaderFooterContent, HeaderFooterContentHeights, HeaderFooterLayout, HitTestResult, HyperlinkInfo, ImageBlock, ImageFragment, ImageMeasure, ImageRun, ImageRunPosition, type KeepNextChain, Layout, LayoutOptions, LineBreakRun, ListMarkerFormatting, ListNumPr, MathRun, Measure, MeasuredLine, Page, PageBreakBlock, PageBreakMeasure, PageHeaderFooterRefs, PageMargins, type PageState, type Paginator, type PaginatorOptions, ParagraphAttrs, ParagraphBlock, ParagraphBorders, ParagraphFragment, ParagraphIndent, ParagraphMeasure, ParagraphSpacing, RenderedPageBreakRun, Run, RunFormatting, SdtGroup, SectionBreakBlock, SectionBreakMeasure, SectionLayoutConfig, SectionPageNumbering, type SectionState, TabAlignment, TabRun, TabStop, TableBlock, TableCell, TableCellMeasure, TableFragment, TableMeasure, TableRow, TableRowMeasure, TextBoxBlock, TextBoxFlowAttrs, TextBoxFragment, TextBoxMeasure, TextRun, applyContextualSpacing, applyPendingToActive, assertExhaustiveFlowBlock, calculateChainHeight, collectSectionConfigs, computeKeepNextChains, createInitialSectionState, createPaginator, findPageIndexContainingPmPos, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getEffectiveColumns, getEffectiveMargins, getEffectivePageSize, getHeaderRowsHeight, getMidChainIndices, getTableRowLeadingWidth, hasKeepLines, hasPageBreakBefore, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, layoutDocument, resolveSectionHeaderFooterRefs, resolveTableCellPadding, scheduleSectionBreak, tableColumnsArePinned };
@@ -11,7 +11,7 @@ import { INITIAL_RENDERED_BREAK_STATE, reconcileAfterBlock, reconcileBreakBefore
11
11
  import { applyPendingToActive, createInitialSectionState, getEffectiveColumns, getEffectiveMargins, getEffectivePageSize, scheduleSectionBreak } from "./section-breaks.js";
12
12
  import { buildTableRowBreakInfo, getRowContinuationSkip, snapRowBreak } from "./tableRowBreak.js";
13
13
  import { bandFragmentX, bandTopContentY, isPageFrameRelativeAnchor } from "./textBoxFlow.js";
14
- import { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, tableColumnsArePinned } from "./types.js";
14
+ import { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, resolveTableCellPadding, tableColumnsArePinned } from "./types.js";
15
15
  import { panic } from "better-result";
16
16
  //#region src/layout-engine/index.ts
17
17
  /**
@@ -257,9 +257,7 @@ function layoutDocument(blocks, measures, options) {
257
257
  break;
258
258
  case "sectionBreak": {
259
259
  const nextSectionConfig = sectionConfigs[sectionIdx + 1] ?? initialConfig;
260
- let nextType = options.bodyBreakType ?? sectionBreakTypes[sectionIdx] ?? DEFAULT_SECTION_BREAK_TYPE;
261
- if (sectionIdx + 1 < sectionBreakTypes.length) nextType = sectionBreakTypes[sectionIdx + 1] ?? DEFAULT_SECTION_BREAK_TYPE;
262
- handleSectionBreak(block, paginator, nextSectionConfig, nextType, sectionIdx + 1);
260
+ handleSectionBreak(block, paginator, nextSectionConfig, sectionBreakTypes[sectionIdx] ?? DEFAULT_SECTION_BREAK_TYPE, sectionIdx + 1);
263
261
  const nextColumns = nextSectionConfig.columns;
264
262
  const nextBreakIndex = breakIndices[sectionIdx + 1] ?? blocks.length;
265
263
  const nextBreak = blocks[nextBreakIndex];
@@ -937,4 +935,4 @@ function handleSectionBreak(_block, paginator, nextSectionConfig, nextSectionTyp
937
935
  paginator.updateColumns(nextSectionConfig.columns ?? DEFAULT_COLUMNS);
938
936
  }
939
937
  //#endregion
940
- export { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, applyContextualSpacing, applyPendingToActive, assertExhaustiveFlowBlock, calculateChainHeight, collectSectionConfigs, computeKeepNextChains, createInitialSectionState, createPaginator, findPageIndexContainingPmPos, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getEffectiveColumns, getEffectiveMargins, getEffectivePageSize, getHeaderRowsHeight, getMidChainIndices, getTableRowLeadingWidth, hasKeepLines, hasPageBreakBefore, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, layoutDocument, resolveSectionHeaderFooterRefs, scheduleSectionBreak, tableColumnsArePinned };
938
+ export { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, applyContextualSpacing, applyPendingToActive, assertExhaustiveFlowBlock, calculateChainHeight, collectSectionConfigs, computeKeepNextChains, createInitialSectionState, createPaginator, findPageIndexContainingPmPos, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getEffectiveColumns, getEffectiveMargins, getEffectivePageSize, getHeaderRowsHeight, getMidChainIndices, getTableRowLeadingWidth, hasKeepLines, hasPageBreakBefore, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, layoutDocument, resolveSectionHeaderFooterRefs, resolveTableCellPadding, scheduleSectionBreak, tableColumnsArePinned };