@extend-ai/react-docx 0.5.0 → 0.6.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.
package/dist/index.js CHANGED
@@ -4833,6 +4833,7 @@ function parseTable(tableXml2, context) {
4833
4833
  const rowHeightRuleRaw = rowHeightTag ? getAttribute(rowHeightTag, "w:hRule")?.toLowerCase() : void 0;
4834
4834
  const rowHeightRule = rowHeightRuleRaw === "atleast" || rowHeightRuleRaw === "exact" || rowHeightRuleRaw === "auto" ? rowHeightRuleRaw === "atleast" ? "atLeast" : rowHeightRuleRaw : void 0;
4835
4835
  const rowCantSplit = rowPropertiesXml ? parseOnOffAttribute(rowPropertiesXml, "cantSplit") : void 0;
4836
+ const rowIsHeader = rowPropertiesXml ? parseOnOffAttribute(rowPropertiesXml, "tblHeader") : void 0;
4836
4837
  const parsedCells = extractBalancedTagBlocks(rowXml, "w:tc").map(
4837
4838
  (cellXml) => parseTableCell(cellXml, context)
4838
4839
  );
@@ -4889,11 +4890,12 @@ function parseTable(tableXml2, context) {
4889
4890
  rows.push({
4890
4891
  type: "table-row",
4891
4892
  cells,
4892
- style: rowBackgroundColor !== void 0 || rowHeightTwips !== void 0 || rowHeightRule !== void 0 || rowCantSplit !== void 0 ? {
4893
+ style: rowBackgroundColor !== void 0 || rowHeightTwips !== void 0 || rowHeightRule !== void 0 || rowCantSplit !== void 0 || rowIsHeader !== void 0 ? {
4893
4894
  backgroundColor: rowBackgroundColor,
4894
4895
  heightTwips: rowHeightTwips,
4895
4896
  ...rowHeightRule !== void 0 ? { heightRule: rowHeightRule } : void 0,
4896
- ...rowCantSplit !== void 0 ? { cantSplit: rowCantSplit } : void 0
4897
+ ...rowCantSplit !== void 0 ? { cantSplit: rowCantSplit } : void 0,
4898
+ ...rowIsHeader !== void 0 ? { isHeader: rowIsHeader } : void 0
4897
4899
  } : void 0
4898
4900
  });
4899
4901
  }
@@ -6698,7 +6700,7 @@ function subscribeRenderableImageSourceUpdates(listener) {
6698
6700
  import * as React from "react";
6699
6701
  import { flushSync } from "react-dom";
6700
6702
  import { renderToStaticMarkup } from "react-dom/server";
6701
- import { useVirtualizer } from "@tanstack/react-virtual";
6703
+ import { useVirtualizer, useWindowVirtualizer } from "@tanstack/react-virtual";
6702
6704
 
6703
6705
  // ../editor-ops/src/index.ts
6704
6706
  function paragraphFromText(text, options) {
@@ -9008,18 +9010,63 @@ function collectTopLevelExplicitPageBreakStartNodeIndexes(nodes) {
9008
9010
  }
9009
9011
 
9010
9012
  // src/page-count-reconciliation.ts
9013
+ var PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS = 10;
9011
9014
  function shouldAllowStoredPageCountReduction(options) {
9012
- const estimatedPageCount = Math.max(1, Math.round(options.estimatedPageCount));
9015
+ const estimatedPageCount = Math.max(
9016
+ 1,
9017
+ Math.round(options.estimatedPageCount)
9018
+ );
9013
9019
  const targetPageCount = Math.max(1, Math.round(options.targetPageCount));
9014
9020
  if (targetPageCount >= estimatedPageCount) {
9015
9021
  return true;
9016
9022
  }
9023
+ if (options.hasMeasuredBodyFooterOverlap === true) {
9024
+ return false;
9025
+ }
9017
9026
  if (options.hasLastRenderedPageBreakHints !== true) {
9018
9027
  return true;
9019
9028
  }
9020
- const renderedBreakHintPageCount = Number.isFinite(options.renderedBreakHintPageCount) ? Math.max(1, Math.round(options.renderedBreakHintPageCount)) : void 0;
9029
+ const renderedBreakHintPageCount = Number.isFinite(
9030
+ options.renderedBreakHintPageCount
9031
+ ) ? Math.max(1, Math.round(options.renderedBreakHintPageCount)) : void 0;
9021
9032
  return renderedBreakHintPageCount !== void 0 && targetPageCount >= renderedBreakHintPageCount;
9022
9033
  }
9034
+ function shouldLatchMeasuredBodyFooterOverlap(options) {
9035
+ if (options.measuredBodyFooterOverlap !== true) {
9036
+ return false;
9037
+ }
9038
+ const targetPageCount = Number.isFinite(options.targetPageCount) ? Math.max(1, Math.round(options.targetPageCount)) : void 0;
9039
+ if (targetPageCount === void 0) {
9040
+ return false;
9041
+ }
9042
+ const pageCount = Math.max(1, Math.round(options.pageCount));
9043
+ return pageCount <= targetPageCount;
9044
+ }
9045
+ function resolveMeasuredBodyFooterOverlapLatchState(options) {
9046
+ const shouldConsiderMeasuredBodyFooterOverlap = shouldLatchMeasuredBodyFooterOverlap({
9047
+ pageCount: options.pageCount,
9048
+ targetPageCount: options.targetPageCount,
9049
+ measuredBodyFooterOverlap: options.overlappingPageIndexes.length > 0
9050
+ });
9051
+ if (!shouldConsiderMeasuredBodyFooterOverlap) {
9052
+ return {
9053
+ signature: void 0,
9054
+ consecutivePasses: 0,
9055
+ shouldLatch: false
9056
+ };
9057
+ }
9058
+ const signature = options.overlappingPageIndexes.map((pageIndex) => `${pageIndex}`).join("|");
9059
+ const consecutivePasses = signature === options.previousSignature ? Math.max(0, Math.round(options.previousConsecutivePasses ?? 0)) + 1 : 1;
9060
+ const stabilityThreshold = Math.max(
9061
+ 1,
9062
+ Math.round(options.stabilityThreshold ?? 1)
9063
+ );
9064
+ return {
9065
+ signature,
9066
+ consecutivePasses,
9067
+ shouldLatch: consecutivePasses >= stabilityThreshold
9068
+ };
9069
+ }
9023
9070
  function isBetterCandidate(candidate, incumbent, targetPageCount) {
9024
9071
  const candidateDifference = Math.abs(candidate.pageCount - targetPageCount);
9025
9072
  const incumbentDifference = Math.abs(incumbent.pageCount - targetPageCount);
@@ -9033,7 +9080,7 @@ function isBetterCandidate(candidate, incumbent, targetPageCount) {
9033
9080
  }
9034
9081
  return candidate.pageCount === targetPageCount && incumbent.pageCount !== targetPageCount;
9035
9082
  }
9036
- function reconcilePagesToTargetCountByScalingHeight(options) {
9083
+ function reconcilePageCountCandidateToTargetCountByScalingHeight(options) {
9037
9084
  const {
9038
9085
  initialPages,
9039
9086
  targetPageCount,
@@ -9045,7 +9092,11 @@ function reconcilePagesToTargetCountByScalingHeight(options) {
9045
9092
  const initialPageCount = initialPages.length;
9046
9093
  const initialDifference = Math.abs(initialPageCount - safeTargetPageCount);
9047
9094
  if (initialDifference === 0 || initialDifference > maxDifference) {
9048
- return initialPages;
9095
+ return {
9096
+ pageCount: initialPageCount,
9097
+ pages: initialPages,
9098
+ scale: 1
9099
+ };
9049
9100
  }
9050
9101
  const bestCandidate = {
9051
9102
  pageCount: initialPageCount,
@@ -9095,33 +9146,85 @@ function reconcilePagesToTargetCountByScalingHeight(options) {
9095
9146
  0.24,
9096
9147
  0.22,
9097
9148
  0.2
9098
- ] : [1.02, 1.04, 1.06, 1.08, 1.1, 1.12, 1.14, 1.16, 1.18, 1.2, 1.22, 1.24, 1.26, 1.28, 1.3];
9099
- for (const scale of scales) {
9149
+ ] : [
9150
+ 1.02,
9151
+ 1.04,
9152
+ 1.06,
9153
+ 1.08,
9154
+ 1.1,
9155
+ 1.12,
9156
+ 1.14,
9157
+ 1.16,
9158
+ 1.18,
9159
+ 1.2,
9160
+ 1.22,
9161
+ 1.24,
9162
+ 1.26,
9163
+ 1.28,
9164
+ 1.3
9165
+ ];
9166
+ const buildCandidateAtScale = (scale) => {
9100
9167
  const pages = buildPagesAtScale(scale);
9101
- const candidate = {
9168
+ return {
9102
9169
  pageCount: pages.length,
9103
9170
  pages,
9104
9171
  scale
9105
9172
  };
9173
+ };
9174
+ const refineExactTargetCandidate = (lowerScale, upperScale) => {
9175
+ let bestExactCandidate;
9176
+ const interval = upperScale - lowerScale;
9177
+ if (!Number.isFinite(interval) || Math.abs(interval) < 1e-4) {
9178
+ return selectedCandidate;
9179
+ }
9180
+ for (let step = 1; step <= PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS; step += 1) {
9181
+ const scale = lowerScale + interval * step / PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS;
9182
+ const candidate = buildCandidateAtScale(scale);
9183
+ if (isBetterCandidate(candidate, selectedCandidate, safeTargetPageCount)) {
9184
+ selectedCandidate = candidate;
9185
+ }
9186
+ if (candidate.pageCount === safeTargetPageCount && (bestExactCandidate === void 0 || isBetterCandidate(
9187
+ candidate,
9188
+ bestExactCandidate,
9189
+ safeTargetPageCount
9190
+ ))) {
9191
+ bestExactCandidate = candidate;
9192
+ }
9193
+ }
9194
+ return bestExactCandidate ?? selectedCandidate;
9195
+ };
9196
+ let previousScale = 1;
9197
+ let previousPageCount = initialPageCount;
9198
+ for (const scale of scales) {
9199
+ const candidate = buildCandidateAtScale(scale);
9106
9200
  if (isBetterCandidate(candidate, selectedCandidate, safeTargetPageCount)) {
9107
9201
  selectedCandidate = candidate;
9108
9202
  }
9109
9203
  if (candidate.pageCount === safeTargetPageCount) {
9110
- return candidate.pages;
9204
+ const crossedIntoExactTarget = needMorePages ? previousPageCount < safeTargetPageCount : previousPageCount > safeTargetPageCount;
9205
+ if (crossedIntoExactTarget) {
9206
+ return refineExactTargetCandidate(previousScale, scale);
9207
+ }
9208
+ return candidate;
9111
9209
  }
9210
+ previousScale = scale;
9211
+ previousPageCount = candidate.pageCount;
9112
9212
  }
9113
- return selectedCandidate.pages;
9213
+ return selectedCandidate;
9114
9214
  }
9115
9215
 
9116
9216
  // src/pretext-layout.ts
9117
9217
  import {
9118
9218
  layoutNextLine,
9219
+ measureLineStats,
9119
9220
  prepareWithSegments
9120
9221
  } from "@chenglou/pretext";
9121
- var PREPARED_TEXT_CACHE_MAX_ENTRIES = 512;
9122
- var LAYOUT_CACHE_MAX_ENTRIES = 256;
9222
+ var PREPARED_TEXT_CACHE_MAX_ENTRIES = 8192;
9223
+ var LAYOUT_CACHE_MAX_ENTRIES = 4096;
9224
+ var LINE_COUNT_CACHE_MAX_ENTRIES = 16384;
9123
9225
  var preparedTextByKey = /* @__PURE__ */ new Map();
9124
9226
  var layoutByKey = /* @__PURE__ */ new Map();
9227
+ var lineCountByKey = /* @__PURE__ */ new Map();
9125
9228
  var fragmentOffsetAdvancesByFragment = /* @__PURE__ */ new WeakMap();
9126
9229
  var graphemeOffsetsByText = /* @__PURE__ */ new Map();
9127
9230
  var measureCanvas;
@@ -9130,6 +9233,24 @@ var graphemeSegmenter;
9130
9233
  function canUsePretext() {
9131
9234
  return typeof OffscreenCanvas !== "undefined" || typeof document !== "undefined";
9132
9235
  }
9236
+ function getCachedValue(cache, key) {
9237
+ const cached = cache.get(key);
9238
+ if (cached === void 0) {
9239
+ return void 0;
9240
+ }
9241
+ cache.delete(key);
9242
+ cache.set(key, cached);
9243
+ return cached;
9244
+ }
9245
+ function trimCache(cache, maxEntries) {
9246
+ while (cache.size > maxEntries) {
9247
+ const firstKey = cache.keys().next().value;
9248
+ if (firstKey === void 0) {
9249
+ break;
9250
+ }
9251
+ cache.delete(firstKey);
9252
+ }
9253
+ }
9133
9254
  function getMeasureContext() {
9134
9255
  if (!canUsePretext()) {
9135
9256
  return void 0;
@@ -9316,7 +9437,7 @@ function prepareCached(text, font, wordBreak = "normal") {
9316
9437
  return void 0;
9317
9438
  }
9318
9439
  const cacheKey = `${font}\0${wordBreak}\0${text}`;
9319
- const cached = preparedTextByKey.get(cacheKey);
9440
+ const cached = getCachedValue(preparedTextByKey, cacheKey);
9320
9441
  if (cached) {
9321
9442
  return cached;
9322
9443
  }
@@ -9326,18 +9447,36 @@ function prepareCached(text, font, wordBreak = "normal") {
9326
9447
  wordBreak
9327
9448
  });
9328
9449
  preparedTextByKey.set(cacheKey, prepared);
9329
- while (preparedTextByKey.size > PREPARED_TEXT_CACHE_MAX_ENTRIES) {
9330
- const firstKey = preparedTextByKey.keys().next().value;
9331
- if (!firstKey) {
9332
- break;
9333
- }
9334
- preparedTextByKey.delete(firstKey);
9335
- }
9450
+ trimCache(preparedTextByKey, PREPARED_TEXT_CACHE_MAX_ENTRIES);
9336
9451
  return prepared;
9337
9452
  } catch {
9338
9453
  return void 0;
9339
9454
  }
9340
9455
  }
9456
+ function measurePretextPlainTextLineCount(text, font, containerWidthPx, options) {
9457
+ if (!text) {
9458
+ return 0;
9459
+ }
9460
+ const wordBreak = options?.wordBreak ?? "normal";
9461
+ const safeWidth = Math.max(1, Math.round(containerWidthPx));
9462
+ const cacheKey = `line-count\0${font}\0${wordBreak}\0${safeWidth}\0${text}`;
9463
+ const cached = getCachedValue(lineCountByKey, cacheKey);
9464
+ if (cached !== void 0) {
9465
+ return cached;
9466
+ }
9467
+ const prepared = prepareCached(text, font, wordBreak);
9468
+ if (!prepared) {
9469
+ return void 0;
9470
+ }
9471
+ try {
9472
+ const lineCount = measureLineStats(prepared, safeWidth).lineCount;
9473
+ lineCountByKey.set(cacheKey, lineCount);
9474
+ trimCache(lineCountByKey, LINE_COUNT_CACHE_MAX_ENTRIES);
9475
+ return lineCount;
9476
+ } catch {
9477
+ return void 0;
9478
+ }
9479
+ }
9341
9480
  function cloneItemCursor(cursor) {
9342
9481
  return {
9343
9482
  itemIndex: cursor.itemIndex,
@@ -9593,7 +9732,7 @@ function layoutTextWithPretextAroundExclusions(text, font, containerWidthPx, lin
9593
9732
  safeLineHeightPx,
9594
9733
  normalizedExclusions
9595
9734
  );
9596
- const cachedLayout = layoutByKey.get(cacheKey);
9735
+ const cachedLayout = getCachedValue(layoutByKey, cacheKey);
9597
9736
  if (cachedLayout) {
9598
9737
  return cachedLayout;
9599
9738
  }
@@ -9667,13 +9806,7 @@ function layoutTextWithPretextAroundExclusions(text, font, containerWidthPx, lin
9667
9806
  exclusions: normalizedExclusions
9668
9807
  };
9669
9808
  layoutByKey.set(cacheKey, nextLayout);
9670
- while (layoutByKey.size > LAYOUT_CACHE_MAX_ENTRIES) {
9671
- const firstKey = layoutByKey.keys().next().value;
9672
- if (!firstKey) {
9673
- break;
9674
- }
9675
- layoutByKey.delete(firstKey);
9676
- }
9809
+ trimCache(layoutByKey, LAYOUT_CACHE_MAX_ENTRIES);
9677
9810
  return nextLayout;
9678
9811
  }
9679
9812
  function layoutItemsWithPretextAroundExclusions(text, items, containerWidthPx, lineHeightPx, exclusions, fallbackFont) {
@@ -9725,7 +9858,7 @@ function layoutItemsWithPretextAroundExclusions(text, items, containerWidthPx, l
9725
9858
  safeLineHeightPx,
9726
9859
  normalizedExclusions
9727
9860
  );
9728
- const cachedLayout = layoutByKey.get(cacheKey);
9861
+ const cachedLayout = getCachedValue(layoutByKey, cacheKey);
9729
9862
  if (cachedLayout) {
9730
9863
  return cachedLayout;
9731
9864
  }
@@ -9839,13 +9972,7 @@ function layoutItemsWithPretextAroundExclusions(text, items, containerWidthPx, l
9839
9972
  exclusions: normalizedExclusions
9840
9973
  };
9841
9974
  layoutByKey.set(cacheKey, nextLayout);
9842
- while (layoutByKey.size > LAYOUT_CACHE_MAX_ENTRIES) {
9843
- const firstKey = layoutByKey.keys().next().value;
9844
- if (!firstKey) {
9845
- break;
9846
- }
9847
- layoutByKey.delete(firstKey);
9848
- }
9975
+ trimCache(layoutByKey, LAYOUT_CACHE_MAX_ENTRIES);
9849
9976
  return nextLayout;
9850
9977
  }
9851
9978
  function resolveOffsetAtPoint(layout, x, y) {
@@ -10079,7 +10206,7 @@ var SCRIPT_FONT_SCALE = 0.65;
10079
10206
  var DEFAULT_PARAGRAPH_LINE_MULTIPLE = 1;
10080
10207
  var WORD_SINGLE_LINE_AUTO_SCALE = 0.88;
10081
10208
  var WORD_SINGLE_LINE_AUTO_SCALE_SANS = 0.9;
10082
- var WORD_SINGLE_LINE_AUTO_SCALE_SERIF = 1.12;
10209
+ var WORD_SINGLE_LINE_AUTO_SCALE_SERIF = 1.08;
10083
10210
  var WORD_AUTO_LINE_SCALE_BLEND_END_MULTIPLE = 1.08;
10084
10211
  var MIN_AUTO_LINE_MULTIPLE = 0.1;
10085
10212
  var MIN_PARAGRAPH_LINE_HEIGHT_PX = 14;
@@ -10089,10 +10216,12 @@ var MEASURED_PAGE_FOOTER_CLEARANCE_BUFFER_PX = 24;
10089
10216
  var UNOVERLAPPED_FOOTER_MIN_CLEARANCE_PX = 16;
10090
10217
  var FLOATING_FOOTER_BASELINE_CLEARANCE_RESERVE_PX = 16;
10091
10218
  var PAGINATION_MEASUREMENT_INTERACTION_DEBOUNCE_MS = 180;
10219
+ var MEASURED_BODY_FOOTER_OVERLAP_STABILITY_THRESHOLD = 3;
10092
10220
  var WORD_TABLE_CELL_PARAGRAPH_AUTO_LINE_TWIPS = 240;
10093
10221
  var WORD_TABLE_CELL_PARAGRAPH_BEFORE_TWIPS = 0;
10094
10222
  var WORD_TABLE_CELL_PARAGRAPH_AFTER_TWIPS = 0;
10095
10223
  var TABLE_ROW_SLICE_VISUAL_BLEED_PX = 1;
10224
+ var TABLE_CELL_SLICE_FULLY_VISIBLE_BOTTOM_BUFFER_PX = 4;
10096
10225
  var DEFAULT_SPLIT_PARAGRAPH_LINE_TWIPS = 259;
10097
10226
  var DEFAULT_SPLIT_PARAGRAPH_AFTER_TWIPS = 160;
10098
10227
  var PAGE_CONTENT_MEASUREMENT_IGNORE_ATTRIBUTE = "data-docx-pagination-ignore";
@@ -10125,15 +10254,21 @@ var LEADING_COVER_SPACER_EXTRA_HEIGHT_PX = 2;
10125
10254
  var PARAGRAPH_SEGMENT_TOP_BLEED_PX = 22;
10126
10255
  var PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX = 6;
10127
10256
  var PARAGRAPH_SEGMENT_VISUAL_SAFETY_PX = 24;
10257
+ var LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_RATIO = 0.18;
10258
+ var LAST_RENDERED_PAGE_BREAK_HINT_MIN_REMAINING_SPACE_PX = MIN_PARAGRAPH_LINE_HEIGHT_PX * 3;
10259
+ var LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_PX = 120;
10128
10260
  var PARAGRAPH_SEGMENT_FALLBACK_TOP_BLEED_MAX_PX = 4;
10129
10261
  var PARAGRAPH_SEGMENT_FALLBACK_BOTTOM_BLEED_MAX_PX = 0;
10130
10262
  var PARAGRAPH_SEGMENT_FALLBACK_VISUAL_SAFETY_PX = 4;
10131
10263
  var INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT = 8;
10132
10264
  var INITIAL_PAGINATION_PAGE_COUNT_OSCILLATION_DISTINCT_THRESHOLD = 2;
10133
10265
  var INITIAL_PAGINATION_PAGE_COUNT_OSCILLATION_CHANGE_THRESHOLD = 4;
10266
+ var INITIAL_PAGINATION_BACKGROUND_REFINEMENT_DELAY_MS = 96;
10134
10267
  var DEFAULT_PAGE_VIRTUALIZATION_OVERSCAN = 2;
10268
+ var LARGE_TABLE_PAGE_VIRTUALIZATION_OVERSCAN = 0;
10269
+ var LARGE_TABLE_PAGE_ADJACENT_RENDER_COUNT = 1;
10135
10270
  var DEFAULT_PAGE_VIRTUALIZATION_SETTLE_DELAY_MS = 350;
10136
- var ENABLE_TABLE_ROW_SLICING = false;
10271
+ var ENABLE_TABLE_ROW_SLICING = true;
10137
10272
  var TOP_AND_BOTTOM_VERTICAL_DRAG_SNAP_PX = 10;
10138
10273
  var HEADER_FOOTER_INACTIVE_OPACITY = 0.5;
10139
10274
  var LETTERHEAD_INDENT_MIN_TWIPS = 900;
@@ -10438,7 +10573,11 @@ function nearestScrollableAncestor(element) {
10438
10573
  }
10439
10574
  current = current.parentElement;
10440
10575
  }
10441
- return null;
10576
+ const scrollingElement = typeof document !== "undefined" ? document.scrollingElement : null;
10577
+ if (scrollingElement instanceof HTMLElement) {
10578
+ return scrollingElement;
10579
+ }
10580
+ return typeof document !== "undefined" ? document.documentElement : null;
10442
10581
  }
10443
10582
  function resolveEffectiveZoomScale(element) {
10444
10583
  let current = element;
@@ -10540,7 +10679,7 @@ function normalizeMeasuredTableRowHeightPx(heightPx) {
10540
10679
  }
10541
10680
  return Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, Math.round(heightPx));
10542
10681
  }
10543
- function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowHeights, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx) {
10682
+ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowHeights, maxAvailableWidthPx, pageContentHeightPx, numberingDefinitions, docGridLinePitchPx) {
10544
10683
  if (measuredRowHeights.length !== table.rows.length) {
10545
10684
  return void 0;
10546
10685
  }
@@ -10548,7 +10687,8 @@ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowH
10548
10687
  table,
10549
10688
  maxAvailableWidthPx,
10550
10689
  numberingDefinitions,
10551
- docGridLinePitchPx
10690
+ docGridLinePitchPx,
10691
+ pageContentHeightPx
10552
10692
  );
10553
10693
  if (estimatedRowHeights.length !== table.rows.length) {
10554
10694
  return void 0;
@@ -10556,6 +10696,7 @@ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowH
10556
10696
  return measuredRowHeights.map((heightPx, rowIndex) => {
10557
10697
  const row = table.rows[rowIndex];
10558
10698
  const normalizedMeasuredHeightPx = normalizeMeasuredTableRowHeightPx(heightPx);
10699
+ const normalizedPageContentHeightPx = Number.isFinite(pageContentHeightPx) && pageContentHeightPx > 0 ? Math.max(120, Math.round(pageContentHeightPx)) : void 0;
10559
10700
  const estimatedHeightPx = Math.max(
10560
10701
  MIN_PARAGRAPH_LINE_HEIGHT_PX,
10561
10702
  Math.round(estimatedRowHeights[rowIndex] ?? MIN_PARAGRAPH_LINE_HEIGHT_PX)
@@ -10573,6 +10714,9 @@ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowH
10573
10714
  if (rowAllowsPageSplit(row) && row.style?.heightRule !== "exact") {
10574
10715
  return Math.max(explicitMinimumHeightPx, normalizedMeasuredHeightPx);
10575
10716
  }
10717
+ if (Number.isFinite(normalizedPageContentHeightPx) && normalizedMeasuredHeightPx > normalizedPageContentHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
10718
+ return Math.max(explicitMinimumHeightPx, normalizedMeasuredHeightPx);
10719
+ }
10576
10720
  const minimumHeightPx = Math.max(
10577
10721
  estimatedHeightPx,
10578
10722
  explicitMinimumHeightPx
@@ -10618,6 +10762,7 @@ function resolveTableMeasuredRowHeightsForPagination(nodes, tableMeasuredRowHeig
10618
10762
  tableNode,
10619
10763
  measuredRowHeights,
10620
10764
  options?.pageContentWidthPxByNodeIndex?.get(tableIndex),
10765
+ options?.pageContentHeightPxByNodeIndex?.get(tableIndex),
10621
10766
  options?.numberingDefinitions,
10622
10767
  options?.docGridLinePitchPxByNodeIndex?.get(tableIndex)
10623
10768
  ) ?? measuredRowHeights.map(
@@ -11382,9 +11527,9 @@ function resolveFooterPaginationReservePx(footerSections, layout) {
11382
11527
  )
11383
11528
  );
11384
11529
  const footerBodyOverlapPx = estimatedFooterHeightPx + layout.footerDistancePx - layout.marginsPx.bottom;
11385
- const explicitFooterOverlapReservePx = Math.max(
11530
+ const explicitFooterBoundaryReservePx = Math.max(
11386
11531
  0,
11387
- Math.round(footerBodyOverlapPx)
11532
+ Math.round(footerBodyOverlapPx + UNOVERLAPPED_FOOTER_MIN_CLEARANCE_PX)
11388
11533
  );
11389
11534
  const floatingFooterBoundaryReservePx = Number.isFinite(
11390
11535
  floatingFooterBoundaryTopPx
@@ -11396,13 +11541,13 @@ function resolveFooterPaginationReservePx(footerSections, layout) {
11396
11541
  ) : 0;
11397
11542
  if (hasFloatingFooterBodyIntrusionRisk) {
11398
11543
  return Math.max(
11399
- explicitFooterOverlapReservePx,
11544
+ explicitFooterBoundaryReservePx,
11400
11545
  floatingFooterBoundaryReservePx,
11401
11546
  FLOATING_FOOTER_BASELINE_CLEARANCE_RESERVE_PX
11402
11547
  );
11403
11548
  }
11404
11549
  return Math.max(
11405
- explicitFooterOverlapReservePx,
11550
+ explicitFooterBoundaryReservePx,
11406
11551
  floatingFooterBoundaryReservePx
11407
11552
  );
11408
11553
  }
@@ -11622,7 +11767,7 @@ function resolvePageContentHeightPxForPageSegments(pageSegments, pageIndex, defa
11622
11767
  );
11623
11768
  }
11624
11769
  function resolveRenderPageContentHeightPxForPageSegments(params) {
11625
- return resolvePageContentHeightPxForPageSegments(
11770
+ const resolvedHeightPx = resolvePageContentHeightPxForPageSegments(
11626
11771
  params.pageSegments,
11627
11772
  params.pageIndex,
11628
11773
  params.defaultPageContentHeightPx,
@@ -11631,6 +11776,13 @@ function resolveRenderPageContentHeightPxForPageSegments(params) {
11631
11776
  params.useMeasuredPageContentHeights === false ? void 0 : params.measuredPageContentIdentityKeysByPageIndex,
11632
11777
  params.pageIdentityKey
11633
11778
  );
11779
+ if (params.useMeasuredPageContentHeights === false && Number.isFinite(params.pageContentHeightScale) && Math.abs(params.pageContentHeightScale - 1) >= 1e-3) {
11780
+ return Math.max(
11781
+ 120,
11782
+ Math.round(resolvedHeightPx * params.pageContentHeightScale)
11783
+ );
11784
+ }
11785
+ return resolvedHeightPx;
11634
11786
  }
11635
11787
  function documentPageContainsOnlySplitParagraphSegments(pageSegments) {
11636
11788
  return pageSegments.length > 0 && pageSegments.every(
@@ -12167,28 +12319,74 @@ function nodeTreeContainsExplicitFontFamily(nodes) {
12167
12319
  return false;
12168
12320
  });
12169
12321
  }
12322
+ function firstExplicitFontFamilyInNodeTree(nodes) {
12323
+ for (const node of nodes) {
12324
+ if (node.type === "paragraph") {
12325
+ for (const child of node.children) {
12326
+ if (child.type !== "text" && child.type !== "form-field") {
12327
+ continue;
12328
+ }
12329
+ const fontFamily = child.style?.fontFamily?.trim();
12330
+ if (fontFamily) {
12331
+ return fontFamily;
12332
+ }
12333
+ }
12334
+ continue;
12335
+ }
12336
+ if (node.type === "table") {
12337
+ for (const row of node.rows) {
12338
+ for (const cell of row.cells) {
12339
+ const nestedFontFamily = firstExplicitFontFamilyInNodeTree(cell.nodes);
12340
+ if (nestedFontFamily) {
12341
+ return nestedFontFamily;
12342
+ }
12343
+ }
12344
+ }
12345
+ }
12346
+ }
12347
+ return void 0;
12348
+ }
12170
12349
  function resolveDocumentInheritedFontFamily(model) {
12171
12350
  const paragraphStyles = model.metadata.paragraphStyles ?? [];
12172
- const styleDefinesFontFamily = paragraphStyles.some(
12351
+ const normalizedDefaultStyleId = model.metadata.defaultParagraphStyleId?.trim().toLowerCase() ?? "";
12352
+ const defaultParagraphStyle = paragraphStyles.find(
12353
+ (style) => style.id.trim().toLowerCase() === normalizedDefaultStyleId
12354
+ ) ?? paragraphStyles.find((style) => style.isDefault) ?? paragraphStyles.find((style) => style.id.trim().toLowerCase() === "normal");
12355
+ const defaultStyleFontFamily = defaultParagraphStyle?.runStyle?.fontFamily?.trim();
12356
+ if (defaultStyleFontFamily) {
12357
+ return cssFontFamily(defaultStyleFontFamily);
12358
+ }
12359
+ const paragraphStyleFontFamily = paragraphStyles.find(
12173
12360
  (style) => Boolean(style.runStyle?.fontFamily?.trim())
12174
- );
12175
- if (styleDefinesFontFamily) {
12176
- return void 0;
12361
+ )?.runStyle?.fontFamily;
12362
+ if (paragraphStyleFontFamily) {
12363
+ return cssFontFamily(paragraphStyleFontFamily);
12177
12364
  }
12178
- if (nodeTreeContainsExplicitFontFamily(model.nodes)) {
12179
- return void 0;
12365
+ const explicitBodyFontFamily = firstExplicitFontFamilyInNodeTree(model.nodes);
12366
+ if (explicitBodyFontFamily) {
12367
+ return cssFontFamily(explicitBodyFontFamily);
12180
12368
  }
12181
- if ((model.metadata.headerSections ?? []).some(
12182
- (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12183
- )) {
12184
- return void 0;
12369
+ for (const section of model.metadata.headerSections ?? []) {
12370
+ const explicitHeaderFontFamily = firstExplicitFontFamilyInNodeTree(
12371
+ section.nodes
12372
+ );
12373
+ if (explicitHeaderFontFamily) {
12374
+ return cssFontFamily(explicitHeaderFontFamily);
12375
+ }
12185
12376
  }
12186
- if ((model.metadata.footerSections ?? []).some(
12187
- (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12188
- )) {
12189
- return void 0;
12377
+ for (const section of model.metadata.footerSections ?? []) {
12378
+ const explicitFooterFontFamily = firstExplicitFontFamilyInNodeTree(
12379
+ section.nodes
12380
+ );
12381
+ if (explicitFooterFontFamily) {
12382
+ return cssFontFamily(explicitFooterFontFamily);
12383
+ }
12190
12384
  }
12191
- return cssFontFamily(DEFAULT_UNSPECIFIED_DOCX_FONT_FAMILY);
12385
+ return nodeTreeContainsExplicitFontFamily(model.nodes) || (model.metadata.headerSections ?? []).some(
12386
+ (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12387
+ ) || (model.metadata.footerSections ?? []).some(
12388
+ (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12389
+ ) ? void 0 : cssFontFamily(DEFAULT_UNSPECIFIED_DOCX_FONT_FAMILY);
12192
12390
  }
12193
12391
  function replaceTabLayoutMarkersWithTabText(root) {
12194
12392
  const centerLayouts = Array.from(
@@ -12556,6 +12754,11 @@ function sectionNodesNeedFullPageFooterOverlay(nodes) {
12556
12754
  function paragraphHasFormField2(paragraph) {
12557
12755
  return paragraph.children.some((child) => child.type === "form-field");
12558
12756
  }
12757
+ function paragraphHasCheckboxFormField(paragraph) {
12758
+ return paragraph.children.some(
12759
+ (child) => child.type === "form-field" && child.fieldType === "checkbox"
12760
+ );
12761
+ }
12559
12762
  function paragraphHasVisibleText2(paragraph) {
12560
12763
  return paragraph.children.some(
12561
12764
  (child) => child.type === "text" && child.text.trim().length > 0 || child.type === "form-field" && formFieldDisplayValue2(child).trim().length > 0
@@ -12874,6 +13077,9 @@ function paragraphLooksLikeCheckboxChoiceRow(paragraph) {
12874
13077
  }
12875
13078
  var KEEP_ALL_SCRIPT_RE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u;
12876
13079
  var MIN_DUAL_WRAPPED_INTERIOR_BAND_PX = 72;
13080
+ var paragraphPretextLayoutSourceCache = /* @__PURE__ */ new WeakMap();
13081
+ var paragraphPretextLayoutItemsBySource = /* @__PURE__ */ new WeakMap();
13082
+ var paragraphPretextUniformFontBySource = /* @__PURE__ */ new WeakMap();
12877
13083
  function imageWrapModeFromFloating(floating) {
12878
13084
  if (!floating) {
12879
13085
  return "inline";
@@ -13019,16 +13225,67 @@ function resolveFloatingForImageWrapMode(mode, currentFloating, seedFloating) {
13019
13225
  };
13020
13226
  }
13021
13227
  }
13228
+ function buildParagraphPretextTabSpacerText(widthPx, style, paragraphBaseFontPx) {
13229
+ const safeWidthPx = Math.max(8, Math.round(widthPx));
13230
+ const spacerCharacter = "\xA0";
13231
+ const spacerAdvancePx = Math.max(
13232
+ 1,
13233
+ measureTextWidthPx2(spacerCharacter, style, paragraphBaseFontPx)
13234
+ );
13235
+ let spacerCount = Math.max(1, Math.round(safeWidthPx / spacerAdvancePx));
13236
+ let spacerText = spacerCharacter.repeat(spacerCount);
13237
+ let measuredWidthPx = measureTextWidthPx2(
13238
+ spacerText,
13239
+ style,
13240
+ paragraphBaseFontPx
13241
+ );
13242
+ while (measuredWidthPx + spacerAdvancePx * 0.5 < safeWidthPx && spacerCount < 64) {
13243
+ spacerCount += 1;
13244
+ spacerText = spacerCharacter.repeat(spacerCount);
13245
+ measuredWidthPx = measureTextWidthPx2(spacerText, style, paragraphBaseFontPx);
13246
+ }
13247
+ while (spacerCount > 1) {
13248
+ const nextText = spacerCharacter.repeat(spacerCount - 1);
13249
+ const nextWidthPx = measureTextWidthPx2(nextText, style, paragraphBaseFontPx);
13250
+ if (Math.abs(nextWidthPx - safeWidthPx) >= Math.abs(measuredWidthPx - safeWidthPx)) {
13251
+ break;
13252
+ }
13253
+ spacerCount -= 1;
13254
+ spacerText = nextText;
13255
+ measuredWidthPx = nextWidthPx;
13256
+ }
13257
+ return spacerText;
13258
+ }
13022
13259
  function buildParagraphPretextLayoutSource(paragraph, options) {
13260
+ const cacheKey = (options?.allowExplicitLineBreakText ? 1 : 0) | (options?.expandTabsForLayout ? 2 : 0);
13261
+ const cachedVariants = paragraphPretextLayoutSourceCache.get(paragraph);
13262
+ const cachedSource = cachedVariants?.get(cacheKey);
13263
+ if (cachedSource !== void 0) {
13264
+ return cachedSource ?? void 0;
13265
+ }
13266
+ const storeCachedSource = (source) => {
13267
+ if (!cachedVariants) {
13268
+ paragraphPretextLayoutSourceCache.set(
13269
+ paragraph,
13270
+ /* @__PURE__ */ new Map([[cacheKey, source ?? null]])
13271
+ );
13272
+ } else {
13273
+ cachedVariants.set(cacheKey, source ?? null);
13274
+ }
13275
+ return source;
13276
+ };
13023
13277
  if (paragraphHasFormField2(paragraph)) {
13024
- return void 0;
13278
+ return storeCachedSource(void 0);
13025
13279
  }
13026
13280
  if (!options?.allowExplicitLineBreakText && paragraphContainsExplicitLineBreakText(paragraph)) {
13027
- return void 0;
13281
+ return storeCachedSource(void 0);
13028
13282
  }
13029
13283
  const runs = [];
13030
13284
  let combinedText = "";
13031
13285
  const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
13286
+ const tabStopPositionsPx = options?.expandTabsForLayout ? resolveParagraphTabStopsPx(paragraph) : [];
13287
+ const fallbackTabWidthPx = paragraphLooksLikeCheckboxChoiceRow(paragraph) ? checkboxChoiceRowTabWidthPx(paragraph) : DEFAULT_TAB_STOP_PX;
13288
+ let approximateLineWidthPx = 0;
13032
13289
  let lastTextStyle = firstRunStyle(paragraph);
13033
13290
  for (let childIndex = 0; childIndex < paragraph.children.length; childIndex += 1) {
13034
13291
  const child = paragraph.children[childIndex];
@@ -13058,10 +13315,63 @@ function buildParagraphPretextLayoutSource(paragraph, options) {
13058
13315
  continue;
13059
13316
  }
13060
13317
  if (child.type !== "text") {
13061
- return void 0;
13062
- }
13063
- if (child.noteReference || child.text.includes(" ")) {
13064
- return void 0;
13318
+ return storeCachedSource(void 0);
13319
+ }
13320
+ if (child.noteReference) {
13321
+ return storeCachedSource(void 0);
13322
+ }
13323
+ if (child.text.includes(" ")) {
13324
+ if (!options?.expandTabsForLayout) {
13325
+ return storeCachedSource(void 0);
13326
+ }
13327
+ const tabSegments = child.text.split(" ");
13328
+ tabSegments.forEach((segmentText, segmentIndex) => {
13329
+ if (segmentText.length > 0) {
13330
+ const startOffset3 = combinedText.length;
13331
+ combinedText += segmentText;
13332
+ runs.push({
13333
+ kind: "text",
13334
+ key: `run-${childIndex}-${segmentIndex}`,
13335
+ text: segmentText,
13336
+ startOffset: startOffset3,
13337
+ endOffset: combinedText.length,
13338
+ style: child.style,
13339
+ link: child.link
13340
+ });
13341
+ approximateLineWidthPx = updateEstimatedLineWidthPxForText(
13342
+ approximateLineWidthPx,
13343
+ segmentText,
13344
+ child.style
13345
+ );
13346
+ }
13347
+ if (segmentIndex >= tabSegments.length - 1) {
13348
+ return;
13349
+ }
13350
+ const tabWidthPx = resolveTabSpacerWidthPx(
13351
+ tabStopPositionsPx,
13352
+ approximateLineWidthPx,
13353
+ fallbackTabWidthPx
13354
+ );
13355
+ const spacerText = buildParagraphPretextTabSpacerText(
13356
+ tabWidthPx,
13357
+ child.style,
13358
+ paragraphBaseFontPx
13359
+ );
13360
+ const startOffset2 = combinedText.length;
13361
+ combinedText += spacerText;
13362
+ runs.push({
13363
+ kind: "tab",
13364
+ key: `run-${childIndex}-${segmentIndex}-tab`,
13365
+ text: spacerText,
13366
+ startOffset: startOffset2,
13367
+ endOffset: combinedText.length,
13368
+ style: child.style,
13369
+ tabWidthPx
13370
+ });
13371
+ approximateLineWidthPx += tabWidthPx;
13372
+ });
13373
+ lastTextStyle = child.style ?? lastTextStyle;
13374
+ continue;
13065
13375
  }
13066
13376
  const startOffset = combinedText.length;
13067
13377
  combinedText += child.text;
@@ -13074,15 +13384,142 @@ function buildParagraphPretextLayoutSource(paragraph, options) {
13074
13384
  style: child.style,
13075
13385
  link: child.link
13076
13386
  });
13387
+ approximateLineWidthPx = updateEstimatedLineWidthPxForText(
13388
+ approximateLineWidthPx,
13389
+ child.text,
13390
+ child.style
13391
+ );
13077
13392
  lastTextStyle = child.style ?? lastTextStyle;
13078
13393
  }
13079
13394
  if (combinedText.length === 0) {
13080
- return void 0;
13395
+ return storeCachedSource(void 0);
13081
13396
  }
13082
- return {
13397
+ return storeCachedSource({
13083
13398
  text: combinedText,
13084
13399
  runs
13400
+ });
13401
+ }
13402
+ function splitParagraphAtExplicitColumnBreaks(paragraph) {
13403
+ if (!paragraphHasExplicitColumnBreak(paragraph)) {
13404
+ return void 0;
13405
+ }
13406
+ const paragraphChildren = [];
13407
+ let currentChildren = [];
13408
+ let sawExplicitColumnBreak = false;
13409
+ const appendCurrentSegment = () => {
13410
+ paragraphChildren.push(currentChildren);
13411
+ currentChildren = [];
13085
13412
  };
13413
+ for (let childIndex = 0; childIndex < paragraph.children.length; childIndex += 1) {
13414
+ const child = paragraph.children[childIndex];
13415
+ if (!child) {
13416
+ continue;
13417
+ }
13418
+ if (child.type === "text") {
13419
+ if (/^[\r\n]+$/.test(child.text)) {
13420
+ const explicitBreakCount = child.text.replace(/[^\n]/g, "").length;
13421
+ if (explicitBreakCount > 0) {
13422
+ for (let breakIndex = 0; breakIndex < explicitBreakCount; breakIndex += 1) {
13423
+ sawExplicitColumnBreak = true;
13424
+ appendCurrentSegment();
13425
+ }
13426
+ continue;
13427
+ }
13428
+ }
13429
+ currentChildren.push(cloneTextRunWithMetadata(child));
13430
+ continue;
13431
+ }
13432
+ if (child.type === "form-field") {
13433
+ currentChildren.push(cloneFormFieldRun2(child));
13434
+ continue;
13435
+ }
13436
+ return void 0;
13437
+ }
13438
+ if (!sawExplicitColumnBreak) {
13439
+ return void 0;
13440
+ }
13441
+ appendCurrentSegment();
13442
+ return paragraphChildren.map((children, segmentIndex) => {
13443
+ const nextStyle = cloneParagraphStyle2(paragraph.style);
13444
+ if (segmentIndex > 0 && nextStyle?.numbering) {
13445
+ nextStyle.numbering = void 0;
13446
+ }
13447
+ return {
13448
+ ...paragraph,
13449
+ style: nextStyle,
13450
+ sourceXml: void 0,
13451
+ children: children.length > 0 ? children : [
13452
+ {
13453
+ type: "text",
13454
+ text: ""
13455
+ }
13456
+ ]
13457
+ };
13458
+ });
13459
+ }
13460
+ function estimateParagraphContentHeightPx(paragraph, availableWidthPx, numberingDefinitions, docGridLinePitchPx) {
13461
+ if (!paragraphHasImage2(paragraph) && !paragraphHasFormField2(paragraph)) {
13462
+ const lineHeightPx = estimateParagraphLineHeightPx(
13463
+ paragraph,
13464
+ docGridLinePitchPx
13465
+ );
13466
+ const lineCount = paragraphLineCountWithinWidth(
13467
+ paragraph,
13468
+ availableWidthPx,
13469
+ numberingDefinitions
13470
+ );
13471
+ return Math.max(1, lineHeightPx * Math.max(1, lineCount));
13472
+ }
13473
+ return Math.max(
13474
+ 1,
13475
+ estimateParagraphHeightPx(
13476
+ paragraph,
13477
+ availableWidthPx,
13478
+ numberingDefinitions,
13479
+ docGridLinePitchPx
13480
+ ) - paragraphBeforeSpacingPx(paragraph) - paragraphAfterSpacingPx(paragraph)
13481
+ );
13482
+ }
13483
+ function projectParagraphConsumedHeightWithExplicitColumnBreaks(paragraphSegments, pageConsumedHeightPx, pageContentHeightPx, sectionFlowOriginPx, columnCount, availableWidthPx, beforeSpacingPx, afterSpacingPx, collapsedMarginPx, numberingDefinitions, docGridLinePitchPx) {
13484
+ if (paragraphSegments.length <= 1 || columnCount <= 1) {
13485
+ return void 0;
13486
+ }
13487
+ const normalizedParagraphStartPx = Math.max(
13488
+ 0,
13489
+ Math.max(pageConsumedHeightPx, sectionFlowOriginPx)
13490
+ );
13491
+ const firstSegmentTopSpacingPx = pageConsumedHeightPx > 0 ? Math.max(0, beforeSpacingPx - collapsedMarginPx) : beforeSpacingPx;
13492
+ const tallestSegmentHeightPx = paragraphSegments.reduce(
13493
+ (tallest, segment) => {
13494
+ return Math.max(
13495
+ tallest,
13496
+ estimateParagraphContentHeightPx(
13497
+ segment,
13498
+ availableWidthPx,
13499
+ numberingDefinitions,
13500
+ docGridLinePitchPx
13501
+ )
13502
+ );
13503
+ },
13504
+ 0
13505
+ );
13506
+ const projectedConsumedHeightPx = normalizedParagraphStartPx + firstSegmentTopSpacingPx + tallestSegmentHeightPx + afterSpacingPx;
13507
+ const sectionFlowCapacityPx = Math.max(
13508
+ 0,
13509
+ pageContentHeightPx - sectionFlowOriginPx
13510
+ );
13511
+ const sectionConsumedPx = Math.max(
13512
+ 0,
13513
+ pageConsumedHeightPx - sectionFlowOriginPx
13514
+ );
13515
+ const remainingColumnHeightPx = Math.max(
13516
+ 0,
13517
+ sectionFlowCapacityPx / columnCount - sectionConsumedPx
13518
+ );
13519
+ if (projectedConsumedHeightPx - pageConsumedHeightPx > remainingColumnHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
13520
+ return void 0;
13521
+ }
13522
+ return projectedConsumedHeightPx;
13086
13523
  }
13087
13524
  function buildSyntheticPretextLayoutSource(text, style) {
13088
13525
  return {
@@ -13106,16 +13543,50 @@ function sanitizeRenderedPretextFragmentText(text) {
13106
13543
  return text.replace(/\r\n?|\n/g, "");
13107
13544
  }
13108
13545
  function buildParagraphPretextLayoutItems(paragraph, source) {
13546
+ const cachedItems = paragraphPretextLayoutItemsBySource.get(source);
13547
+ if (cachedItems) {
13548
+ return cachedItems;
13549
+ }
13109
13550
  const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
13110
13551
  const wordBreak = pretextWordBreakModeForText(source.text);
13111
- return source.runs.filter((run) => run.endOffset > run.startOffset).map((run) => ({
13552
+ const items = source.runs.filter((run) => run.endOffset > run.startOffset).map((run) => ({
13112
13553
  text: run.text,
13113
13554
  font: resolveMeasureFont(run.style, paragraphBaseFontPx),
13114
13555
  startOffset: run.startOffset,
13115
13556
  endOffset: run.endOffset,
13116
- break: run.kind === "image" ? "never" : "normal",
13557
+ break: run.kind === "image" || run.kind === "tab" ? "never" : "normal",
13117
13558
  wordBreak
13118
13559
  }));
13560
+ paragraphPretextLayoutItemsBySource.set(source, items);
13561
+ return items;
13562
+ }
13563
+ function resolveUniformPretextSourceFont(paragraph, source) {
13564
+ const cachedUniformFont = paragraphPretextUniformFontBySource.get(source);
13565
+ if (cachedUniformFont !== void 0) {
13566
+ return cachedUniformFont ?? void 0;
13567
+ }
13568
+ const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
13569
+ let uniformFont;
13570
+ for (const run of source.runs) {
13571
+ if (run.endOffset <= run.startOffset) {
13572
+ continue;
13573
+ }
13574
+ if (run.kind !== "text") {
13575
+ paragraphPretextUniformFontBySource.set(source, null);
13576
+ return void 0;
13577
+ }
13578
+ const runFont = resolveMeasureFont(run.style, paragraphBaseFontPx);
13579
+ if (uniformFont === void 0) {
13580
+ uniformFont = runFont;
13581
+ continue;
13582
+ }
13583
+ if (runFont !== uniformFont) {
13584
+ paragraphPretextUniformFontBySource.set(source, null);
13585
+ return void 0;
13586
+ }
13587
+ }
13588
+ paragraphPretextUniformFontBySource.set(source, uniformFont ?? null);
13589
+ return uniformFont;
13119
13590
  }
13120
13591
  function buildMeasureSegmentsPretextLayoutItems(segments, paragraphBaseFontPx, text) {
13121
13592
  const wordBreak = pretextWordBreakModeForText(text);
@@ -13902,6 +14373,31 @@ function paragraphStartsWithLastRenderedPageBreak(paragraph) {
13902
14373
  ).replace(/<\/?w:(?:ins|smartTag)\b[^>]*>/gi, "").replace(/\s+/g, "");
13903
14374
  return leadingXml.length === 0;
13904
14375
  }
14376
+ function shouldHonorParagraphStartLastRenderedPageBreak(params) {
14377
+ const pageConsumedHeightPx = Math.max(
14378
+ 0,
14379
+ Math.round(params.pageConsumedHeightPx)
14380
+ );
14381
+ const pageContentHeightPx = Math.max(
14382
+ 0,
14383
+ Math.round(params.pageContentHeightPx)
14384
+ );
14385
+ if (pageConsumedHeightPx <= 0 || pageContentHeightPx <= 0) {
14386
+ return false;
14387
+ }
14388
+ const remainingHeightPx = Math.max(
14389
+ 0,
14390
+ pageContentHeightPx - pageConsumedHeightPx
14391
+ );
14392
+ const maxAllowedRemainingHeightPx = clampNumber(
14393
+ Math.round(
14394
+ pageContentHeightPx * LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_RATIO
14395
+ ),
14396
+ LAST_RENDERED_PAGE_BREAK_HINT_MIN_REMAINING_SPACE_PX,
14397
+ LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_PX
14398
+ );
14399
+ return remainingHeightPx <= maxAllowedRemainingHeightPx;
14400
+ }
13905
14401
  function isOnOffTagEnabled2(tagXml) {
13906
14402
  if (!tagXml) {
13907
14403
  return false;
@@ -14045,7 +14541,8 @@ function sectionBreakAfterParagraphStartsNewPage(paragraph) {
14045
14541
  if (cached) {
14046
14542
  return cached.sectionBreakStartsNewPage;
14047
14543
  }
14048
- return paragraphHasExplicitPageBreak2(paragraph) ? paragraphBreakFlagsBySourceXml.get(xml)?.sectionBreakStartsNewPage ?? false : false;
14544
+ paragraphHasExplicitPageBreak2(paragraph);
14545
+ return paragraphBreakFlagsBySourceXml.get(xml)?.sectionBreakStartsNewPage ?? false;
14049
14546
  }
14050
14547
  function nodeAlreadyEndsAtExplicitPageBoundary(node) {
14051
14548
  if (!node || node.type !== "paragraph") {
@@ -14285,6 +14782,10 @@ function singleLineAutoScaleForFontFamily(fontFamily) {
14285
14782
  }
14286
14783
  return WORD_SINGLE_LINE_AUTO_SCALE;
14287
14784
  }
14785
+ function resolveParagraphSingleLineAutoScale(paragraph, fontFamily) {
14786
+ const baseScale = singleLineAutoScaleForFontFamily(fontFamily);
14787
+ return paragraphHasCheckboxFormField(paragraph) ? Math.max(1.08, baseScale) : baseScale;
14788
+ }
14288
14789
  function paragraphContainsExplicitLineBreakText(paragraph) {
14289
14790
  return paragraph.children.some(
14290
14791
  (child) => child.type === "text" && /[\r\n]/.test(child.text)
@@ -14373,6 +14874,23 @@ function resolveParagraphTabStopsPx(paragraph) {
14373
14874
  ).map((value) => Math.round(value)).sort((left, right) => left - right);
14374
14875
  return stopsPx;
14375
14876
  }
14877
+ function resolveParagraphFirstLineOriginPx(paragraph) {
14878
+ const leftIndentPx = twipsToSignedPixels(paragraph.style?.indent?.leftTwips);
14879
+ const firstLineIndentPx = twipsToSignedPixels(
14880
+ paragraph.style?.indent?.firstLineTwips
14881
+ );
14882
+ const hangingIndentPx = twipsToSignedPixels(
14883
+ paragraph.style?.indent?.hangingTwips
14884
+ );
14885
+ const textIndentPx = firstLineIndentPx ?? (Number.isFinite(hangingIndentPx) ? -hangingIndentPx : 0);
14886
+ return (Number.isFinite(leftIndentPx) ? leftIndentPx : 0) + (Number.isFinite(textIndentPx) ? textIndentPx : 0);
14887
+ }
14888
+ function resolveParagraphFirstLineLeftTabStopsPx(paragraph) {
14889
+ const firstLineOriginPx = resolveParagraphFirstLineOriginPx(paragraph);
14890
+ return (paragraph.style?.tabStops ?? []).filter((tabStop) => tabStop.alignment !== "right").map((tabStop) => twipsToPixels(tabStop.positionTwips)).filter(
14891
+ (value) => Number.isFinite(value) && value > firstLineOriginPx + 0.5
14892
+ ).map((value) => Math.round(value - firstLineOriginPx)).sort((left, right) => left - right);
14893
+ }
14376
14894
  function resolveNextTabStopPx(currentLineWidthPx, tabStopsPx) {
14377
14895
  const nextExplicit = tabStopsPx.find(
14378
14896
  (stopPx) => stopPx > currentLineWidthPx + 0.5
@@ -14586,12 +15104,37 @@ function estimateTabLeaderWrappedLineCountForParagraph(paragraph, maxLineWidthPx
14586
15104
  paragraphBaseFontPx
14587
15105
  );
14588
15106
  }
15107
+ var wrappedLineCountByParagraph = /* @__PURE__ */ new WeakMap();
15108
+ function cachedWrappedLineCountForParagraph(paragraph, widthPx) {
15109
+ return wrappedLineCountByParagraph.get(paragraph)?.get(widthPx);
15110
+ }
15111
+ function rememberWrappedLineCountForParagraph(paragraph, widthPx, lineCount) {
15112
+ let countsByWidth = wrappedLineCountByParagraph.get(paragraph);
15113
+ if (!countsByWidth) {
15114
+ countsByWidth = /* @__PURE__ */ new Map();
15115
+ wrappedLineCountByParagraph.set(paragraph, countsByWidth);
15116
+ }
15117
+ countsByWidth.set(widthPx, lineCount);
15118
+ return lineCount;
15119
+ }
14589
15120
  function estimateWrappedLineCountForParagraph(paragraph, availableWidthPx) {
14590
15121
  const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
14591
15122
  const maxLineWidthPx = Math.max(
14592
15123
  paragraphBaseFontPx * 2,
14593
15124
  Math.round(availableWidthPx)
14594
15125
  );
15126
+ const cachedLineCount = cachedWrappedLineCountForParagraph(
15127
+ paragraph,
15128
+ maxLineWidthPx
15129
+ );
15130
+ if (cachedLineCount !== void 0) {
15131
+ return cachedLineCount;
15132
+ }
15133
+ const rememberLineCount = (lineCount2) => rememberWrappedLineCountForParagraph(
15134
+ paragraph,
15135
+ maxLineWidthPx,
15136
+ Math.max(1, Math.round(lineCount2))
15137
+ );
14595
15138
  const tabStopsPx = resolveParagraphTabStopsPx(paragraph);
14596
15139
  const useTabLeaderLayout = paragraphUsesTabLeaders(paragraph);
14597
15140
  const anchoredTabLayout = paragraphAnchoredTabLayout(paragraph);
@@ -14606,6 +15149,21 @@ function estimateWrappedLineCountForParagraph(paragraph, availableWidthPx) {
14606
15149
  if (!pretextSource) {
14607
15150
  return void 0;
14608
15151
  }
15152
+ const uniformFont = resolveUniformPretextSourceFont(
15153
+ paragraph,
15154
+ pretextSource
15155
+ );
15156
+ if (uniformFont !== void 0) {
15157
+ const fastLineCount = measurePretextPlainTextLineCount(
15158
+ pretextSource.text,
15159
+ uniformFont,
15160
+ maxLineWidthPx,
15161
+ { wordBreak: pretextWordBreakModeForText(pretextSource.text) }
15162
+ );
15163
+ if (fastLineCount !== void 0) {
15164
+ return fastLineCount;
15165
+ }
15166
+ }
14609
15167
  const lineHeightPx = estimateParagraphLineHeightPx(paragraph);
14610
15168
  const layout = layoutParagraphPretextSource(
14611
15169
  paragraph,
@@ -14617,7 +15175,7 @@ function estimateWrappedLineCountForParagraph(paragraph, availableWidthPx) {
14617
15175
  return layout?.lineCount;
14618
15176
  })();
14619
15177
  if (pretextPlainLineCount) {
14620
- return Math.max(1, pretextPlainLineCount);
15178
+ return rememberLineCount(pretextPlainLineCount);
14621
15179
  }
14622
15180
  }
14623
15181
  if (useTabLeaderLayout) {
@@ -14627,7 +15185,7 @@ function estimateWrappedLineCountForParagraph(paragraph, availableWidthPx) {
14627
15185
  paragraphBaseFontPx
14628
15186
  );
14629
15187
  if (tabLeaderLineCount !== void 0) {
14630
- return tabLeaderLineCount;
15188
+ return rememberLineCount(tabLeaderLineCount);
14631
15189
  }
14632
15190
  }
14633
15191
  let lineCount = 1;
@@ -14745,7 +15303,7 @@ function estimateWrappedLineCountForParagraph(paragraph, availableWidthPx) {
14745
15303
  commitToken(token, child.style);
14746
15304
  }
14747
15305
  }
14748
- return hasVisibleContent ? Math.max(1, lineCount) : 1;
15306
+ return rememberLineCount(hasVisibleContent ? lineCount : 1);
14749
15307
  }
14750
15308
  function paragraphAvailableTextWidthPx(paragraph, availableWidthPx, numberingDefinitions) {
14751
15309
  const safeAvailableWidthPx = Math.max(24, Math.round(availableWidthPx));
@@ -14860,6 +15418,58 @@ function wrappedPretextParagraphBlockHeightPx(layout) {
14860
15418
  }
14861
15419
  return Math.max(1, Math.round(layout.height));
14862
15420
  }
15421
+ function resolvePretextLineRangeContentHeightPx(layout, startLineIndex, endLineIndex) {
15422
+ if (layout.lines.length === 0) {
15423
+ return 0;
15424
+ }
15425
+ const lineHeightPx = Math.max(1, Math.round(layout.lineHeightPx ?? 1));
15426
+ const safeStart = Math.max(
15427
+ 0,
15428
+ Math.min(Math.round(startLineIndex), layout.lines.length)
15429
+ );
15430
+ const safeEnd = Math.max(
15431
+ safeStart,
15432
+ Math.min(Math.round(endLineIndex), layout.lines.length)
15433
+ );
15434
+ if (safeEnd <= safeStart) {
15435
+ return 0;
15436
+ }
15437
+ const firstLineTopPx = layout.lines[safeStart]?.y ?? safeStart * lineHeightPx;
15438
+ const lastLineTopPx = layout.lines[safeEnd - 1]?.y ?? (safeEnd - 1) * lineHeightPx;
15439
+ return Math.max(1, Math.round(lastLineTopPx - firstLineTopPx + lineHeightPx));
15440
+ }
15441
+ function resolveMaxPretextLineRangeEndIndexThatFits(layout, startLineIndex, maxEndLineIndex, availableHeightPx) {
15442
+ const safeStart = Math.max(
15443
+ 0,
15444
+ Math.min(Math.round(startLineIndex), layout.lines.length)
15445
+ );
15446
+ const safeMaxEnd = Math.max(
15447
+ safeStart,
15448
+ Math.min(Math.round(maxEndLineIndex), layout.lines.length)
15449
+ );
15450
+ const safeAvailableHeightPx = Math.max(0, Math.round(availableHeightPx));
15451
+ if (safeAvailableHeightPx <= 0 || safeMaxEnd <= safeStart) {
15452
+ return safeStart;
15453
+ }
15454
+ let low = safeStart;
15455
+ let high = safeMaxEnd;
15456
+ let bestEnd = safeStart;
15457
+ while (low <= high) {
15458
+ const mid = Math.floor((low + high) / 2);
15459
+ const candidateHeightPx = resolvePretextLineRangeContentHeightPx(
15460
+ layout,
15461
+ safeStart,
15462
+ mid
15463
+ );
15464
+ if (candidateHeightPx <= safeAvailableHeightPx) {
15465
+ bestEnd = mid;
15466
+ low = mid + 1;
15467
+ continue;
15468
+ }
15469
+ high = mid - 1;
15470
+ }
15471
+ return bestEnd;
15472
+ }
14863
15473
  function estimateAbsoluteFloatingImageFootprintPx(paragraph, image) {
14864
15474
  if (!shouldRenderAbsoluteFloatingImage(image)) {
14865
15475
  return 0;
@@ -14899,10 +15509,7 @@ function resolveAutoLineSpacingMultiple(lineTwips, fallbackMultiple) {
14899
15509
  function autoLineHeightScaleForMultiple(multiple, singleLineScale) {
14900
15510
  const safeSingleLineScale = Math.max(
14901
15511
  MIN_AUTO_LINE_MULTIPLE,
14902
- Math.min(
14903
- 1,
14904
- Number.isFinite(singleLineScale) ? singleLineScale : WORD_SINGLE_LINE_AUTO_SCALE
14905
- )
15512
+ Number.isFinite(singleLineScale) ? singleLineScale : WORD_SINGLE_LINE_AUTO_SCALE
14906
15513
  );
14907
15514
  if (!Number.isFinite(multiple)) {
14908
15515
  return safeSingleLineScale;
@@ -14918,9 +15525,9 @@ function autoLineHeightScaleForMultiple(multiple, singleLineScale) {
14918
15525
  (safeSingleLineScale + (1 - safeSingleLineScale) * blendProgress).toFixed(4)
14919
15526
  );
14920
15527
  }
14921
- function calibrateAutoLineSpacingMultiple(multiple, fontFamily) {
15528
+ function calibrateAutoLineSpacingMultiple(multiple, fontFamily, singleLineScaleOverride) {
14922
15529
  const normalizedMultiple = Math.max(MIN_AUTO_LINE_MULTIPLE, multiple);
14923
- const singleLineScale = singleLineAutoScaleForFontFamily(fontFamily);
15530
+ const singleLineScale = singleLineScaleOverride ?? singleLineAutoScaleForFontFamily(fontFamily);
14924
15531
  return Math.max(
14925
15532
  MIN_AUTO_LINE_MULTIPLE,
14926
15533
  Number(
@@ -14964,13 +15571,18 @@ function estimateParagraphLineHeightPx(paragraph, docGridLinePitchPx, disableDoc
14964
15571
  );
14965
15572
  const baseFontPx = paragraphBaseFontSizePx(paragraph);
14966
15573
  const baseFontFamily = paragraphDominantFontFamily(paragraph);
15574
+ const singleLineScale = resolveParagraphSingleLineAutoScale(
15575
+ paragraph,
15576
+ baseFontFamily
15577
+ );
14967
15578
  const defaultLineMultiple = isTableOfContentsParagraph(paragraph) ? 1.05 : DEFAULT_PARAGRAPH_LINE_MULTIPLE;
14968
15579
  const normalLineHeightPx = Math.max(
14969
15580
  1,
14970
15581
  Math.round(
14971
15582
  baseFontPx * calibrateAutoLineSpacingMultiple(
14972
15583
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
14973
- baseFontFamily
15584
+ baseFontFamily,
15585
+ singleLineScale
14974
15586
  )
14975
15587
  )
14976
15588
  );
@@ -14987,7 +15599,8 @@ function estimateParagraphLineHeightPx(paragraph, docGridLinePitchPx, disableDoc
14987
15599
  }
14988
15600
  const multiple = calibrateAutoLineSpacingMultiple(
14989
15601
  resolveAutoLineSpacingMultiple(lineTwips, defaultLineMultiple),
14990
- baseFontFamily
15602
+ baseFontFamily,
15603
+ singleLineScale
14991
15604
  );
14992
15605
  const autoLineHeightPx = Math.max(1, Math.round(baseFontPx * multiple));
14993
15606
  const minimumReadableAutoLineHeightPx = paragraph.style?.numbering ? Math.ceil(baseFontPx) : 0;
@@ -15153,14 +15766,17 @@ function suppressFirstTableCellParagraphTopSpacing(paragraph) {
15153
15766
  }
15154
15767
  function estimateTableCellContentHeightPx(nodeContent, availableWidthPx, numberingDefinitions, applyWordTableDefaults = false, docGridLinePitchPx) {
15155
15768
  let paragraphIndex = 0;
15156
- return nodeContent.reduce((sum, contentNode) => {
15769
+ let expandedWithPretextLayout = false;
15770
+ let totalHeightPx = 0;
15771
+ for (const contentNode of nodeContent) {
15157
15772
  if (!isParagraphCellContentNode(contentNode)) {
15158
- return sum + estimateTableHeightPx(
15773
+ totalHeightPx += estimateTableHeightPx(
15159
15774
  contentNode,
15160
15775
  availableWidthPx,
15161
15776
  numberingDefinitions,
15162
15777
  docGridLinePitchPx
15163
15778
  );
15779
+ continue;
15164
15780
  }
15165
15781
  const disableDocGridSnap = paragraphDocGridSnapState(contentNode) === "disable";
15166
15782
  const paragraphForLayout = wordLikeTableCellParagraph(
@@ -15174,14 +15790,55 @@ function estimateTableCellContentHeightPx(nodeContent, availableWidthPx, numberi
15174
15790
  docGridLinePitchPx,
15175
15791
  disableDocGridSnap
15176
15792
  );
15793
+ const lineHeightPx = Math.max(
15794
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
15795
+ estimateParagraphLineHeightPx(
15796
+ paragraphForLayout,
15797
+ docGridLinePitchPx,
15798
+ disableDocGridSnap
15799
+ )
15800
+ );
15801
+ const pretextSource = buildParagraphPretextLayoutSource(
15802
+ paragraphForLayout,
15803
+ {
15804
+ allowExplicitLineBreakText: true,
15805
+ expandTabsForLayout: true
15806
+ }
15807
+ );
15808
+ const paragraphTextWidthPx = typeof availableWidthPx === "number" && availableWidthPx > 0 ? paragraphAvailableTextWidthPx(
15809
+ paragraphForLayout,
15810
+ availableWidthPx,
15811
+ numberingDefinitions
15812
+ ) : void 0;
15813
+ const pretextLayout = pretextSource && typeof paragraphTextWidthPx === "number" && paragraphTextWidthPx > 0 ? layoutParagraphPretextSource(
15814
+ paragraphForLayout,
15815
+ pretextSource,
15816
+ paragraphTextWidthPx,
15817
+ lineHeightPx,
15818
+ []
15819
+ ) : void 0;
15177
15820
  const suppressTopSpacing = paragraphIndex === 0 && suppressFirstTableCellParagraphTopSpacing(contentNode);
15178
15821
  paragraphIndex += 1;
15822
+ const beforeSpacing = suppressTopSpacing ? 0 : twipsToPixels(paragraphForLayout.style?.spacing?.beforeTwips) ?? 0;
15823
+ const afterSpacing = twipsToPixels(paragraphForLayout.style?.spacing?.afterTwips) ?? 0;
15824
+ const topBorderInsetPx = paragraphBorderInsetPx(
15825
+ paragraphForLayout.style?.borders?.top
15826
+ );
15827
+ const bottomBorderInsetPx = paragraphBorderInsetPx(
15828
+ paragraphForLayout.style?.borders?.bottom
15829
+ );
15830
+ const pretextHeightPx = pretextLayout ? beforeSpacing + afterSpacing + topBorderInsetPx + bottomBorderInsetPx + wrappedPretextParagraphBlockHeightPx(pretextLayout) : 0;
15831
+ const resolvedBaseHeight = pretextHeightPx > 0 ? Math.max(baseHeight, pretextHeightPx) : baseHeight;
15832
+ if (pretextHeightPx > baseHeight) {
15833
+ expandedWithPretextLayout = true;
15834
+ }
15179
15835
  if (!suppressTopSpacing) {
15180
- return sum + baseHeight;
15836
+ totalHeightPx += resolvedBaseHeight;
15837
+ continue;
15181
15838
  }
15182
- const beforeSpacing = twipsToPixels(paragraphForLayout.style?.spacing?.beforeTwips) ?? 0;
15183
- return sum + Math.max(1, baseHeight - beforeSpacing);
15184
- }, 0);
15839
+ totalHeightPx += Math.max(1, resolvedBaseHeight - beforeSpacing);
15840
+ }
15841
+ return totalHeightPx + (expandedWithPretextLayout ? Math.max(1, MIN_PARAGRAPH_LINE_HEIGHT_PX) : 0);
15185
15842
  }
15186
15843
  function rowAllowsPageSplit(row) {
15187
15844
  return row.style?.cantSplit !== true && row.style?.heightRule !== "exact";
@@ -15199,7 +15856,7 @@ function rowHasDeepFlowContent(row) {
15199
15856
  }
15200
15857
  return nestedTableCount > 0 || blockNodeCount >= SPLITTABLE_TABLE_ROW_DEEP_CONTENT_NODE_THRESHOLD;
15201
15858
  }
15202
- function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitHeightPx) {
15859
+ function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitHeightPx, pageContentHeightPx) {
15203
15860
  if (!rowAllowsPageSplit(row)) {
15204
15861
  return estimatedRowHeightPx;
15205
15862
  }
@@ -15213,6 +15870,13 @@ function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitH
15213
15870
  MIN_PARAGRAPH_LINE_HEIGHT_PX * 2,
15214
15871
  Math.round(explicitHeightPx)
15215
15872
  );
15873
+ const safePageContentHeightPx = Number.isFinite(pageContentHeightPx) && pageContentHeightPx > 0 ? Math.max(
15874
+ MIN_PARAGRAPH_LINE_HEIGHT_PX * 4,
15875
+ Math.round(pageContentHeightPx)
15876
+ ) : void 0;
15877
+ if (safePageContentHeightPx !== void 0 && estimatedRowHeightPx > safePageContentHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
15878
+ return estimatedRowHeightPx;
15879
+ }
15216
15880
  const cappedHeightPx = safeExplicitHeightPx + MIN_PARAGRAPH_LINE_HEIGHT_PX * SPLITTABLE_TABLE_ROW_ESTIMATE_EXTRA_LINE_COUNT;
15217
15881
  return Math.min(estimatedRowHeightPx, cappedHeightPx);
15218
15882
  }
@@ -15250,7 +15914,7 @@ function tableUsesWordLikeParagraphDefaults(table) {
15250
15914
  }
15251
15915
  return table.style?.layout === "fixed" && tableHasVisibleBorders(table) && tableContainsParagraphsWithoutExplicitSpacing(table);
15252
15916
  }
15253
- function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx) {
15917
+ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx, pageContentHeightPx) {
15254
15918
  const defaultCellMargin = table.style?.cellMarginTwips;
15255
15919
  const columnCount = tableColumnCount(table);
15256
15920
  const tableWidthPx = twipsToPixels(table.style?.widthTwips);
@@ -15268,7 +15932,11 @@ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefiniti
15268
15932
  return normalizeColumnWidthsPx(widthsPx, columnCount, tableWidthPx, 1);
15269
15933
  })();
15270
15934
  const rawResolvedTableWidthPx = tableWidthPx ?? rawTableColumnWidthsPx.reduce((sum, widthPx) => sum + widthPx, 0);
15271
- const maxTableWidthPx = Number.isFinite(maxAvailableWidthPx) && maxAvailableWidthPx > 0 ? Math.max(120, maxAvailableWidthPx) : void 0;
15935
+ const collapsedHorizontalBorderBleedPx = resolveCollapsedTableHorizontalOuterBleedPx(table, columnCount);
15936
+ const maxTableWidthPx = Number.isFinite(maxAvailableWidthPx) && maxAvailableWidthPx > 0 ? Math.max(
15937
+ 120,
15938
+ maxAvailableWidthPx - collapsedHorizontalBorderBleedPx
15939
+ ) : void 0;
15272
15940
  const resolvedTableWidthPx = clampTableWidthPx(
15273
15941
  rawResolvedTableWidthPx,
15274
15942
  maxTableWidthPx
@@ -15315,7 +15983,8 @@ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefiniti
15315
15983
  rowHeightPx = capSplitFriendlyTableRowEstimatePx(
15316
15984
  row,
15317
15985
  rowHeightPx,
15318
- explicitHeightPx
15986
+ explicitHeightPx,
15987
+ pageContentHeightPx
15319
15988
  );
15320
15989
  return Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, rowHeightPx);
15321
15990
  });
@@ -15416,6 +16085,45 @@ function paragraphSegmentHasPartialLineRange(paragraphLineRange) {
15416
16085
  }
15417
16086
  return paragraphLineRange.startLineIndex > 0 || paragraphLineRange.endLineIndex < paragraphLineRange.totalLineCount;
15418
16087
  }
16088
+ function resolveLineRangeWithinVerticalSlice(lineTopOffsetsPx, lineHeightPx, sliceTopPx, sliceBottomPx) {
16089
+ if (lineTopOffsetsPx.length === 0 || !Number.isFinite(lineHeightPx) || lineHeightPx <= 0) {
16090
+ return void 0;
16091
+ }
16092
+ const safeSliceTopPx = Math.max(0, sliceTopPx);
16093
+ const safeSliceBottomPx = Math.max(safeSliceTopPx, sliceBottomPx);
16094
+ const sliceHasHeight = safeSliceBottomPx > safeSliceTopPx;
16095
+ let startLineIndex;
16096
+ let endLineIndex;
16097
+ for (let lineIndex = 0; lineIndex < lineTopOffsetsPx.length; lineIndex += 1) {
16098
+ const lineTopPx = lineTopOffsetsPx[lineIndex] ?? lineIndex * lineHeightPx;
16099
+ const lineBottomPx = lineTopPx + lineHeightPx;
16100
+ const lineBelongsToSlice = sliceHasHeight && lineBottomPx > safeSliceTopPx + PAGE_OVERFLOW_TOLERANCE_PX && lineBottomPx <= safeSliceBottomPx + PAGE_OVERFLOW_TOLERANCE_PX;
16101
+ if (lineBelongsToSlice) {
16102
+ if (startLineIndex === void 0) {
16103
+ startLineIndex = lineIndex;
16104
+ }
16105
+ endLineIndex = lineIndex + 1;
16106
+ }
16107
+ }
16108
+ if (startLineIndex === void 0 || endLineIndex === void 0 || endLineIndex <= startLineIndex) {
16109
+ return void 0;
16110
+ }
16111
+ return {
16112
+ startLineIndex,
16113
+ endLineIndex,
16114
+ totalLineCount: lineTopOffsetsPx.length,
16115
+ lineHeightPx
16116
+ };
16117
+ }
16118
+ function resolveTableCellParagraphVisualBottomPx(params) {
16119
+ return Math.max(
16120
+ Math.round(params.paragraphTopPx + params.paragraphHeightPx),
16121
+ Math.round(params.textBottomPx)
16122
+ );
16123
+ }
16124
+ function tableCellParagraphFitsFullyWithinSlice(params) {
16125
+ return params.sliceStartPx <= params.paragraphTopPx + PAGE_OVERFLOW_TOLERANCE_PX && params.sliceBottomPx >= params.paragraphBottomPx + TABLE_CELL_SLICE_FULLY_VISIBLE_BOTTOM_BUFFER_PX - PAGE_OVERFLOW_TOLERANCE_PX;
16126
+ }
15419
16127
  function resolveParagraphSegmentClipBleedPx(paragraphLineRange) {
15420
16128
  if (!paragraphSegmentHasPartialLineRange(paragraphLineRange)) {
15421
16129
  return {
@@ -15425,7 +16133,7 @@ function resolveParagraphSegmentClipBleedPx(paragraphLineRange) {
15425
16133
  }
15426
16134
  return {
15427
16135
  topPx: paragraphLineRange && paragraphLineRange.startLineIndex > 0 ? Math.max(0, PARAGRAPH_SEGMENT_TOP_BLEED_PX) : 0,
15428
- bottomPx: Math.max(0, PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX)
16136
+ bottomPx: paragraphLineRange && paragraphLineRange.endLineIndex < paragraphLineRange.totalLineCount ? Math.max(0, PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX) : 0
15429
16137
  };
15430
16138
  }
15431
16139
  function resolveFallbackParagraphSegmentClipBleedPx(paragraph, paragraphLineRange) {
@@ -15499,12 +16207,32 @@ function estimateRenderedPageSegmentHeightPx(node, segment, model, availableWidt
15499
16207
  false
15500
16208
  ) : 0;
15501
16209
  const afterSpacingPx = paragraphLineRange.endLineIndex >= paragraphLineRange.totalLineCount ? effectiveParagraphAfterSpacingPx(model, segment.nodeIndex, node) : 0;
16210
+ const paragraphPretextSource = buildParagraphPretextLayoutSource(node, {
16211
+ allowExplicitLineBreakText: true,
16212
+ expandTabsForLayout: true
16213
+ });
16214
+ const paragraphPretextLayout = paragraphPretextSource ? layoutParagraphPretextSource(
16215
+ node,
16216
+ paragraphPretextSource,
16217
+ paragraphAvailableTextWidthPx(
16218
+ node,
16219
+ availableWidthPx,
16220
+ numberingDefinitions
16221
+ ),
16222
+ Math.max(1, paragraphLineRange.lineHeightPx),
16223
+ []
16224
+ ) : void 0;
16225
+ const segmentContentHeightPx = paragraphPretextLayout && paragraphPretextLayout.lineCount > 0 ? resolvePretextLineRangeContentHeightPx(
16226
+ paragraphPretextLayout,
16227
+ paragraphLineRange.startLineIndex,
16228
+ paragraphLineRange.endLineIndex
16229
+ ) : Math.max(
16230
+ 1,
16231
+ paragraphLineRange.endLineIndex - paragraphLineRange.startLineIndex
16232
+ ) * Math.max(1, paragraphLineRange.lineHeightPx);
15502
16233
  return Math.max(
15503
16234
  1,
15504
- beforeSpacingPx + Math.max(
15505
- 1,
15506
- paragraphLineRange.endLineIndex - paragraphLineRange.startLineIndex
15507
- ) * Math.max(1, paragraphLineRange.lineHeightPx) + afterSpacingPx
16235
+ beforeSpacingPx + segmentContentHeightPx + afterSpacingPx
15508
16236
  );
15509
16237
  }
15510
16238
  return Math.max(
@@ -15645,6 +16373,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15645
16373
  let pageConsumedHeightPx = 0;
15646
16374
  let previousParagraphAfterPx = 0;
15647
16375
  let currentMetricsIndex = 0;
16376
+ let currentSectionPageFlowOriginPx = 0;
15648
16377
  let currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15649
16378
  0,
15650
16379
  metricsBySection[0]
@@ -15686,11 +16415,13 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15686
16415
  currentPageIndex,
15687
16416
  nodeMetrics
15688
16417
  );
16418
+ currentSectionPageFlowOriginPx = pageConsumedHeightPx;
15689
16419
  }
15690
16420
  if (hardBreakStartNodeIndexes.has(nodeIndex) && currentPageSegments.length > 0) {
15691
16421
  startNextPage();
15692
16422
  pageConsumedHeightPx = 0;
15693
16423
  previousParagraphAfterPx = 0;
16424
+ currentSectionPageFlowOriginPx = 0;
15694
16425
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15695
16426
  currentPageIndex,
15696
16427
  nodeMetrics
@@ -15745,6 +16476,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15745
16476
  startNextPage();
15746
16477
  pageConsumedHeightPx = 0;
15747
16478
  previousParagraphAfterPx = 0;
16479
+ currentSectionPageFlowOriginPx = 0;
15748
16480
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15749
16481
  currentPageIndex,
15750
16482
  nodeMetrics
@@ -15754,15 +16486,20 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15754
16486
  startNextPage();
15755
16487
  pageConsumedHeightPx = 0;
15756
16488
  previousParagraphAfterPx = 0;
16489
+ currentSectionPageFlowOriginPx = 0;
15757
16490
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15758
16491
  currentPageIndex,
15759
16492
  nodeMetrics
15760
16493
  );
15761
16494
  }
15762
- if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak(node) && !nodeAlreadyEndsAtExplicitPageBoundary(model.nodes[nodeIndex - 1]) && currentPageSegments.length > 0) {
16495
+ if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak(node) && shouldHonorParagraphStartLastRenderedPageBreak({
16496
+ pageConsumedHeightPx,
16497
+ pageContentHeightPx: currentPageContentHeightPx
16498
+ }) && !nodeAlreadyEndsAtExplicitPageBoundary(model.nodes[nodeIndex - 1]) && currentPageSegments.length > 0) {
15763
16499
  startNextPage();
15764
16500
  pageConsumedHeightPx = 0;
15765
16501
  previousParagraphAfterPx = 0;
16502
+ currentSectionPageFlowOriginPx = 0;
15766
16503
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15767
16504
  currentPageIndex,
15768
16505
  nodeMetrics
@@ -15782,7 +16519,36 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15782
16519
  nodeIndex,
15783
16520
  node
15784
16521
  );
15785
- const rawNodeHeightPx = Math.max(
16522
+ const paragraphLineHeightPx = estimateParagraphLineHeightPx(
16523
+ node,
16524
+ nodeMetrics.docGridLinePitchPx
16525
+ );
16526
+ const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
16527
+ node,
16528
+ nodeMetrics.pageContentWidthPx,
16529
+ numberingDefinitions
16530
+ );
16531
+ const paragraphPretextSourceForSegmentRendering = buildParagraphPretextLayoutSource(node, {
16532
+ allowExplicitLineBreakText: true,
16533
+ expandTabsForLayout: true
16534
+ });
16535
+ let paragraphPretextLayoutForSegmentRendering;
16536
+ let paragraphPretextLayoutForSegmentRenderingResolved = false;
16537
+ const resolveParagraphPretextLayoutForSegmentRendering = () => {
16538
+ if (paragraphPretextLayoutForSegmentRenderingResolved) {
16539
+ return paragraphPretextLayoutForSegmentRendering;
16540
+ }
16541
+ paragraphPretextLayoutForSegmentRenderingResolved = true;
16542
+ paragraphPretextLayoutForSegmentRendering = paragraphPretextSourceForSegmentRendering ? layoutParagraphPretextSource(
16543
+ node,
16544
+ paragraphPretextSourceForSegmentRendering,
16545
+ paragraphTextWidthPx,
16546
+ paragraphLineHeightPx,
16547
+ []
16548
+ ) : void 0;
16549
+ return paragraphPretextLayoutForSegmentRendering;
16550
+ };
16551
+ let rawNodeHeightPx = Math.max(
15786
16552
  1,
15787
16553
  estimateParagraphHeightPx(
15788
16554
  node,
@@ -15806,6 +16572,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15806
16572
  startNextPage();
15807
16573
  pageConsumedHeightPx = 0;
15808
16574
  previousParagraphAfterPx = 0;
16575
+ currentSectionPageFlowOriginPx = 0;
15809
16576
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15810
16577
  currentPageIndex,
15811
16578
  nodeMetrics
@@ -15816,38 +16583,33 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15816
16583
  1,
15817
16584
  Math.max(rawNodeHeightPx, coverFootprintPx) - collapsedMarginPx
15818
16585
  );
15819
- const paragraphLineHeightPx = estimateParagraphLineHeightPx(
15820
- node,
15821
- nodeMetrics.docGridLinePitchPx
15822
- );
15823
- const paragraphPretextSourceForSegmentRendering = buildParagraphPretextLayoutSource(node, {
15824
- allowExplicitLineBreakText: true
15825
- });
15826
16586
  const paragraphSupportsPretextSegmentRendering = Boolean(
15827
16587
  paragraphPretextSourceForSegmentRendering
15828
16588
  );
15829
- const paragraphPretextLineCount = (() => {
15830
- if (!paragraphContainsExplicitLineBreakText(node)) {
15831
- return void 0;
15832
- }
15833
- const pretextSource = paragraphPretextSourceForSegmentRendering;
15834
- if (!pretextSource) {
15835
- return void 0;
16589
+ const remainingHeightBeforeParagraphPx = Math.max(
16590
+ 0,
16591
+ currentPageContentHeightPx - pageConsumedHeightPx
16592
+ );
16593
+ if (paragraphSupportsPretextSegmentRendering && remainingHeightBeforeParagraphPx <= collapsedNodeHeightPx + paragraphLineHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
16594
+ const pretextLayout = resolveParagraphPretextLayoutForSegmentRendering();
16595
+ const pretextContentHeightPx = pretextLayout ? wrappedPretextParagraphBlockHeightPx(pretextLayout) : void 0;
16596
+ if (Number.isFinite(pretextContentHeightPx)) {
16597
+ rawNodeHeightPx = Math.max(
16598
+ rawNodeHeightPx,
16599
+ Math.max(
16600
+ 1,
16601
+ Math.round(
16602
+ beforeSpacingPx + pretextContentHeightPx + afterSpacingPx
16603
+ )
16604
+ )
16605
+ );
15836
16606
  }
15837
- const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
15838
- node,
15839
- nodeMetrics.pageContentWidthPx,
15840
- numberingDefinitions
15841
- );
15842
- const pretextLayout = layoutParagraphPretextSource(
15843
- node,
15844
- pretextSource,
15845
- paragraphTextWidthPx,
15846
- paragraphLineHeightPx,
15847
- []
15848
- );
15849
- return pretextLayout?.lineCount;
15850
- })();
16607
+ }
16608
+ const collapsedNodeHeightPxAdjusted = Math.max(
16609
+ 1,
16610
+ Math.max(rawNodeHeightPx, coverFootprintPx) - collapsedMarginPx
16611
+ );
16612
+ const paragraphPretextLineCount = paragraphContainsExplicitLineBreakText(node) || paragraphContainsTabCharacter(node) ? resolveParagraphPretextLayoutForSegmentRendering()?.lineCount : void 0;
15851
16613
  const supportsImageParagraphLineSplit = paragraphHasImage2(node) && paragraphSupportsPretextSegmentRendering;
15852
16614
  const paragraphLineCount = paragraphLineCountWithinWidth(
15853
16615
  node,
@@ -15855,6 +16617,54 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15855
16617
  numberingDefinitions
15856
16618
  );
15857
16619
  const resolvedParagraphLineCount = Number.isFinite(paragraphPretextLineCount) && paragraphPretextLineCount > 0 ? Math.max(1, Math.round(paragraphPretextLineCount)) : paragraphLineCount;
16620
+ const explicitColumnBreakParagraphSegments = (nodeMetrics.pageContentHeightMultiplier ?? 1) > 1 ? splitParagraphAtExplicitColumnBreaks(node) : void 0;
16621
+ const tryConsumeExplicitColumnBreakParagraph = () => {
16622
+ if (!explicitColumnBreakParagraphSegments || explicitColumnBreakParagraphSegments.length <= 1) {
16623
+ return false;
16624
+ }
16625
+ const projectedConsumedHeightPx = projectParagraphConsumedHeightWithExplicitColumnBreaks(
16626
+ explicitColumnBreakParagraphSegments,
16627
+ pageConsumedHeightPx,
16628
+ currentPageContentHeightPx,
16629
+ currentSectionPageFlowOriginPx,
16630
+ Math.max(
16631
+ 1,
16632
+ Math.round(nodeMetrics.pageContentHeightMultiplier ?? 1)
16633
+ ),
16634
+ nodeMetrics.pageContentWidthPx,
16635
+ beforeSpacingPx,
16636
+ afterSpacingPx,
16637
+ collapsedMarginPx,
16638
+ numberingDefinitions,
16639
+ nodeMetrics.docGridLinePitchPx
16640
+ );
16641
+ if (!Number.isFinite(projectedConsumedHeightPx)) {
16642
+ return false;
16643
+ }
16644
+ currentPageSegments.push({ nodeIndex });
16645
+ pageConsumedHeightPx = Math.max(
16646
+ pageConsumedHeightPx,
16647
+ Math.round(projectedConsumedHeightPx)
16648
+ );
16649
+ previousParagraphAfterPx = afterSpacingPx;
16650
+ return true;
16651
+ };
16652
+ if (tryConsumeExplicitColumnBreakParagraph()) {
16653
+ continue;
16654
+ }
16655
+ if (explicitColumnBreakParagraphSegments && explicitColumnBreakParagraphSegments.length > 1 && pageConsumedHeightPx > 0 && currentPageSegments.length > 0) {
16656
+ startNextPage();
16657
+ pageConsumedHeightPx = 0;
16658
+ previousParagraphAfterPx = 0;
16659
+ currentSectionPageFlowOriginPx = 0;
16660
+ currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16661
+ currentPageIndex,
16662
+ nodeMetrics
16663
+ );
16664
+ if (tryConsumeExplicitColumnBreakParagraph()) {
16665
+ continue;
16666
+ }
16667
+ }
15858
16668
  const widowControlEnabled = paragraphWidowControlEnabled(node);
15859
16669
  const minLinesPerSegment = widowControlEnabled ? 2 : 1;
15860
16670
  const canSplitParagraphAcrossPages = paragraphCanSplitAcrossPages(node, resolvedParagraphLineCount, {
@@ -15863,6 +16673,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15863
16673
  allowImageParagraphSplit: supportsImageParagraphLineSplit
15864
16674
  }) && (!widowControlEnabled || resolvedParagraphLineCount > 3);
15865
16675
  if (canSplitParagraphAcrossPages && allowParagraphLineSplitting) {
16676
+ const pretextLayoutForSegmentSplitting = resolveParagraphPretextLayoutForSegmentRendering();
15866
16677
  const resolveSegmentReservePx = (startLineIndex, endLineIndex) => {
15867
16678
  const paragraphSegmentRange = {
15868
16679
  startLineIndex,
@@ -15875,6 +16686,16 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15875
16686
  paragraphSegmentRange
15876
16687
  );
15877
16688
  };
16689
+ const resolveSegmentContentHeightPx = (startLineIndex, endLineIndex) => {
16690
+ if (pretextLayoutForSegmentSplitting && pretextLayoutForSegmentSplitting.lineCount > 0) {
16691
+ return resolvePretextLineRangeContentHeightPx(
16692
+ pretextLayoutForSegmentSplitting,
16693
+ startLineIndex,
16694
+ endLineIndex
16695
+ );
16696
+ }
16697
+ return Math.max(1, endLineIndex - startLineIndex) * paragraphLineHeightPx;
16698
+ };
15878
16699
  let lineCursor = 0;
15879
16700
  let isFirstSegment = true;
15880
16701
  while (lineCursor < resolvedParagraphLineCount) {
@@ -15890,7 +16711,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15890
16711
  lineCursor,
15891
16712
  resolvedParagraphLineCount
15892
16713
  );
15893
- const allRemainingHeightPx = topSpacingPx + linesRemaining * paragraphLineHeightPx + bottomSpacingPx;
16714
+ const allRemainingHeightPx = topSpacingPx + resolveSegmentContentHeightPx(
16715
+ lineCursor,
16716
+ resolvedParagraphLineCount
16717
+ ) + bottomSpacingPx;
15894
16718
  if (allRemainingHeightPx + allRemainingSegmentReservePx <= remainingHeightPx2) {
15895
16719
  currentPageSegments.push({
15896
16720
  nodeIndex,
@@ -15922,11 +16746,27 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15922
16746
  availableForLinesPx / paragraphLineHeightPx
15923
16747
  );
15924
16748
  linesThatFit = Math.min(linesThatFit, maxLinesThisPage);
16749
+ if (pretextLayoutForSegmentSplitting && pretextLayoutForSegmentSplitting.lineCount > 0 && linesThatFit > 0) {
16750
+ const exactSegmentEndLineIndex = resolveMaxPretextLineRangeEndIndexThatFits(
16751
+ pretextLayoutForSegmentSplitting,
16752
+ lineCursor,
16753
+ Math.min(
16754
+ resolvedParagraphLineCount,
16755
+ lineCursor + linesThatFit
16756
+ ),
16757
+ availableForLinesPx
16758
+ );
16759
+ linesThatFit = Math.max(
16760
+ 0,
16761
+ exactSegmentEndLineIndex - lineCursor
16762
+ );
16763
+ }
15925
16764
  if (linesThatFit < minLinesPerSegment) {
15926
16765
  if (currentPageSegments.length > 0) {
15927
16766
  startNextPage();
15928
16767
  pageConsumedHeightPx = 0;
15929
16768
  previousParagraphAfterPx = 0;
16769
+ currentSectionPageFlowOriginPx = 0;
15930
16770
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15931
16771
  currentPageIndex,
15932
16772
  nodeMetrics
@@ -15956,7 +16796,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15956
16796
  lineCursor,
15957
16797
  segmentEndLineIndex
15958
16798
  );
15959
- if (topSpacingPx + (segmentEndLineIndex - lineCursor) * paragraphLineHeightPx + segmentReservePx <= remainingHeightPx2) {
16799
+ if (topSpacingPx + resolveSegmentContentHeightPx(
16800
+ lineCursor,
16801
+ segmentEndLineIndex
16802
+ ) + segmentReservePx <= remainingHeightPx2) {
15960
16803
  break;
15961
16804
  }
15962
16805
  linesThatFit -= 1;
@@ -15978,7 +16821,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15978
16821
  lineHeightPx: paragraphLineHeightPx
15979
16822
  }
15980
16823
  });
15981
- pageConsumedHeightPx += topSpacingPx + (safeSegmentEndLineIndex - lineCursor) * paragraphLineHeightPx;
16824
+ pageConsumedHeightPx += topSpacingPx + resolveSegmentContentHeightPx(lineCursor, safeSegmentEndLineIndex);
15982
16825
  previousParagraphAfterPx = 0;
15983
16826
  lineCursor = safeSegmentEndLineIndex;
15984
16827
  isFirstSegment = false;
@@ -15986,6 +16829,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15986
16829
  startNextPage();
15987
16830
  pageConsumedHeightPx = 0;
15988
16831
  previousParagraphAfterPx = 0;
16832
+ currentSectionPageFlowOriginPx = 0;
15989
16833
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15990
16834
  currentPageIndex,
15991
16835
  nodeMetrics
@@ -15994,7 +16838,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15994
16838
  }
15995
16839
  continue;
15996
16840
  }
15997
- let requiredHeightPx = collapsedNodeHeightPx;
16841
+ let requiredHeightPx = collapsedNodeHeightPxAdjusted;
15998
16842
  if (node.style?.keepNext === true && paragraphHasVisibleText2(node)) {
15999
16843
  let chainCursor = nodeIndex;
16000
16844
  let chainPreviousParagraphAfterPx = afterSpacingPx;
@@ -16048,6 +16892,11 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16048
16892
  1,
16049
16893
  nextRawHeightPx - collapsedChainMarginPx
16050
16894
  );
16895
+ requiredHeightPx += keepNextPaginationReservePx(
16896
+ currentChainNode,
16897
+ nextChainNode,
16898
+ chainMetrics.docGridLinePitchPx
16899
+ );
16051
16900
  chainPreviousParagraphAfterPx = nextAfterSpacingPx;
16052
16901
  }
16053
16902
  }
@@ -16085,6 +16934,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16085
16934
  startNextPage();
16086
16935
  pageConsumedHeightPx = 0;
16087
16936
  previousParagraphAfterPx = 0;
16937
+ currentSectionPageFlowOriginPx = 0;
16088
16938
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16089
16939
  currentPageIndex,
16090
16940
  nodeMetrics
@@ -16110,7 +16960,8 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16110
16960
  node,
16111
16961
  nodeMetrics.pageContentWidthPx,
16112
16962
  numberingDefinitions,
16113
- nodeMetrics.docGridLinePitchPx
16963
+ nodeMetrics.docGridLinePitchPx,
16964
+ nodeMetrics.pageContentHeightPx
16114
16965
  );
16115
16966
  if (!measuredRowHeightsPx && !estimatedRowHeightsByTableNodeIndex.has(nodeIndex)) {
16116
16967
  estimatedRowHeightsByTableNodeIndex.set(nodeIndex, estimatedRowHeightsPx);
@@ -16126,14 +16977,45 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16126
16977
  startNextPage();
16127
16978
  pageConsumedHeightPx = 0;
16128
16979
  previousParagraphAfterPx = 0;
16980
+ currentSectionPageFlowOriginPx = 0;
16129
16981
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16130
16982
  currentPageIndex,
16131
16983
  nodeMetrics
16132
16984
  );
16133
16985
  }
16986
+ let headerRunLength = 0;
16987
+ for (const row of node.rows) {
16988
+ if (row.style?.isHeader === true) {
16989
+ headerRunLength += 1;
16990
+ } else {
16991
+ break;
16992
+ }
16993
+ }
16994
+ const headerRunHeightPx = headerRunLength > 0 ? sumEstimatedTableRowHeightsPx(
16995
+ estimatedRowHeightsPx,
16996
+ 0,
16997
+ headerRunLength
16998
+ ) : 0;
16999
+ const canRepeatHeader = headerRunLength > 0 && headerRunHeightPx > 0 && headerRunHeightPx + MIN_PARAGRAPH_LINE_HEIGHT_PX * 2 < currentPageContentHeightPx;
16134
17000
  let rowStartIndex = 0;
16135
17001
  let rowSliceOffsetPx = 0;
17002
+ let repeatedHeaderHeightPxOnThisPage = 0;
16136
17003
  while (rowStartIndex < estimatedRowHeightsPx.length) {
17004
+ if (currentPageSegments.length === 0) {
17005
+ repeatedHeaderHeightPxOnThisPage = 0;
17006
+ }
17007
+ if (canRepeatHeader && rowStartIndex >= headerRunLength && currentPageSegments.length === 0) {
17008
+ currentPageSegments.push({
17009
+ nodeIndex,
17010
+ tableRowRange: {
17011
+ startRowIndex: 0,
17012
+ endRowIndex: headerRunLength
17013
+ }
17014
+ });
17015
+ pageConsumedHeightPx += headerRunHeightPx;
17016
+ previousParagraphAfterPx = 0;
17017
+ repeatedHeaderHeightPxOnThisPage = headerRunHeightPx;
17018
+ }
16137
17019
  const remainingHeightPx = Math.max(
16138
17020
  0,
16139
17021
  currentPageContentHeightPx - pageConsumedHeightPx
@@ -16147,7 +17029,11 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16147
17029
  0,
16148
17030
  currentRowTotalHeightPx - rowSliceOffsetPx
16149
17031
  );
16150
- const rowExceedsFreshPageHeightPx = currentRowTotalHeightPx > currentPageContentHeightPx + PAGE_OVERFLOW_TOLERANCE_PX;
17032
+ const freshPageAvailableHeightPx = Math.max(
17033
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
17034
+ currentPageContentHeightPx - repeatedHeaderHeightPxOnThisPage
17035
+ );
17036
+ const rowExceedsFreshPageHeightPx = currentRowTotalHeightPx > freshPageAvailableHeightPx + PAGE_OVERFLOW_TOLERANCE_PX;
16151
17037
  const canSplitCurrentRow = rowSliceOffsetPx > 0 || rowAllowsPageSplit(currentRow) || rowExceedsFreshPageHeightPx;
16152
17038
  const shouldContinueExistingRowSlice = rowSliceOffsetPx > 0;
16153
17039
  const rowNeedsSliceOnThisPage = ENABLE_TABLE_ROW_SLICING && canSplitCurrentRow && currentRowRemainingHeightPx > remainingHeightPx + PAGE_OVERFLOW_TOLERANCE_PX && (shouldContinueExistingRowSlice || rowExceedsFreshPageHeightPx);
@@ -16155,6 +17041,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16155
17041
  startNextPage();
16156
17042
  pageConsumedHeightPx = 0;
16157
17043
  previousParagraphAfterPx = 0;
17044
+ currentSectionPageFlowOriginPx = 0;
16158
17045
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16159
17046
  currentPageIndex,
16160
17047
  nodeMetrics
@@ -16166,6 +17053,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16166
17053
  startNextPage();
16167
17054
  pageConsumedHeightPx = 0;
16168
17055
  previousParagraphAfterPx = 0;
17056
+ currentSectionPageFlowOriginPx = 0;
16169
17057
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16170
17058
  currentPageIndex,
16171
17059
  nodeMetrics
@@ -16207,6 +17095,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16207
17095
  startNextPage();
16208
17096
  pageConsumedHeightPx = 0;
16209
17097
  previousParagraphAfterPx = 0;
17098
+ currentSectionPageFlowOriginPx = 0;
16210
17099
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16211
17100
  currentPageIndex,
16212
17101
  nodeMetrics
@@ -16215,6 +17104,24 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16215
17104
  continue;
16216
17105
  }
16217
17106
  if (rowSliceOffsetPx > 0) {
17107
+ currentPageSegments.push({
17108
+ nodeIndex,
17109
+ tableRowRange: {
17110
+ startRowIndex: rowStartIndex,
17111
+ endRowIndex: Math.min(
17112
+ estimatedRowHeightsPx.length,
17113
+ rowStartIndex + 1
17114
+ )
17115
+ },
17116
+ tableRowSlice: {
17117
+ rowIndex: rowStartIndex,
17118
+ startOffsetPx: rowSliceOffsetPx,
17119
+ sliceHeightPx: currentRowRemainingHeightPx,
17120
+ totalRowHeightPx: currentRowTotalHeightPx
17121
+ }
17122
+ });
17123
+ pageConsumedHeightPx += currentRowRemainingHeightPx;
17124
+ previousParagraphAfterPx = 0;
16218
17125
  rowStartIndex += 1;
16219
17126
  rowSliceOffsetPx = 0;
16220
17127
  continue;
@@ -16237,6 +17144,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16237
17144
  startNextPage();
16238
17145
  pageConsumedHeightPx = 0;
16239
17146
  previousParagraphAfterPx = 0;
17147
+ currentSectionPageFlowOriginPx = 0;
16240
17148
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16241
17149
  currentPageIndex,
16242
17150
  nodeMetrics
@@ -16267,6 +17175,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16267
17175
  startNextPage();
16268
17176
  pageConsumedHeightPx = 0;
16269
17177
  previousParagraphAfterPx = 0;
17178
+ currentSectionPageFlowOriginPx = 0;
16270
17179
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16271
17180
  currentPageIndex,
16272
17181
  nodeMetrics
@@ -16295,6 +17204,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16295
17204
  startNextPage();
16296
17205
  pageConsumedHeightPx = 0;
16297
17206
  previousParagraphAfterPx = 0;
17207
+ currentSectionPageFlowOriginPx = 0;
16298
17208
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16299
17209
  currentPageIndex,
16300
17210
  nodeMetrics
@@ -16766,6 +17676,10 @@ function resolveHighlightColor(value) {
16766
17676
  }
16767
17677
  function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap = false) {
16768
17678
  const baseFontFamily = paragraphDominantFontFamily(paragraph);
17679
+ const singleLineScale = resolveParagraphSingleLineAutoScale(
17680
+ paragraph,
17681
+ baseFontFamily
17682
+ );
16769
17683
  const lineTwips = paragraph.style?.spacing?.lineTwips;
16770
17684
  const docGridMinimumLineHeightPx = resolveParagraphDocGridLinePitchPx(
16771
17685
  paragraph,
@@ -16782,7 +17696,8 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16782
17696
  }
16783
17697
  return calibrateAutoLineSpacingMultiple(
16784
17698
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16785
- baseFontFamily
17699
+ baseFontFamily,
17700
+ singleLineScale
16786
17701
  );
16787
17702
  }
16788
17703
  const lineRule = paragraph.style?.spacing?.lineRule ?? "auto";
@@ -16799,7 +17714,8 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16799
17714
  lineTwips,
16800
17715
  DEFAULT_PARAGRAPH_LINE_MULTIPLE
16801
17716
  ),
16802
- baseFontFamily
17717
+ baseFontFamily,
17718
+ singleLineScale
16803
17719
  );
16804
17720
  return Number(lineMultiple.toFixed(3));
16805
17721
  }
@@ -16810,7 +17726,8 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16810
17726
  Math.round(
16811
17727
  paragraphBaseFontSizePx(paragraph) * calibrateAutoLineSpacingMultiple(
16812
17728
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16813
- baseFontFamily
17729
+ baseFontFamily,
17730
+ singleLineScale
16814
17731
  )
16815
17732
  )
16816
17733
  );
@@ -16826,12 +17743,29 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16826
17743
  if (lineRule === "exact") {
16827
17744
  return calibrateAutoLineSpacingMultiple(
16828
17745
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16829
- baseFontFamily
17746
+ baseFontFamily,
17747
+ singleLineScale
16830
17748
  );
16831
17749
  }
16832
17750
  return calibrateAutoLineSpacingMultiple(
16833
17751
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16834
- baseFontFamily
17752
+ baseFontFamily,
17753
+ singleLineScale
17754
+ );
17755
+ }
17756
+ function keepNextPaginationReservePx(paragraph, nextParagraph, docGridLinePitchPx) {
17757
+ if (paragraph.style?.keepNext !== true || !nextParagraph || !Number.isFinite(paragraph.style?.headingLevel)) {
17758
+ return 0;
17759
+ }
17760
+ const nextParagraphText = paragraphText(nextParagraph).replace(/\s+/g, " ").trim();
17761
+ if (nextParagraph.style?.numbering === void 0 && nextParagraphText.length < 80) {
17762
+ return 0;
17763
+ }
17764
+ return Math.max(
17765
+ nextParagraph.style?.numbering ? 10 : 6,
17766
+ Math.round(
17767
+ estimateParagraphLineHeightPx(nextParagraph, docGridLinePitchPx) * (nextParagraph.style?.numbering ? 1 : 0.5)
17768
+ )
16835
17769
  );
16836
17770
  }
16837
17771
  function paragraphBorderToCss(border) {
@@ -17405,6 +18339,17 @@ function tableOfContentsLeadingLeftTabStopPx(paragraph) {
17405
18339
  ).sort((left, right) => left - right);
17406
18340
  return leftTabStopPositionsPx[0];
17407
18341
  }
18342
+ function paragraphContainsTabCharacter(paragraph) {
18343
+ return paragraph.children.some((child) => {
18344
+ if (child.type === "text") {
18345
+ return child.text.includes(" ");
18346
+ }
18347
+ if (child.type === "form-field") {
18348
+ return formFieldDisplayValue2(child).includes(" ");
18349
+ }
18350
+ return false;
18351
+ });
18352
+ }
17408
18353
  function paragraphTabCharacterCount(paragraph) {
17409
18354
  return paragraph.children.reduce((count, child) => {
17410
18355
  const text = child.type === "text" ? child.text : child.type === "form-field" ? formFieldDisplayValue2(child) : "";
@@ -18799,6 +19744,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
18799
19744
  ) ? Math.round(options?.floatingAnchorOriginCorrectionXPx) : 0;
18800
19745
  const checkboxChoiceRow = paragraphLooksLikeCheckboxChoiceRow(paragraph);
18801
19746
  const fallbackTabWidthPx = checkboxChoiceRow ? checkboxChoiceRowTabWidthPx(paragraph) : DEFAULT_TAB_STOP_PX;
19747
+ const tabLeaderLeftTabStopPositionsPx = useTabLeaderLayout ? resolveParagraphFirstLineLeftTabStopsPx(paragraph) : [];
18802
19748
  const shouldTrackTabLineWidth = !useTabLeaderLayout && !useAnchoredTabLayout;
18803
19749
  let approximateLineWidthPx = 0;
18804
19750
  let trackedVisibleChildCursor = 0;
@@ -18917,6 +19863,32 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
18917
19863
  lineHeight: "1em"
18918
19864
  };
18919
19865
  };
19866
+ const renderTabLeaderLeftSpacer = (target, key, style, trackedInlineChange, widthPx) => {
19867
+ const textStyle = trackedInlineStyle(
19868
+ runStyleToCss(style, documentTheme),
19869
+ trackedInlineChange
19870
+ );
19871
+ const hasUnderline = Boolean(style?.underline);
19872
+ target.push(
19873
+ /* @__PURE__ */ jsx(
19874
+ "span",
19875
+ {
19876
+ style: {
19877
+ ...textStyle,
19878
+ display: "inline-block",
19879
+ width: widthPx,
19880
+ minWidth: widthPx,
19881
+ whiteSpace: "pre",
19882
+ textDecoration: hasUnderline ? "none" : textStyle.textDecoration,
19883
+ borderBottom: hasUnderline ? "1px solid currentColor" : void 0,
19884
+ lineHeight: "1em"
19885
+ },
19886
+ children: "\xA0"
19887
+ },
19888
+ key
19889
+ )
19890
+ );
19891
+ };
18920
19892
  const resolvePageFieldText = (value, preferredZone) => {
18921
19893
  if (!hasPageField || value.trim().length === 0) {
18922
19894
  return value;
@@ -19206,7 +20178,10 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19206
20178
  (() => {
19207
20179
  const cropLayout = imageCropLayout(child, widthPx, heightPx);
19208
20180
  const imageVisualStyle = {
19209
- filter: appendCssFilters(child.cssFilter, options?.imageFilterSuffix),
20181
+ filter: appendCssFilters(
20182
+ child.cssFilter,
20183
+ options?.imageFilterSuffix
20184
+ ),
19210
20185
  opacity: child.cssOpacity
19211
20186
  };
19212
20187
  const imageTransformStyle = resolveImageRenderTransformStyle(child, {
@@ -19527,14 +20502,42 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19527
20502
  return;
19528
20503
  }
19529
20504
  if (leftText.length > 0) {
19530
- renderRun(
19531
- runsLeft,
19532
- child,
19533
- `${keyPrefix}-run-${childIndex}-left`,
19534
- resolveFieldText(leftText, 0),
19535
- trackedInlineChange,
19536
- childIndex
19537
- );
20505
+ let tabLeaderLeftLineWidthPx = 0;
20506
+ const leftTextParts = leftText.split(" ");
20507
+ leftTextParts.forEach((part, partIndex) => {
20508
+ if (part.length > 0) {
20509
+ const resolvedPart = resolveFieldText(part, 0);
20510
+ renderRun(
20511
+ runsLeft,
20512
+ child,
20513
+ `${keyPrefix}-run-${childIndex}-left-${partIndex}`,
20514
+ resolvedPart,
20515
+ trackedInlineChange,
20516
+ childIndex
20517
+ );
20518
+ tabLeaderLeftLineWidthPx = updateEstimatedLineWidthPxForText(
20519
+ tabLeaderLeftLineWidthPx,
20520
+ resolvedPart,
20521
+ child.style
20522
+ );
20523
+ }
20524
+ if (partIndex >= leftTextParts.length - 1) {
20525
+ return;
20526
+ }
20527
+ const tabWidthPx = resolveTabSpacerWidthPx(
20528
+ tabLeaderLeftTabStopPositionsPx,
20529
+ tabLeaderLeftLineWidthPx,
20530
+ fallbackTabWidthPx
20531
+ );
20532
+ renderTabLeaderLeftSpacer(
20533
+ runsLeft,
20534
+ `${keyPrefix}-run-${childIndex}-left-tab-${partIndex}`,
20535
+ child.style,
20536
+ trackedInlineChange,
20537
+ tabWidthPx
20538
+ );
20539
+ tabLeaderLeftLineWidthPx += tabWidthPx;
20540
+ });
19538
20541
  }
19539
20542
  renderRun(
19540
20543
  runsRight,
@@ -19760,10 +20763,10 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19760
20763
  {
19761
20764
  "data-docx-tab-zone": "left",
19762
20765
  style: {
19763
- display: "inline-flex",
20766
+ display: "block",
20767
+ flex: "0 1 auto",
19764
20768
  minWidth: 0,
19765
- whiteSpace: "pre-wrap",
19766
- alignItems: "baseline"
20769
+ whiteSpace: "pre-wrap"
19767
20770
  },
19768
20771
  children: runsLeft
19769
20772
  }
@@ -19791,12 +20794,13 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19791
20794
  {
19792
20795
  "data-docx-tab-zone": "right",
19793
20796
  style: {
19794
- display: "inline-flex",
19795
- minWidth: 0,
19796
- justifyContent: "flex-end",
20797
+ display: "block",
20798
+ flex: "0 0 max-content",
20799
+ minWidth: "max-content",
20800
+ width: "max-content",
19797
20801
  textAlign: "right",
19798
- whiteSpace: "pre-wrap",
19799
- alignItems: "baseline"
20802
+ whiteSpace: "nowrap",
20803
+ textIndent: 0
19800
20804
  },
19801
20805
  children: runsRight
19802
20806
  }
@@ -20046,20 +21050,7 @@ function buildParagraphNumberingLabels(model) {
20046
21050
  ])
20047
21051
  );
20048
21052
  const countersByNumId = /* @__PURE__ */ new Map();
20049
- const headingCountersByAbstractNumId = /* @__PURE__ */ new Map();
20050
- const isHeadingLikeParagraph = (paragraph) => {
20051
- if (Number.isFinite(paragraph.style?.headingLevel)) {
20052
- return true;
20053
- }
20054
- if (isTableOfContentsParagraph(paragraph)) {
20055
- return true;
20056
- }
20057
- const styleId = paragraph.style?.styleId?.trim().toLowerCase();
20058
- if (!styleId) {
20059
- return false;
20060
- }
20061
- return /(?:^|[\s_-])heading(?:[\s_-]?\d+)?$/.test(styleId) || /^heading\d*$/.test(styleId);
20062
- };
21053
+ const abstractCountersByAbstractNumId = /* @__PURE__ */ new Map();
20063
21054
  const registerParagraph = (paragraph, key) => {
20064
21055
  const paragraphNumbering = paragraph.style?.numbering;
20065
21056
  if (!paragraphNumbering || paragraphNumbering.numId <= 0) {
@@ -20070,13 +21061,12 @@ function buildParagraphNumberingLabels(model) {
20070
21061
  const level = findNumberingLevelDefinition(numbering, numId, ilvl);
20071
21062
  const numberingInstance = numberingInstanceByNumId.get(numId);
20072
21063
  const abstractNumId = numberingInstance?.abstractNumId;
20073
- const isSharedCounterParagraph = isHeadingLikeParagraph(paragraph);
20074
21064
  const template = level?.text ?? `%${ilvl + 1}.`;
20075
21065
  if (!template || template.trim().length === 0) {
20076
21066
  return;
20077
21067
  }
20078
21068
  const counters = countersByNumId.get(numId) ?? [];
20079
- const sharedAbstractCounters = isSharedCounterParagraph && Number.isFinite(abstractNumId) ? headingCountersByAbstractNumId.get(abstractNumId) ?? [] : void 0;
21069
+ const sharedAbstractCounters = Number.isFinite(abstractNumId) ? abstractCountersByAbstractNumId.get(abstractNumId) ?? [] : void 0;
20080
21070
  let parentCountersChanged = false;
20081
21071
  for (let index = 0; index < ilvl; index += 1) {
20082
21072
  const abstractCounterValue = sharedAbstractCounters && Number.isFinite(sharedAbstractCounters[index]) ? Math.max(1, Math.round(sharedAbstractCounters[index])) : void 0;
@@ -20105,7 +21095,7 @@ function buildParagraphNumberingLabels(model) {
20105
21095
  for (let index = ilvl + 1; index < sharedAbstractCounters.length; index += 1) {
20106
21096
  sharedAbstractCounters[index] = void 0;
20107
21097
  }
20108
- headingCountersByAbstractNumId.set(
21098
+ abstractCountersByAbstractNumId.set(
20109
21099
  abstractNumId,
20110
21100
  sharedAbstractCounters
20111
21101
  );
@@ -20851,6 +21841,14 @@ function tableBorderToCss(border) {
20851
21841
  const color = border?.color ?? "#000000";
20852
21842
  return `${widthPx}px ${cssStyle} ${color}`;
20853
21843
  }
21844
+ function tableBorderStrokeWidthPx(border) {
21845
+ const type = normalizeBorderType(border?.type);
21846
+ if (!type || type === "none" || type === "nil") {
21847
+ return 0;
21848
+ }
21849
+ const sizeEighthPt = border?.sizeEighthPt;
21850
+ return Number.isFinite(sizeEighthPt) && sizeEighthPt > 0 ? Math.max(0.5, Number((sizeEighthPt / 6).toFixed(2))) : 1;
21851
+ }
20854
21852
  function borderTypeVisible(type) {
20855
21853
  const normalizedType = normalizeBorderType(type);
20856
21854
  return Boolean(
@@ -21302,6 +22300,68 @@ function resolveTableCellBorderCss(tableBorders, cellBorders, rowIndex, rowCount
21302
22300
  ...left !== void 0 ? { borderLeft: left } : void 0
21303
22301
  };
21304
22302
  }
22303
+ function resolveCollapsedTableHorizontalOuterBleedPx(table, columnCount = tableColumnCount(table)) {
22304
+ if (columnCount <= 0 || tableUsesSeparateBorderModel(table)) {
22305
+ return 0;
22306
+ }
22307
+ const rowCount = table.rows.length;
22308
+ const tableBorders = table.style?.borders;
22309
+ let maxLeftBorderWidthPx = tableBorderStrokeWidthPx(tableBorders?.left);
22310
+ let maxRightBorderWidthPx = tableBorderStrokeWidthPx(tableBorders?.right);
22311
+ table.rows.forEach((row, rowIndex) => {
22312
+ let columnCursor = 0;
22313
+ row.cells.forEach((cell) => {
22314
+ const columnSpan = cell.style?.gridSpan && cell.style.gridSpan > 1 ? cell.style.gridSpan : 1;
22315
+ const startColumnIndex = columnCursor;
22316
+ const endColumnIndex = Math.min(
22317
+ columnCount - 1,
22318
+ startColumnIndex + columnSpan - 1
22319
+ );
22320
+ columnCursor += columnSpan;
22321
+ if (cell.style?.vMergeContinuation) {
22322
+ return;
22323
+ }
22324
+ if (startColumnIndex === 0) {
22325
+ maxLeftBorderWidthPx = Math.max(
22326
+ maxLeftBorderWidthPx,
22327
+ tableBorderStrokeWidthPx(
22328
+ resolveTableBorder(
22329
+ tableBorders,
22330
+ cell.style?.borders,
22331
+ "left",
22332
+ rowIndex,
22333
+ rowCount,
22334
+ startColumnIndex,
22335
+ endColumnIndex,
22336
+ columnCount
22337
+ )
22338
+ )
22339
+ );
22340
+ }
22341
+ if (endColumnIndex >= columnCount - 1) {
22342
+ maxRightBorderWidthPx = Math.max(
22343
+ maxRightBorderWidthPx,
22344
+ tableBorderStrokeWidthPx(
22345
+ resolveTableBorder(
22346
+ tableBorders,
22347
+ cell.style?.borders,
22348
+ "right",
22349
+ rowIndex,
22350
+ rowCount,
22351
+ startColumnIndex,
22352
+ endColumnIndex,
22353
+ columnCount
22354
+ )
22355
+ )
22356
+ );
22357
+ }
22358
+ });
22359
+ });
22360
+ return Math.max(
22361
+ 0,
22362
+ Math.ceil((maxLeftBorderWidthPx + maxRightBorderWidthPx) / 2)
22363
+ );
22364
+ }
21305
22365
  function resolveTableCellDiagonalOverlayCss(tableBorders, cellBorders) {
21306
22366
  const diagonalDownBorder = cellBorders?.tl2br ?? tableBorders?.tl2br;
21307
22367
  const diagonalUpBorder = cellBorders?.tr2bl ?? tableBorders?.tr2bl;
@@ -23193,6 +24253,7 @@ function useDocxEditor(options = {}) {
23193
24253
  const [status, setStatus] = React.useState(
23194
24254
  options.initialStatus ?? "Ready"
23195
24255
  );
24256
+ const isImporting = false;
23196
24257
  const [documentTheme, setDocumentThemeState] = React.useState(options.initialDocumentTheme ?? "light");
23197
24258
  const [showTrackedChanges, setShowTrackedChangesState] = React.useState(options.initialShowTrackedChanges ?? false);
23198
24259
  const [paginationInfo, setPaginationInfo] = React.useState({
@@ -26659,6 +27720,7 @@ function useDocxEditor(options = {}) {
26659
27720
  documentLoadNonce,
26660
27721
  fileName,
26661
27722
  status,
27723
+ isImporting,
26662
27724
  documentTheme,
26663
27725
  trackedChanges,
26664
27726
  showTrackedChanges,
@@ -26943,12 +28005,9 @@ function useDocxPageThumbnails(editor, options = {}) {
26943
28005
  [pageSurfaceRegistryEditor]
26944
28006
  );
26945
28007
  React.useEffect(
26946
- () => subscribeDocxViewerPageSurfaces(
26947
- pageSurfaceRegistryEditor,
26948
- () => {
26949
- setPageSurfaceEpoch((current) => current + 1);
26950
- }
26951
- ),
28008
+ () => subscribeDocxViewerPageSurfaces(pageSurfaceRegistryEditor, () => {
28009
+ setPageSurfaceEpoch((current) => current + 1);
28010
+ }),
26952
28011
  [pageSurfaceRegistryEditor]
26953
28012
  );
26954
28013
  const mountedPageElements = React.useMemo(
@@ -27035,7 +28094,9 @@ function useDocxPageThumbnails(editor, options = {}) {
27035
28094
  );
27036
28095
  await Promise.all(tasks);
27037
28096
  }, [renderPageThumbnailToCanvas]);
27038
- const renderPageThumbnailToCanvasRef = React.useRef(renderPageThumbnailToCanvas);
28097
+ const renderPageThumbnailToCanvasRef = React.useRef(
28098
+ renderPageThumbnailToCanvas
28099
+ );
27039
28100
  React.useEffect(() => {
27040
28101
  renderPageThumbnailToCanvasRef.current = renderPageThumbnailToCanvas;
27041
28102
  }, [renderPageThumbnailToCanvas]);
@@ -27670,7 +28731,11 @@ function renderHeaderNode(node, keyPrefix, documentTheme, numberingDefinitions,
27670
28731
  return normalizeColumnWidthsPx(widthsPx, columnCount, tableWidthPx, 1);
27671
28732
  })();
27672
28733
  const rawResolvedTableWidthPx = tableWidthPx ?? rawTableColumnWidthsPx.reduce((sum, widthPx) => sum + widthPx, 0);
27673
- const maxTableWidthPx = Number.isFinite(maxContentWidthPx) && maxContentWidthPx > 0 ? Math.max(120, maxContentWidthPx - tableIndentPx) : void 0;
28734
+ const collapsedHorizontalBorderBleedPx = resolveCollapsedTableHorizontalOuterBleedPx(node, columnCount);
28735
+ const maxTableWidthPx = Number.isFinite(maxContentWidthPx) && maxContentWidthPx > 0 ? Math.max(
28736
+ 120,
28737
+ maxContentWidthPx - tableIndentPx - collapsedHorizontalBorderBleedPx
28738
+ ) : void 0;
27674
28739
  const resolvedTableWidthPx = clampTableWidthPx(
27675
28740
  rawResolvedTableWidthPx,
27676
28741
  maxTableWidthPx
@@ -27783,6 +28848,7 @@ function renderHeaderNode(node, keyPrefix, documentTheme, numberingDefinitions,
27783
28848
  "span",
27784
28849
  {
27785
28850
  contentEditable: false,
28851
+ "data-docx-pagination-ignore": "true",
27786
28852
  style: {
27787
28853
  position: "absolute",
27788
28854
  top: -TABLE_HANDLE_SAFEZONE_TOP_PX,
@@ -27800,6 +28866,7 @@ function renderHeaderNode(node, keyPrefix, documentTheme, numberingDefinitions,
27800
28866
  "span",
27801
28867
  {
27802
28868
  contentEditable: false,
28869
+ "data-docx-pagination-ignore": "true",
27803
28870
  style: {
27804
28871
  position: "absolute",
27805
28872
  right: -TABLE_HANDLE_SAFEZONE_RIGHT_PX,
@@ -28411,6 +29478,11 @@ function DocxEditorViewer({
28411
29478
  measuredPageContentIdentityKeysByIndex,
28412
29479
  setMeasuredPageContentIdentityKeysByIndex
28413
29480
  ] = React.useState([]);
29481
+ const [hasMeasuredBodyFooterOverlap, setHasMeasuredBodyFooterOverlap] = React.useState(false);
29482
+ const measuredBodyFooterOverlapCandidateRef = React.useRef({
29483
+ signature: void 0,
29484
+ consecutivePasses: 0
29485
+ });
28414
29486
  const [, setRenderableImageSourceRevision] = React.useState(0);
28415
29487
  const [activeEditableParagraphSegment, setActiveEditableParagraphSegment] = React.useState(void 0);
28416
29488
  const wrappedParagraphTextareaRef = React.useRef(
@@ -28420,6 +29492,10 @@ function DocxEditorViewer({
28420
29492
  const wrappedParagraphSelectionDragRef = React.useRef(void 0);
28421
29493
  const wrappedParagraphSurfaceRegistryRef = React.useRef(/* @__PURE__ */ new Map());
28422
29494
  const [isInitialPaginationSettled, setIsInitialPaginationSettled] = React.useState(!deferInitialPaginationPaint);
29495
+ const [
29496
+ initialPaginationBackgroundRefinementUnlocked,
29497
+ setInitialPaginationBackgroundRefinementUnlocked
29498
+ ] = React.useState(!deferInitialPaginationPaint);
28423
29499
  const [postImportPaginationUnlocked, setPostImportPaginationUnlocked] = React.useState(false);
28424
29500
  const [
28425
29501
  initialPaginationReservedLayoutState,
@@ -28461,6 +29537,11 @@ function DocxEditorViewer({
28461
29537
  React.useEffect(() => {
28462
29538
  setMeasuredPageContentHeightByIndex([]);
28463
29539
  setMeasuredPageContentIdentityKeysByIndex([]);
29540
+ setHasMeasuredBodyFooterOverlap(false);
29541
+ measuredBodyFooterOverlapCandidateRef.current = {
29542
+ signature: void 0,
29543
+ consecutivePasses: 0
29544
+ };
28464
29545
  setTableMeasuredRowHeights({});
28465
29546
  setTableRowHeights({});
28466
29547
  setTableColumnWidths({});
@@ -28504,6 +29585,9 @@ function DocxEditorViewer({
28504
29585
  }
28505
29586
  initialPaginationRevealFrameRef.current = null;
28506
29587
  setIsInitialPaginationSettled(!deferInitialPaginationPaint);
29588
+ setInitialPaginationBackgroundRefinementUnlocked(
29589
+ !deferInitialPaginationPaint
29590
+ );
28507
29591
  }, [deferInitialPaginationPaint, editor.documentLoadNonce]);
28508
29592
  const [activeRowResize, setActiveRowResize] = React.useState();
28509
29593
  const [activeEmbeddedRowResize, setActiveEmbeddedRowResize] = React.useState();
@@ -28792,6 +29876,28 @@ function DocxEditorViewer({
28792
29876
  }
28793
29877
  return widthByNodeIndex;
28794
29878
  }, [editor.model.nodes, paginationSectionMetrics]);
29879
+ const pageContentHeightPxByNodeIndex = React.useMemo(() => {
29880
+ const heightByNodeIndex = /* @__PURE__ */ new Map();
29881
+ if (editor.model.nodes.length === 0 || paginationSectionMetrics.length === 0) {
29882
+ return heightByNodeIndex;
29883
+ }
29884
+ let currentMetricsIndex = 0;
29885
+ for (let nodeIndex = 0; nodeIndex < editor.model.nodes.length; nodeIndex += 1) {
29886
+ currentMetricsIndex = resolvePaginationSectionMetricsIndexForNodeIndex(
29887
+ paginationSectionMetrics,
29888
+ nodeIndex,
29889
+ currentMetricsIndex
29890
+ );
29891
+ const pageContentHeightPx = paginationSectionMetrics[currentMetricsIndex]?.pageContentHeightPx;
29892
+ if (Number.isFinite(pageContentHeightPx) && pageContentHeightPx > 0) {
29893
+ heightByNodeIndex.set(
29894
+ nodeIndex,
29895
+ Math.round(pageContentHeightPx)
29896
+ );
29897
+ }
29898
+ }
29899
+ return heightByNodeIndex;
29900
+ }, [editor.model.nodes, paginationSectionMetrics]);
28795
29901
  const sectionColumnsBySectionIndex = React.useMemo(
28796
29902
  () => documentSections.map(
28797
29903
  (section) => parseSectionColumns(section.sectionPropertiesXml)
@@ -28841,6 +29947,7 @@ function DocxEditorViewer({
28841
29947
  activeDraftKeys,
28842
29948
  numberingDefinitions: editor.model.metadata.numberingDefinitions,
28843
29949
  pageContentWidthPxByNodeIndex,
29950
+ pageContentHeightPxByNodeIndex,
28844
29951
  docGridLinePitchPxByNodeIndex
28845
29952
  }
28846
29953
  );
@@ -28850,6 +29957,7 @@ function DocxEditorViewer({
28850
29957
  editor.canUndo,
28851
29958
  editor.model.metadata.numberingDefinitions,
28852
29959
  editor.model.nodes,
29960
+ pageContentHeightPxByNodeIndex,
28853
29961
  pageContentWidthPxByNodeIndex,
28854
29962
  disableMeasuredImportPagination,
28855
29963
  tableDraftLayoutEpoch,
@@ -28907,17 +30015,43 @@ function DocxEditorViewer({
28907
30015
  (count, node) => count + (node.type === "paragraph" && paragraphHasLastRenderedPageBreak(node) ? 1 : 0),
28908
30016
  0
28909
30017
  ) : void 0;
30018
+ const hasMultiColumnRenderedPageBreakHints = editor.model.nodes.some(
30019
+ (node, nodeIndex) => {
30020
+ if (node.type !== "paragraph" || !paragraphStartsWithLastRenderedPageBreak(node)) {
30021
+ return false;
30022
+ }
30023
+ const metricsIndex = resolvePaginationSectionMetricsIndexForNodeIndex(
30024
+ paginationSectionMetrics,
30025
+ nodeIndex,
30026
+ 0
30027
+ );
30028
+ return (paginationSectionMetrics[metricsIndex]?.pageContentHeightMultiplier ?? 1) > 1;
30029
+ }
30030
+ );
28910
30031
  const minimumPageCount = Math.max(1, hardBreakCount + 1);
28911
30032
  const targetPageCount = Number.isFinite(storedDocumentPageCount2) && storedDocumentPageCount2 > 0 ? Math.max(
28912
30033
  minimumPageCount,
28913
30034
  Math.round(storedDocumentPageCount2)
28914
30035
  ) : void 0;
30036
+ let estimatedPages = buildEstimatedPages(
30037
+ tableMeasuredRowHeightsForPagination
30038
+ );
30039
+ let estimatedPagesUseMeasuredPageContentHeightsForRender = canUseMeasuredPageContentHeights;
30040
+ let estimatedRenderMeasuredPageContentHeightsPxByPageIndex = canUseMeasuredPageContentHeights ? measuredPageContentHeightByIndex : void 0;
30041
+ let estimatedRenderPageContentHeightScale = void 0;
30042
+ const deferExpensiveInitialPaginationReconciliation = deferInitialPaginationPaint && !initialPaginationBackgroundRefinementUnlocked;
30043
+ if (deferExpensiveInitialPaginationReconciliation) {
30044
+ return {
30045
+ pages: estimatedPages,
30046
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30047
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30048
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
30049
+ };
30050
+ }
28915
30051
  const pureEstimatedPages = buildEstimatedPages(
28916
30052
  tableMeasuredRowHeightsForPagination,
28917
30053
  null
28918
30054
  );
28919
- let estimatedPages = buildEstimatedPages(tableMeasuredRowHeightsForPagination);
28920
- let estimatedPagesUseMeasuredPageContentHeightsForRender = canUseMeasuredPageContentHeights;
28921
30055
  if (measuredPageContentHeightByIndex && measuredPageContentHeightByIndex.length > 0) {
28922
30056
  const measuredPagesAreOnlySplitParagraphs = estimatedPages.length > 0 && estimatedPages.every(
28923
30057
  (pageSegments) => documentPageContainsOnlySplitParagraphSegments(pageSegments)
@@ -28928,21 +30062,29 @@ function DocxEditorViewer({
28928
30062
  if (measuredPagesAreOnlySplitParagraphs && purePagesAreOnlySplitParagraphs && pureEstimatedPages.length < estimatedPages.length) {
28929
30063
  estimatedPages = pureEstimatedPages;
28930
30064
  estimatedPagesUseMeasuredPageContentHeightsForRender = false;
30065
+ estimatedRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30066
+ estimatedRenderPageContentHeightScale = void 0;
28931
30067
  }
28932
30068
  }
28933
- if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && tableMeasuredRowHeightsForPagination) {
30069
+ if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && tableMeasuredRowHeightsForPagination && !hasMultiColumnRenderedPageBreakHints) {
28934
30070
  const candidatePages = [
28935
30071
  {
28936
30072
  pages: estimatedPages,
28937
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30073
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30074
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30075
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
28938
30076
  },
28939
30077
  {
28940
30078
  pages: buildEstimatedPages(void 0),
28941
- useMeasuredPageContentHeightsForRender: canUseMeasuredPageContentHeights
30079
+ useMeasuredPageContentHeightsForRender: canUseMeasuredPageContentHeights,
30080
+ renderMeasuredPageContentHeightsPxByPageIndex: canUseMeasuredPageContentHeights ? measuredPageContentHeightByIndex : void 0,
30081
+ renderPageContentHeightScale: void 0
28942
30082
  },
28943
30083
  {
28944
30084
  pages: buildEstimatedPages(void 0, null),
28945
- useMeasuredPageContentHeightsForRender: false
30085
+ useMeasuredPageContentHeightsForRender: false,
30086
+ renderMeasuredPageContentHeightsPxByPageIndex: void 0,
30087
+ renderPageContentHeightScale: void 0
28946
30088
  }
28947
30089
  ];
28948
30090
  const bestCandidate = candidatePages.reduce((best, candidate) => {
@@ -28954,11 +30096,15 @@ function DocxEditorViewer({
28954
30096
  });
28955
30097
  estimatedPages = bestCandidate.pages;
28956
30098
  estimatedPagesUseMeasuredPageContentHeightsForRender = bestCandidate.useMeasuredPageContentHeightsForRender;
28957
- } else if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0) {
30099
+ estimatedRenderMeasuredPageContentHeightsPxByPageIndex = bestCandidate.renderMeasuredPageContentHeightsPxByPageIndex;
30100
+ estimatedRenderPageContentHeightScale = bestCandidate.renderPageContentHeightScale;
30101
+ } else if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && !hasMultiColumnRenderedPageBreakHints) {
28958
30102
  const pureEstimatedPages2 = buildEstimatedPages(void 0, null);
28959
30103
  if (Math.abs(pureEstimatedPages2.length - targetPageCount) < Math.abs(estimatedPages.length - targetPageCount)) {
28960
30104
  estimatedPages = pureEstimatedPages2;
28961
30105
  estimatedPagesUseMeasuredPageContentHeightsForRender = false;
30106
+ estimatedRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30107
+ estimatedRenderPageContentHeightScale = void 0;
28962
30108
  }
28963
30109
  }
28964
30110
  const measuredPageHeightOverridesReduceContent = !editor.canUndo && !editor.canRedo && !floatingMovePreview && !dropCapMovePreview && estimatedPages.some((segments, pageIndex) => {
@@ -28985,7 +30131,9 @@ function DocxEditorViewer({
28985
30131
  if (!Number.isFinite(storedDocumentPageCount2) || storedDocumentPageCount2 <= 0) {
28986
30132
  return {
28987
30133
  pages: estimatedPages,
28988
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30134
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30135
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30136
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
28989
30137
  };
28990
30138
  }
28991
30139
  const resolvedTargetPageCount = targetPageCount ?? minimumPageCount;
@@ -28995,22 +30143,26 @@ function DocxEditorViewer({
28995
30143
  )
28996
30144
  );
28997
30145
  const allowMeasuredReductionOverPaginationReconciliation = measuredPageHeightOverridesReduceContent && estimatedPages.length > resolvedTargetPageCount;
28998
- const allowStoredPageCountReconciliation = !editor.canUndo && !editor.canRedo && !hasPageAnchoredFloatingFooterContent && shouldAllowStoredPageCountReduction({
30146
+ const allowStoredPageCountReconciliation = !editor.canUndo && !editor.canRedo && !hasPageAnchoredFloatingFooterContent && !hasMultiColumnRenderedPageBreakHints && shouldAllowStoredPageCountReduction({
28999
30147
  estimatedPageCount: estimatedPages.length,
29000
30148
  targetPageCount: resolvedTargetPageCount,
29001
30149
  hasLastRenderedPageBreakHints,
29002
- renderedBreakHintPageCount
30150
+ renderedBreakHintPageCount,
30151
+ hasMeasuredBodyFooterOverlap
29003
30152
  }) && (!measuredPageHeightOverridesReduceContent || allowMeasuredReductionOverPaginationReconciliation);
29004
30153
  if (!allowStoredPageCountReconciliation) {
29005
30154
  return {
29006
30155
  pages: estimatedPages,
29007
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30156
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30157
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30158
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
29008
30159
  };
29009
30160
  }
29010
30161
  if (estimatedPages.length === resolvedTargetPageCount) {
29011
30162
  return {
29012
30163
  pages: estimatedPages,
29013
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30164
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30165
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex
29014
30166
  };
29015
30167
  }
29016
30168
  const reconciliationScales = allowMeasuredReductionOverPaginationReconciliation ? [
@@ -29030,7 +30182,7 @@ function DocxEditorViewer({
29030
30182
  1.28,
29031
30183
  1.3
29032
30184
  ] : void 0;
29033
- const reconcileCandidatePages = (initialPages, measuredTableRowHeightsByNodeIndex, measuredPageContentHeightsOverride) => reconcilePagesToTargetCountByScalingHeight({
30185
+ const reconcileCandidatePages = (initialPages, measuredTableRowHeightsByNodeIndex, measuredPageContentHeightsOverride) => reconcilePageCountCandidateToTargetCountByScalingHeight({
29034
30186
  initialPages,
29035
30187
  targetPageCount: resolvedTargetPageCount,
29036
30188
  maxDifference: hasTableInternalPageBreaks ? 2 : 3,
@@ -29056,27 +30208,38 @@ function DocxEditorViewer({
29056
30208
  }
29057
30209
  )
29058
30210
  });
29059
- let reconciledPages = reconcileCandidatePages(
30211
+ let reconciledCandidate = reconcileCandidatePages(
29060
30212
  estimatedPages,
29061
30213
  tableMeasuredRowHeightsForPagination,
29062
30214
  estimatedPagesUseMeasuredPageContentHeightsForRender ? measuredPageContentHeightByIndex : null
29063
30215
  );
30216
+ let reconciledPages = reconciledCandidate.pages;
29064
30217
  let reconciledPagesUseMeasuredPageContentHeightsForRender = estimatedPagesUseMeasuredPageContentHeightsForRender;
30218
+ let reconciledRenderMeasuredPageContentHeightsPxByPageIndex = reconciledPagesUseMeasuredPageContentHeightsForRender ? scaleMeasuredPageContentHeights(
30219
+ measuredPageContentHeightByIndex,
30220
+ reconciledCandidate.scale
30221
+ ) : void 0;
30222
+ let reconciledRenderPageContentHeightScale = reconciledPagesUseMeasuredPageContentHeightsForRender ? void 0 : reconciledCandidate.scale;
29065
30223
  if (!editor.canUndo && !editor.canRedo) {
29066
30224
  const pureEstimatedPages2 = buildEstimatedPages(void 0, null);
29067
- const pureReconciledPages = reconcileCandidatePages(
30225
+ const pureReconciledCandidate = reconcileCandidatePages(
29068
30226
  pureEstimatedPages2,
29069
30227
  void 0,
29070
30228
  null
29071
30229
  );
30230
+ const pureReconciledPages = pureReconciledCandidate.pages;
29072
30231
  if (Math.abs(pureReconciledPages.length - resolvedTargetPageCount) < Math.abs(reconciledPages.length - resolvedTargetPageCount)) {
29073
30232
  reconciledPages = pureReconciledPages;
29074
30233
  reconciledPagesUseMeasuredPageContentHeightsForRender = false;
30234
+ reconciledRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30235
+ reconciledRenderPageContentHeightScale = pureReconciledCandidate.scale;
29075
30236
  }
29076
30237
  }
29077
30238
  return {
29078
30239
  pages: reconciledPages,
29079
- useMeasuredPageContentHeightsForRender: reconciledPagesUseMeasuredPageContentHeightsForRender
30240
+ useMeasuredPageContentHeightsForRender: reconciledPagesUseMeasuredPageContentHeightsForRender,
30241
+ renderMeasuredPageContentHeightsPxByPageIndex: reconciledRenderMeasuredPageContentHeightsPxByPageIndex,
30242
+ renderPageContentHeightScale: reconciledRenderPageContentHeightScale
29080
30243
  };
29081
30244
  }, [
29082
30245
  editor.canRedo,
@@ -29095,12 +30258,17 @@ function DocxEditorViewer({
29095
30258
  isReadOnly,
29096
30259
  floatingMovePreview,
29097
30260
  dropCapMovePreview,
30261
+ deferInitialPaginationPaint,
29098
30262
  disableMeasuredImportPagination,
30263
+ hasMeasuredBodyFooterOverlap,
30264
+ initialPaginationBackgroundRefinementUnlocked,
29099
30265
  measuredPageContentHeightByIndex,
29100
30266
  tableMeasuredRowHeightsForPagination
29101
30267
  ]);
29102
30268
  const pageNodeSegmentsByPage = pageSegmentationPlan.pages;
29103
30269
  const useMeasuredPageContentHeightsForRender = pageSegmentationPlan.useMeasuredPageContentHeightsForRender;
30270
+ const renderMeasuredPageContentHeightsPxByPageIndex = pageSegmentationPlan.renderMeasuredPageContentHeightsPxByPageIndex;
30271
+ const renderPageContentHeightScale = pageSegmentationPlan.renderPageContentHeightScale;
29104
30272
  const pageNodeSegmentIdentityKeysByPage = React.useMemo(
29105
30273
  () => pageNodeSegmentsByPage.map(
29106
30274
  (pageSegments) => documentPageNodeSegmentsIdentityKey(pageSegments)
@@ -29316,6 +30484,32 @@ function DocxEditorViewer({
29316
30484
  };
29317
30485
  }, [editor.model.nodes, pageNodeSegmentsByPage]);
29318
30486
  const pageCount = pageNodeSegmentsByPage.length;
30487
+ const hasLargeTableLayoutSurface = React.useMemo(() => {
30488
+ let tableParagraphCount = 0;
30489
+ let tableCellCount = 0;
30490
+ let largestRowParagraphCount = 0;
30491
+ for (const node of editor.model.nodes) {
30492
+ if (node.type !== "table") {
30493
+ continue;
30494
+ }
30495
+ for (const row of node.rows) {
30496
+ let rowParagraphCount = 0;
30497
+ tableCellCount += row.cells.length;
30498
+ for (const cell of row.cells) {
30499
+ const paragraphCount = tableCellParagraphsRecursively(
30500
+ cell.nodes
30501
+ ).length;
30502
+ tableParagraphCount += paragraphCount;
30503
+ rowParagraphCount += paragraphCount;
30504
+ }
30505
+ largestRowParagraphCount = Math.max(
30506
+ largestRowParagraphCount,
30507
+ rowParagraphCount
30508
+ );
30509
+ }
30510
+ }
30511
+ return tableParagraphCount >= 1e3 || tableCellCount >= 240 || largestRowParagraphCount >= 100;
30512
+ }, [editor.model.nodes]);
29319
30513
  const hideDocumentUntilPaginationSettled = deferInitialPaginationPaint && !isInitialPaginationSettled;
29320
30514
  const estimateDocumentStackHeightPx = React.useCallback(
29321
30515
  (count) => {
@@ -29387,28 +30581,34 @@ function DocxEditorViewer({
29387
30581
  const hasExternalVisiblePageRange = Number.isFinite(Number(visiblePageRange?.startPageIndex)) || Number.isFinite(Number(visiblePageRange?.endPageIndex));
29388
30582
  const [deferInternalPageVirtualization, setDeferInternalPageVirtualization] = React.useState(false);
29389
30583
  const [internalVirtualScrollElement, setInternalVirtualScrollElement] = React.useState(null);
30584
+ const [observedVisiblePageRange, setObservedVisiblePageRange] = React.useState(void 0);
29390
30585
  const pageVirtualizationSettleDelayMs = Math.max(
29391
30586
  0,
29392
30587
  Math.round(
29393
30588
  Number.isFinite(pageVirtualization?.settleDelayMs) ? pageVirtualization?.settleDelayMs : DEFAULT_PAGE_VIRTUALIZATION_SETTLE_DELAY_MS
29394
30589
  )
29395
30590
  );
29396
- const pageVirtualizationOverscan = Math.max(
30591
+ const rawPageVirtualizationOverscan = Math.max(
29397
30592
  0,
29398
30593
  Math.round(
29399
30594
  Number.isFinite(pageVirtualization?.overscan) ? pageVirtualization?.overscan : DEFAULT_PAGE_VIRTUALIZATION_OVERSCAN
29400
30595
  )
29401
30596
  );
30597
+ const pageVirtualizationOverscan = hasLargeTableLayoutSurface && !Number.isFinite(pageVirtualization?.overscan) ? LARGE_TABLE_PAGE_VIRTUALIZATION_OVERSCAN : rawPageVirtualizationOverscan;
29402
30598
  const webdriverActive = typeof navigator !== "undefined" && navigator.webdriver === true;
29403
30599
  const internalPageVirtualizationRequested = pageVirtualization?.enabled !== false && !hasExternalVisiblePageRange && !hideDocumentUntilPaginationSettled && isInitialPaginationSettled && !deferInternalPageVirtualization && !webdriverActive && pageCount > 1;
29404
30600
  React.useEffect(() => {
29405
- setDeferInternalPageVirtualization(true);
29406
- }, [editor.documentLoadNonce]);
30601
+ setDeferInternalPageVirtualization(!hasLargeTableLayoutSurface);
30602
+ }, [editor.documentLoadNonce, hasLargeTableLayoutSurface]);
29407
30603
  React.useEffect(() => {
29408
30604
  if (typeof window === "undefined" || webdriverActive || pageCount <= 1) {
29409
30605
  setDeferInternalPageVirtualization(true);
29410
30606
  return;
29411
30607
  }
30608
+ if (hasLargeTableLayoutSurface) {
30609
+ setDeferInternalPageVirtualization(false);
30610
+ return;
30611
+ }
29412
30612
  const timeoutId = window.setTimeout(() => {
29413
30613
  setDeferInternalPageVirtualization(false);
29414
30614
  }, pageVirtualizationSettleDelayMs);
@@ -29417,6 +30617,7 @@ function DocxEditorViewer({
29417
30617
  };
29418
30618
  }, [
29419
30619
  editor.documentLoadNonce,
30620
+ hasLargeTableLayoutSurface,
29420
30621
  pageCount,
29421
30622
  pageVirtualizationSettleDelayMs,
29422
30623
  webdriverActive
@@ -29430,15 +30631,30 @@ function DocxEditorViewer({
29430
30631
  );
29431
30632
  }, [editor.documentLoadNonce, pageCount, trackedChangesEnabled]);
29432
30633
  const internalPageVirtualizationEnabled = internalPageVirtualizationRequested && internalVirtualScrollElement !== null;
29433
- const internalPageVirtualizer = useVirtualizer({
29434
- count: Math.max(1, pageCount),
29435
- getScrollElement: () => internalPageVirtualizationEnabled ? internalVirtualScrollElement : null,
29436
- estimateSize: (pageIndex) => {
30634
+ const internalPageVirtualizationPending = typeof window !== "undefined" && internalPageVirtualizationRequested && internalVirtualScrollElement === null;
30635
+ const internalVirtualScrollUsesWindow = typeof document !== "undefined" && internalVirtualScrollElement !== null && (internalVirtualScrollElement === document.scrollingElement || internalVirtualScrollElement === document.documentElement || internalVirtualScrollElement === document.body);
30636
+ const internalElementPageVirtualizationEnabled = internalPageVirtualizationEnabled && !internalVirtualScrollUsesWindow;
30637
+ const internalWindowPageVirtualizationEnabled = internalPageVirtualizationEnabled && internalVirtualScrollUsesWindow;
30638
+ const estimateVirtualPageSize = React.useCallback(
30639
+ (pageIndex) => {
29437
30640
  const pageLayout = pageSectionInfoByIndex[pageIndex]?.layout ?? documentLayout;
29438
30641
  return Math.max(1, pageLayout.pageHeightPx + DOC_PAGE_BREAK_GAP);
29439
30642
  },
30643
+ [documentLayout, pageSectionInfoByIndex]
30644
+ );
30645
+ const internalElementPageVirtualizer = useVirtualizer({
30646
+ count: Math.max(1, pageCount),
30647
+ getScrollElement: () => internalElementPageVirtualizationEnabled ? internalVirtualScrollElement : null,
30648
+ estimateSize: estimateVirtualPageSize,
30649
+ overscan: pageVirtualizationOverscan
30650
+ });
30651
+ const internalWindowPageVirtualizer = useWindowVirtualizer({
30652
+ count: Math.max(1, pageCount),
30653
+ getScrollElement: () => internalWindowPageVirtualizationEnabled && typeof window !== "undefined" ? window : null,
30654
+ estimateSize: estimateVirtualPageSize,
29440
30655
  overscan: pageVirtualizationOverscan
29441
30656
  });
30657
+ const internalPageVirtualizer = internalVirtualScrollUsesWindow ? internalWindowPageVirtualizer : internalElementPageVirtualizer;
29442
30658
  const internalVirtualItems = internalPageVirtualizer.getVirtualItems();
29443
30659
  const internalVisiblePageRange = React.useMemo(() => {
29444
30660
  if (!internalPageVirtualizationEnabled) {
@@ -29473,7 +30689,166 @@ function DocxEditorViewer({
29473
30689
  endPageIndex
29474
30690
  };
29475
30691
  }, [internalPageVirtualizationEnabled, internalVirtualItems, pageCount]);
29476
- const effectiveVisiblePageRange = visiblePageRange ?? internalVisiblePageRange;
30692
+ const internalRenderVisiblePageRange = React.useMemo(() => {
30693
+ if (!internalVisiblePageRange) {
30694
+ return void 0;
30695
+ }
30696
+ if (!hasLargeTableLayoutSurface || Number.isFinite(pageVirtualization?.overscan)) {
30697
+ return internalVisiblePageRange;
30698
+ }
30699
+ const scrollDirection = internalPageVirtualizer.scrollDirection;
30700
+ const renderPreviousPage = scrollDirection !== "backward";
30701
+ const renderNextPage = scrollDirection === "backward";
30702
+ const startPageIndex = clampNumber(
30703
+ internalVisiblePageRange.startPageIndex - (renderPreviousPage ? LARGE_TABLE_PAGE_ADJACENT_RENDER_COUNT : 0),
30704
+ 0,
30705
+ pageCount - 1
30706
+ );
30707
+ const endPageIndex = clampNumber(
30708
+ internalVisiblePageRange.endPageIndex + (renderNextPage ? LARGE_TABLE_PAGE_ADJACENT_RENDER_COUNT : 0),
30709
+ startPageIndex,
30710
+ pageCount - 1
30711
+ );
30712
+ return {
30713
+ startPageIndex,
30714
+ endPageIndex
30715
+ };
30716
+ }, [
30717
+ hasLargeTableLayoutSurface,
30718
+ internalPageVirtualizer.scrollDirection,
30719
+ internalVisiblePageRange,
30720
+ pageCount,
30721
+ pageVirtualization?.overscan
30722
+ ]);
30723
+ React.useLayoutEffect(() => {
30724
+ if (!internalPageVirtualizationEnabled || !internalVirtualScrollElement || internalVirtualItems.length > 0 || typeof window === "undefined") {
30725
+ setObservedVisiblePageRange(
30726
+ (current) => current === void 0 ? current : void 0
30727
+ );
30728
+ return;
30729
+ }
30730
+ const rootElement = viewerRootRef.current;
30731
+ if (!rootElement) {
30732
+ setObservedVisiblePageRange(
30733
+ (current) => current === void 0 ? current : void 0
30734
+ );
30735
+ return;
30736
+ }
30737
+ let frameId = null;
30738
+ const syncVisiblePageRange = () => {
30739
+ frameId = null;
30740
+ const viewportRect = internalVirtualScrollUsesWindow ? {
30741
+ top: 0,
30742
+ bottom: window.innerHeight
30743
+ } : internalVirtualScrollElement.getBoundingClientRect();
30744
+ const pageWrappers = rootElement.querySelectorAll(
30745
+ '[data-docx-page-wrapper="true"][data-index]'
30746
+ );
30747
+ let firstVisiblePageIndex;
30748
+ let lastVisiblePageIndex;
30749
+ for (const pageWrapper of pageWrappers) {
30750
+ const rawPageIndex = pageWrapper.getAttribute("data-index");
30751
+ const pageIndex = Number.parseInt(rawPageIndex ?? "", 10);
30752
+ if (!Number.isFinite(pageIndex)) {
30753
+ continue;
30754
+ }
30755
+ const pageRect = pageWrapper.getBoundingClientRect();
30756
+ if (pageRect.bottom <= viewportRect.top) {
30757
+ continue;
30758
+ }
30759
+ if (pageRect.top >= viewportRect.bottom) {
30760
+ if (firstVisiblePageIndex !== void 0) {
30761
+ break;
30762
+ }
30763
+ continue;
30764
+ }
30765
+ if (firstVisiblePageIndex === void 0) {
30766
+ firstVisiblePageIndex = pageIndex;
30767
+ }
30768
+ lastVisiblePageIndex = pageIndex;
30769
+ }
30770
+ if (firstVisiblePageIndex === void 0 || lastVisiblePageIndex === void 0) {
30771
+ setObservedVisiblePageRange(
30772
+ (current) => current === void 0 ? current : void 0
30773
+ );
30774
+ return;
30775
+ }
30776
+ const startPageIndex = clampNumber(
30777
+ firstVisiblePageIndex - pageVirtualizationOverscan,
30778
+ 0,
30779
+ pageCount - 1
30780
+ );
30781
+ const endPageIndex = clampNumber(
30782
+ lastVisiblePageIndex + pageVirtualizationOverscan,
30783
+ startPageIndex,
30784
+ pageCount - 1
30785
+ );
30786
+ setObservedVisiblePageRange((current) => {
30787
+ if (current?.startPageIndex === startPageIndex && current?.endPageIndex === endPageIndex) {
30788
+ return current;
30789
+ }
30790
+ return {
30791
+ startPageIndex,
30792
+ endPageIndex
30793
+ };
30794
+ });
30795
+ };
30796
+ const scheduleVisiblePageRangeSync = () => {
30797
+ if (frameId !== null) {
30798
+ return;
30799
+ }
30800
+ frameId = window.requestAnimationFrame(syncVisiblePageRange);
30801
+ };
30802
+ const resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(() => {
30803
+ scheduleVisiblePageRangeSync();
30804
+ }) : void 0;
30805
+ if (!internalVirtualScrollUsesWindow) {
30806
+ resizeObserver?.observe(internalVirtualScrollElement);
30807
+ }
30808
+ resizeObserver?.observe(rootElement);
30809
+ if (internalVirtualScrollUsesWindow) {
30810
+ window.addEventListener("scroll", scheduleVisiblePageRangeSync, {
30811
+ passive: true
30812
+ });
30813
+ } else {
30814
+ internalVirtualScrollElement.addEventListener(
30815
+ "scroll",
30816
+ scheduleVisiblePageRangeSync,
30817
+ { passive: true }
30818
+ );
30819
+ }
30820
+ window.addEventListener("resize", scheduleVisiblePageRangeSync);
30821
+ scheduleVisiblePageRangeSync();
30822
+ return () => {
30823
+ if (internalVirtualScrollUsesWindow) {
30824
+ window.removeEventListener("scroll", scheduleVisiblePageRangeSync);
30825
+ } else {
30826
+ internalVirtualScrollElement.removeEventListener(
30827
+ "scroll",
30828
+ scheduleVisiblePageRangeSync
30829
+ );
30830
+ }
30831
+ window.removeEventListener("resize", scheduleVisiblePageRangeSync);
30832
+ resizeObserver?.disconnect();
30833
+ if (frameId !== null) {
30834
+ window.cancelAnimationFrame(frameId);
30835
+ }
30836
+ };
30837
+ }, [
30838
+ internalPageVirtualizationEnabled,
30839
+ internalVirtualItems.length,
30840
+ internalVirtualScrollElement,
30841
+ internalVirtualScrollUsesWindow,
30842
+ pageCount,
30843
+ pageVirtualizationOverscan
30844
+ ]);
30845
+ const effectiveVisiblePageRange = visiblePageRange ?? internalRenderVisiblePageRange ?? observedVisiblePageRange ?? (internalPageVirtualizationPending ? {
30846
+ startPageIndex: 0,
30847
+ endPageIndex: Math.min(
30848
+ pageCount - 1,
30849
+ Math.max(0, pageVirtualizationOverscan)
30850
+ )
30851
+ } : void 0);
29477
30852
  const normalizedVisiblePageRange = React.useMemo(() => {
29478
30853
  if (pageCount <= 0) {
29479
30854
  return {
@@ -29501,7 +30876,8 @@ function DocxEditorViewer({
29501
30876
  pageCount
29502
30877
  ]);
29503
30878
  const initialPremeasureStartPageIndex = hasExternalVisiblePageRange ? normalizedVisiblePageRange.startPageIndex : 0;
29504
- const initialPremeasureEndPageIndex = hasExternalVisiblePageRange ? normalizedVisiblePageRange.endPageIndex : Math.min(pageCount - 1, INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT - 1);
30879
+ const initialPremeasurePageLimit = hasLargeTableLayoutSurface ? Math.min(2, INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT) : INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT;
30880
+ const initialPremeasureEndPageIndex = hasExternalVisiblePageRange ? normalizedVisiblePageRange.endPageIndex : Math.min(pageCount - 1, initialPremeasurePageLimit - 1);
29505
30881
  const measureAllPagesBeforeInitialReveal = hideDocumentUntilPaginationSettled && pageCount > 0 && initialPremeasureStartPageIndex === 0 && initialPremeasureEndPageIndex >= pageCount - 1;
29506
30882
  const visiblePageStartIndex = measureAllPagesBeforeInitialReveal ? 0 : hideDocumentUntilPaginationSettled ? initialPremeasureStartPageIndex : normalizedVisiblePageRange.startPageIndex;
29507
30883
  const visiblePageEndIndex = measureAllPagesBeforeInitialReveal ? pageCount - 1 : hideDocumentUntilPaginationSettled ? initialPremeasureEndPageIndex : normalizedVisiblePageRange.endPageIndex;
@@ -29515,20 +30891,64 @@ function DocxEditorViewer({
29515
30891
  }
29516
30892
  return indexes;
29517
30893
  }, [pageCount, visiblePageEndIndex, visiblePageStartIndex]);
30894
+ const visibleTableRowIndexesByNodeIndex = React.useMemo(() => {
30895
+ const rowsByNodeIndex = /* @__PURE__ */ new Map();
30896
+ const addRowIndex = (nodeIndex, rowIndex) => {
30897
+ const tableNode = editor.model.nodes[nodeIndex];
30898
+ if (!tableNode || tableNode.type !== "table" || rowIndex < 0 || rowIndex >= tableNode.rows.length) {
30899
+ return;
30900
+ }
30901
+ const existing = rowsByNodeIndex.get(nodeIndex);
30902
+ if (existing) {
30903
+ existing.add(rowIndex);
30904
+ } else {
30905
+ rowsByNodeIndex.set(nodeIndex, /* @__PURE__ */ new Set([rowIndex]));
30906
+ }
30907
+ };
30908
+ for (const pageIndex of visiblePageIndexes) {
30909
+ for (const segment of pageNodeSegmentsByPage[pageIndex] ?? []) {
30910
+ const tableNode = editor.model.nodes[segment.nodeIndex];
30911
+ if (!tableNode || tableNode.type !== "table") {
30912
+ continue;
30913
+ }
30914
+ if (segment.tableRowSlice) {
30915
+ addRowIndex(segment.nodeIndex, segment.tableRowSlice.rowIndex);
30916
+ continue;
30917
+ }
30918
+ if (segment.tableRowRange) {
30919
+ for (let rowIndex = segment.tableRowRange.startRowIndex; rowIndex < segment.tableRowRange.endRowIndex; rowIndex += 1) {
30920
+ addRowIndex(segment.nodeIndex, rowIndex);
30921
+ }
30922
+ continue;
30923
+ }
30924
+ for (let rowIndex = 0; rowIndex < tableNode.rows.length; rowIndex += 1) {
30925
+ addRowIndex(segment.nodeIndex, rowIndex);
30926
+ }
30927
+ }
30928
+ }
30929
+ return rowsByNodeIndex;
30930
+ }, [editor.model.nodes, pageNodeSegmentsByPage, visiblePageIndexes]);
29518
30931
  const paginationMeasurementEnabled = hideDocumentUntilPaginationSettled || postImportPaginationUnlocked;
29519
30932
  const visiblePagesHavePendingPaginationMeasurements = React.useMemo(() => {
29520
30933
  if (pageCount === 0) {
29521
30934
  return false;
29522
30935
  }
29523
30936
  for (const pageIndex of visiblePageIndexes) {
29524
- if (!Number.isFinite(measuredPageContentHeightByIndex[pageIndex])) {
30937
+ const pageSegments = pageNodeSegmentsByPage[pageIndex] ?? [];
30938
+ const pageContainsTableRowSlice = pageSegments.some(
30939
+ (segment) => Boolean(segment.tableRowSlice)
30940
+ );
30941
+ if (!Number.isFinite(measuredPageContentHeightByIndex[pageIndex]) && !(hasLargeTableLayoutSurface && pageContainsTableRowSlice)) {
29525
30942
  return true;
29526
30943
  }
29527
- for (const segment of pageNodeSegmentsByPage[pageIndex] ?? []) {
30944
+ for (const segment of pageSegments) {
29528
30945
  const tableNode = editor.model.nodes[segment.nodeIndex];
29529
30946
  if (!tableNode || tableNode.type !== "table") {
29530
30947
  continue;
29531
30948
  }
30949
+ if (segment.tableRowSlice) {
30950
+ continue;
30951
+ }
29532
30952
  const measuredHeights = tableMeasuredRowHeights[segment.nodeIndex];
29533
30953
  if (!measuredHeights || measuredHeights.length !== tableNode.rows.length) {
29534
30954
  return true;
@@ -29538,6 +30958,7 @@ function DocxEditorViewer({
29538
30958
  return false;
29539
30959
  }, [
29540
30960
  editor.model.nodes,
30961
+ hasLargeTableLayoutSurface,
29541
30962
  measuredPageContentHeightByIndex,
29542
30963
  pageCount,
29543
30964
  pageNodeSegmentsByPage,
@@ -29609,7 +31030,13 @@ function DocxEditorViewer({
29609
31030
  rootElement.querySelectorAll(
29610
31031
  '[data-docx-page-wrapper="true"][data-index]'
29611
31032
  )
29612
- );
31033
+ ).filter((element) => {
31034
+ const pageIndex = Number.parseInt(
31035
+ element.getAttribute("data-index") ?? "",
31036
+ 10
31037
+ );
31038
+ return Number.isFinite(pageIndex) && pageIndex >= visiblePageStartIndex && pageIndex <= visiblePageEndIndex;
31039
+ });
29613
31040
  const nextElements = new Set(pageWrappers);
29614
31041
  observedElements.forEach((element) => {
29615
31042
  if (!nextElements.has(element)) {
@@ -29645,7 +31072,9 @@ function DocxEditorViewer({
29645
31072
  internalPageVirtualizationEnabled,
29646
31073
  internalPageVirtualizer,
29647
31074
  internalVirtualScrollElement,
29648
- pageCount
31075
+ pageCount,
31076
+ visiblePageEndIndex,
31077
+ visiblePageStartIndex
29649
31078
  ]);
29650
31079
  React.useEffect(() => {
29651
31080
  if (!internalPageVirtualizationEnabled) {
@@ -30158,11 +31587,18 @@ function DocxEditorViewer({
30158
31587
  const nextMeasuredPageDiagnostics = pageNodeSegmentsByPage.map(
30159
31588
  (_, pageIndex) => {
30160
31589
  const pageLayout = pageSectionInfoByIndex[pageIndex]?.layout ?? documentLayout;
30161
- const pageElement = pageElementsRef.current.get(pageIndex);
30162
31590
  const fallbackHeightPx = Math.max(
30163
31591
  120,
30164
31592
  pageLayout.pageHeightPx - pageLayout.marginsPx.top - pageLayout.marginsPx.bottom
30165
31593
  );
31594
+ const pageIsVisible = pageIndex >= visiblePageStartIndex && pageIndex <= visiblePageEndIndex;
31595
+ if (!pageIsVisible) {
31596
+ return {
31597
+ heightPx: measuredPageContentHeightByIndex?.[pageIndex] ?? fallbackHeightPx,
31598
+ bodyOverrunsFooter: false
31599
+ };
31600
+ }
31601
+ const pageElement = pageElementsRef.current.get(pageIndex);
30166
31602
  if (!pageElement) {
30167
31603
  return {
30168
31604
  heightPx: fallbackHeightPx,
@@ -30174,7 +31610,9 @@ function DocxEditorViewer({
30174
31610
  const footerElement = pageFooterElementsRef.current.get(pageIndex);
30175
31611
  const headerHeightPx = headerElement ? Math.max(
30176
31612
  0,
30177
- Math.round(headerElement.getBoundingClientRect().height / zoomScale)
31613
+ Math.round(
31614
+ headerElement.getBoundingClientRect().height / zoomScale
31615
+ )
30178
31616
  ) : 0;
30179
31617
  const docxFooterTopPx = resolveFooterNodesFloatingBoundaryTopPx(
30180
31618
  pageHeaderAndFooterNodes[pageIndex]?.footerNodes ?? [],
@@ -30240,7 +31678,9 @@ function DocxEditorViewer({
30240
31678
  bottomPx: rect.bottom,
30241
31679
  widthPx: rect.width,
30242
31680
  heightPx: rect.height,
30243
- ignore: !element.isConnected || Boolean(element.closest("[data-docx-image-location]")) || Boolean(
31681
+ ignore: !element.isConnected || Boolean(
31682
+ element.closest("[data-docx-image-location]")
31683
+ ) || Boolean(
30244
31684
  element.closest(
30245
31685
  `[${PAGE_CONTENT_MEASUREMENT_IGNORE_ATTRIBUTE}="true"]`
30246
31686
  )
@@ -30270,7 +31710,31 @@ function DocxEditorViewer({
30270
31710
  const nextMeasuredHeights = nextMeasuredPageDiagnostics.map(
30271
31711
  (diagnostics) => diagnostics.heightPx
30272
31712
  );
31713
+ const overlappingPageIndexes = nextMeasuredPageDiagnostics.reduce(
31714
+ (indexes, diagnostics, pageIndex) => {
31715
+ if (diagnostics.bodyOverrunsFooter) {
31716
+ indexes.push(pageIndex);
31717
+ }
31718
+ return indexes;
31719
+ },
31720
+ []
31721
+ );
31722
+ const nextMeasuredBodyFooterOverlapLatchState = resolveMeasuredBodyFooterOverlapLatchState({
31723
+ pageCount,
31724
+ targetPageCount: editor.model.metadata.documentPageCount,
31725
+ overlappingPageIndexes,
31726
+ previousSignature: measuredBodyFooterOverlapCandidateRef.current.signature,
31727
+ previousConsecutivePasses: measuredBodyFooterOverlapCandidateRef.current.consecutivePasses,
31728
+ stabilityThreshold: MEASURED_BODY_FOOTER_OVERLAP_STABILITY_THRESHOLD
31729
+ });
31730
+ measuredBodyFooterOverlapCandidateRef.current = {
31731
+ signature: nextMeasuredBodyFooterOverlapLatchState.signature,
31732
+ consecutivePasses: nextMeasuredBodyFooterOverlapLatchState.consecutivePasses
31733
+ };
30273
31734
  const frameId = window.requestAnimationFrame(() => {
31735
+ if (nextMeasuredBodyFooterOverlapLatchState.shouldLatch) {
31736
+ setHasMeasuredBodyFooterOverlap(true);
31737
+ }
30274
31738
  setMeasuredPageContentHeightByIndex((current) => {
30275
31739
  const stabilizedHeights = stabilizeMeasuredPageContentHeights(
30276
31740
  current,
@@ -30323,10 +31787,13 @@ function DocxEditorViewer({
30323
31787
  paginationMeasurementEnabled,
30324
31788
  paginationMeasurementEpoch,
30325
31789
  pageCount,
31790
+ editor.model.metadata.documentPageCount,
30326
31791
  pageNodeSegmentsByPage,
30327
31792
  pageNodeSegmentIdentityKeysByPage,
30328
31793
  pageSectionInfoByIndex,
30329
- pageHeaderAndFooterNodes
31794
+ pageHeaderAndFooterNodes,
31795
+ visiblePageEndIndex,
31796
+ visiblePageStartIndex
30330
31797
  ]);
30331
31798
  React.useEffect(() => {
30332
31799
  if (!deferInitialPaginationPaint || isInitialPaginationSettled || disableMeasuredImportPagination) {
@@ -30355,6 +31822,27 @@ function DocxEditorViewer({
30355
31822
  isInitialPaginationSettled,
30356
31823
  pageCount
30357
31824
  ]);
31825
+ React.useEffect(() => {
31826
+ if (!deferInitialPaginationPaint || !isInitialPaginationSettled || initialPaginationBackgroundRefinementUnlocked) {
31827
+ return;
31828
+ }
31829
+ if (typeof window === "undefined") {
31830
+ setInitialPaginationBackgroundRefinementUnlocked(true);
31831
+ return;
31832
+ }
31833
+ const timeoutId = window.setTimeout(() => {
31834
+ React.startTransition(() => {
31835
+ setInitialPaginationBackgroundRefinementUnlocked(true);
31836
+ });
31837
+ }, INITIAL_PAGINATION_BACKGROUND_REFINEMENT_DELAY_MS);
31838
+ return () => {
31839
+ window.clearTimeout(timeoutId);
31840
+ };
31841
+ }, [
31842
+ deferInitialPaginationPaint,
31843
+ initialPaginationBackgroundRefinementUnlocked,
31844
+ isInitialPaginationSettled
31845
+ ]);
30358
31846
  React.useEffect(() => {
30359
31847
  if (!deferInitialPaginationPaint || isInitialPaginationSettled) {
30360
31848
  return;
@@ -34573,10 +36061,14 @@ function DocxEditorViewer({
34573
36061
  if (node.type !== "table") {
34574
36062
  return;
34575
36063
  }
36064
+ const visibleRowIndexes = visibleTableRowIndexesByNodeIndex.get(nodeIndex);
36065
+ if (!visibleRowIndexes || visibleRowIndexes.size === 0) {
36066
+ return;
36067
+ }
34576
36068
  const measuredByRowIndex = /* @__PURE__ */ new Map();
34577
36069
  const recordMeasuredRow = (rowIndex, rowHeightPx) => {
34578
36070
  const normalizedRowIndex = Math.max(0, Math.round(rowIndex));
34579
- if (normalizedRowIndex >= node.rows.length) {
36071
+ if (normalizedRowIndex >= node.rows.length || !visibleRowIndexes.has(normalizedRowIndex)) {
34580
36072
  return;
34581
36073
  }
34582
36074
  const normalizedHeight = normalizeMeasuredTableRowHeightPx(rowHeightPx);
@@ -34609,7 +36101,8 @@ function DocxEditorViewer({
34609
36101
  );
34610
36102
  });
34611
36103
  }
34612
- const rowCells = document.querySelectorAll(
36104
+ const measurementRoot = viewerRootRef.current ?? document;
36105
+ const rowCells = measurementRoot.querySelectorAll(
34613
36106
  `[data-docx-table-cell='true'][data-docx-table-index='${nodeIndex}'][data-docx-row-index]`
34614
36107
  );
34615
36108
  rowCells.forEach((cellElement) => {
@@ -34640,7 +36133,8 @@ function DocxEditorViewer({
34640
36133
  node,
34641
36134
  pageContentWidthPxByNodeIndex.get(nodeIndex),
34642
36135
  editor.model.metadata.numberingDefinitions,
34643
- docGridLinePitchPxByNodeIndex.get(nodeIndex)
36136
+ docGridLinePitchPxByNodeIndex.get(nodeIndex),
36137
+ pageContentHeightPxByNodeIndex.get(nodeIndex)
34644
36138
  );
34645
36139
  const previousMeasuredRowHeights = tableMeasuredRowHeights[nodeIndex];
34646
36140
  const measuredHeights = node.rows.map((_, rowIndex) => {
@@ -34706,8 +36200,7 @@ function DocxEditorViewer({
34706
36200
  tableColumnWidths,
34707
36201
  tableRowHeights,
34708
36202
  tableDraftLayoutEpoch,
34709
- visiblePageEndIndex,
34710
- visiblePageStartIndex
36203
+ visibleTableRowIndexesByNodeIndex
34711
36204
  ]);
34712
36205
  const normalizeResizableHeights = React.useCallback(
34713
36206
  (rowHeights) => {
@@ -36167,6 +37660,29 @@ function DocxEditorViewer({
36167
37660
  `${keyPrefix}-fragment-image-${lineIndex}-${run.key}-${overlapStart}`
36168
37661
  );
36169
37662
  }
37663
+ if (run.kind === "tab" && Number.isFinite(run.tabWidthPx)) {
37664
+ const overlapRatio = run.endOffset > run.startOffset ? (overlapEnd - overlapStart) / (run.endOffset - run.startOffset) : 1;
37665
+ const tabWidthPx = Math.max(
37666
+ 1,
37667
+ Math.round(run.tabWidthPx * overlapRatio)
37668
+ );
37669
+ return /* @__PURE__ */ jsx(
37670
+ "span",
37671
+ {
37672
+ "data-docx-tab-char": "true",
37673
+ style: {
37674
+ ...runStyleToCss(run.style, documentContentTheme),
37675
+ display: "inline-block",
37676
+ width: tabWidthPx,
37677
+ minWidth: tabWidthPx,
37678
+ whiteSpace: "pre",
37679
+ lineHeight: "1em"
37680
+ },
37681
+ children: "\xA0"
37682
+ },
37683
+ `${keyPrefix}-fragment-tab-${lineIndex}-${run.key}-${overlapStart}`
37684
+ );
37685
+ }
36170
37686
  const slice = run.text.slice(
36171
37687
  overlapStart - run.startOffset,
36172
37688
  overlapEnd - run.startOffset
@@ -39002,6 +40518,488 @@ function DocxEditorViewer({
39002
40518
  boxSizing: "border-box",
39003
40519
  overflow: floatingMovePreview || dropCapMovePreview ? "visible" : "clip"
39004
40520
  };
40521
+ const tableCellParagraphSliceLayoutCacheRef = React.useRef(
40522
+ /* @__PURE__ */ new Map()
40523
+ );
40524
+ const tableCellParagraphFlowLayoutCacheRef = React.useRef(
40525
+ /* @__PURE__ */ new Map()
40526
+ );
40527
+ const tableCellParagraphSlicePlanCacheRef = React.useRef(
40528
+ /* @__PURE__ */ new Map()
40529
+ );
40530
+ const tableCellParagraphSliceSignatureCacheRef = React.useRef(
40531
+ /* @__PURE__ */ new WeakMap()
40532
+ );
40533
+ React.useEffect(() => {
40534
+ tableCellParagraphSliceLayoutCacheRef.current.clear();
40535
+ tableCellParagraphFlowLayoutCacheRef.current.clear();
40536
+ tableCellParagraphSlicePlanCacheRef.current.clear();
40537
+ tableCellParagraphSliceSignatureCacheRef.current = /* @__PURE__ */ new WeakMap();
40538
+ }, [paragraphStructureEpoch]);
40539
+ const resolveTableCellParagraphSliceSignature = (cell) => {
40540
+ const cellKey = cell;
40541
+ const cached = tableCellParagraphSliceSignatureCacheRef.current.get(cellKey);
40542
+ if (cached) {
40543
+ return cached;
40544
+ }
40545
+ const signature = [
40546
+ JSON.stringify(cell.style ?? null),
40547
+ ...cell.nodes.map(
40548
+ (paragraph, paragraphIndex) => isParagraphCellContentNode(paragraph) ? `${paragraphIndex}:${paragraph.sourceXml ?? paragraphText(paragraph)}` : `${paragraphIndex}:${paragraph.type}`
40549
+ )
40550
+ ].join("");
40551
+ tableCellParagraphSliceSignatureCacheRef.current.set(cellKey, signature);
40552
+ return signature;
40553
+ };
40554
+ const resolveTableCellParagraphSlicePlans = (params) => {
40555
+ const {
40556
+ cell,
40557
+ rowHeightPx,
40558
+ sliceStartPx,
40559
+ sliceHeightPx,
40560
+ cellContentWidthPx,
40561
+ tableCellMarginTwips,
40562
+ applyWordTableDefaults,
40563
+ docGridLinePitchPx
40564
+ } = params;
40565
+ if (!cell.nodes.every(isParagraphCellContentNode)) {
40566
+ return void 0;
40567
+ }
40568
+ const numberingDefinitions = editor.model.metadata.numberingDefinitions;
40569
+ const cellSignature = resolveTableCellParagraphSliceSignature(cell);
40570
+ const flowLayoutCacheKey = [
40571
+ cellContentWidthPx,
40572
+ JSON.stringify(tableCellMarginTwips ?? null),
40573
+ applyWordTableDefaults ? 1 : 0,
40574
+ docGridLinePitchPx ?? 0,
40575
+ cellSignature
40576
+ ].join(":");
40577
+ let flowLayout = tableCellParagraphFlowLayoutCacheRef.current.get(flowLayoutCacheKey);
40578
+ if (!flowLayout) {
40579
+ const contentHeightPx = estimateTableCellContentHeightPx(
40580
+ cell.nodes,
40581
+ cellContentWidthPx,
40582
+ numberingDefinitions,
40583
+ applyWordTableDefaults,
40584
+ docGridLinePitchPx
40585
+ );
40586
+ const paddingPx = resolveTableSpacingPaddingPx(
40587
+ mergeTableSpacing(tableCellMarginTwips, cell.style?.marginTwips)
40588
+ );
40589
+ let paragraphTopPx = paddingPx.top;
40590
+ const entries = [];
40591
+ for (let paragraphIndex = 0; paragraphIndex < cell.nodes.length; paragraphIndex += 1) {
40592
+ const paragraph = cell.nodes[paragraphIndex];
40593
+ if (!paragraph) {
40594
+ continue;
40595
+ }
40596
+ const disableDocGridSnap = paragraphDocGridSnapState(paragraph) === "disable";
40597
+ const layoutCacheKey2 = `${cellContentWidthPx}:${applyWordTableDefaults ? 1 : 0}:${docGridLinePitchPx ?? 0}:${paragraphIndex}:${paragraph.sourceXml ?? paragraphText(paragraph)}`;
40598
+ let layoutEntry = tableCellParagraphSliceLayoutCacheRef.current.get(layoutCacheKey2);
40599
+ if (!layoutEntry) {
40600
+ const paragraphForLayout = wordLikeTableCellParagraph(
40601
+ paragraph,
40602
+ applyWordTableDefaults
40603
+ );
40604
+ const paragraphHeightPx2 = estimateParagraphHeightPx(
40605
+ paragraphForLayout,
40606
+ cellContentWidthPx,
40607
+ numberingDefinitions,
40608
+ docGridLinePitchPx,
40609
+ disableDocGridSnap
40610
+ );
40611
+ const suppressTopSpacing = paragraphIndex === 0 && suppressFirstTableCellParagraphTopSpacing(paragraph);
40612
+ const beforeSpacingPx = suppressTopSpacing ? 0 : twipsToPixels(paragraphForLayout.style?.spacing?.beforeTwips) ?? 0;
40613
+ const topBorderInsetPx = paragraphBorderInsetPx(
40614
+ paragraphForLayout.style?.borders?.top
40615
+ );
40616
+ const lineHeightPx = Math.max(
40617
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
40618
+ estimateParagraphLineHeightPx(
40619
+ paragraphForLayout,
40620
+ docGridLinePitchPx,
40621
+ disableDocGridSnap
40622
+ )
40623
+ );
40624
+ const pretextSource = buildParagraphPretextLayoutSource(
40625
+ paragraphForLayout,
40626
+ {
40627
+ allowExplicitLineBreakText: true,
40628
+ expandTabsForLayout: true
40629
+ }
40630
+ );
40631
+ const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
40632
+ paragraphForLayout,
40633
+ cellContentWidthPx,
40634
+ numberingDefinitions
40635
+ );
40636
+ const pretextLayout = pretextSource ? layoutParagraphPretextSource(
40637
+ paragraphForLayout,
40638
+ pretextSource,
40639
+ paragraphTextWidthPx,
40640
+ lineHeightPx,
40641
+ []
40642
+ ) : void 0;
40643
+ const totalLineCount = Math.max(
40644
+ 1,
40645
+ pretextLayout?.lineCount ?? paragraphLineCountWithinWidth(
40646
+ paragraphForLayout,
40647
+ cellContentWidthPx,
40648
+ numberingDefinitions
40649
+ )
40650
+ );
40651
+ layoutEntry = {
40652
+ paragraphForLayout,
40653
+ paragraphHeightPx: paragraphHeightPx2,
40654
+ textTopOffsetPx: beforeSpacingPx + topBorderInsetPx,
40655
+ lineHeightPx,
40656
+ lineTopOffsetsPx: pretextLayout ? pretextLayout.lines.map(
40657
+ (line) => Math.max(0, Math.round(line.y))
40658
+ ) : Array.from(
40659
+ { length: totalLineCount },
40660
+ (_, lineIndex) => lineIndex * lineHeightPx
40661
+ ),
40662
+ pretextSource: pretextSource ?? void 0,
40663
+ pretextLayout: pretextLayout ?? void 0
40664
+ };
40665
+ tableCellParagraphSliceLayoutCacheRef.current.set(
40666
+ layoutCacheKey2,
40667
+ layoutEntry
40668
+ );
40669
+ }
40670
+ const paragraphHeightPx = layoutEntry.paragraphHeightPx;
40671
+ const textTopPx = paragraphTopPx + layoutEntry.textTopOffsetPx;
40672
+ const textBottomPx = textTopPx + (layoutEntry.pretextLayout ? wrappedPretextParagraphBlockHeightPx(layoutEntry.pretextLayout) : layoutEntry.lineHeightPx * layoutEntry.lineTopOffsetsPx.length);
40673
+ const paragraphBottomPx = resolveTableCellParagraphVisualBottomPx({
40674
+ paragraphTopPx,
40675
+ paragraphHeightPx,
40676
+ textBottomPx
40677
+ });
40678
+ entries.push({
40679
+ paragraph,
40680
+ paragraphIndex,
40681
+ paragraphTopPx,
40682
+ textTopPx,
40683
+ paragraphBottomPx,
40684
+ layoutEntry
40685
+ });
40686
+ paragraphTopPx = paragraphBottomPx;
40687
+ }
40688
+ flowLayout = {
40689
+ contentHeightPx,
40690
+ paddingPx,
40691
+ entries
40692
+ };
40693
+ tableCellParagraphFlowLayoutCacheRef.current.set(
40694
+ flowLayoutCacheKey,
40695
+ flowLayout
40696
+ );
40697
+ }
40698
+ const availableContentHeightPx = Math.max(
40699
+ 0,
40700
+ rowHeightPx - flowLayout.paddingPx.top - flowLayout.paddingPx.bottom
40701
+ );
40702
+ const extraVerticalSpacePx = Math.max(
40703
+ 0,
40704
+ availableContentHeightPx - flowLayout.contentHeightPx
40705
+ );
40706
+ const verticalOffsetPx = cell.style?.verticalAlign === "center" ? Math.round(extraVerticalSpacePx / 2) : cell.style?.verticalAlign === "bottom" ? extraVerticalSpacePx : 0;
40707
+ const sliceBottomPx = sliceStartPx + sliceHeightPx;
40708
+ const slicePlanCacheKey = [
40709
+ flowLayoutCacheKey,
40710
+ rowHeightPx,
40711
+ sliceStartPx,
40712
+ sliceHeightPx
40713
+ ].join(":");
40714
+ const cachedPlans = tableCellParagraphSlicePlanCacheRef.current.get(slicePlanCacheKey);
40715
+ if (cachedPlans) {
40716
+ return cachedPlans;
40717
+ }
40718
+ const plans = [];
40719
+ let firstCandidateIndex = 0;
40720
+ let low = 0;
40721
+ let high = flowLayout.entries.length;
40722
+ while (low < high) {
40723
+ const mid = Math.floor((low + high) / 2);
40724
+ const entryBottomPx = (flowLayout.entries[mid]?.paragraphBottomPx ?? 0) + verticalOffsetPx;
40725
+ if (entryBottomPx <= sliceStartPx + PAGE_OVERFLOW_TOLERANCE_PX) {
40726
+ low = mid + 1;
40727
+ } else {
40728
+ high = mid;
40729
+ }
40730
+ }
40731
+ firstCandidateIndex = low;
40732
+ for (let entryIndex = firstCandidateIndex; entryIndex < flowLayout.entries.length; entryIndex += 1) {
40733
+ const entry = flowLayout.entries[entryIndex];
40734
+ if (!entry) {
40735
+ continue;
40736
+ }
40737
+ const paragraphTopPx = entry.paragraphTopPx + verticalOffsetPx;
40738
+ const textTopPx = entry.textTopPx + verticalOffsetPx;
40739
+ const paragraphBottomPx = entry.paragraphBottomPx + verticalOffsetPx;
40740
+ if (paragraphTopPx >= sliceBottomPx - PAGE_OVERFLOW_TOLERANCE_PX) {
40741
+ break;
40742
+ }
40743
+ const intersectsParagraph = sliceBottomPx > paragraphTopPx + PAGE_OVERFLOW_TOLERANCE_PX && sliceStartPx < paragraphBottomPx - PAGE_OVERFLOW_TOLERANCE_PX;
40744
+ if (!intersectsParagraph) {
40745
+ continue;
40746
+ }
40747
+ const fullyVisible = tableCellParagraphFitsFullyWithinSlice({
40748
+ sliceStartPx,
40749
+ sliceBottomPx,
40750
+ paragraphTopPx,
40751
+ paragraphBottomPx
40752
+ });
40753
+ if (fullyVisible) {
40754
+ plans.push({
40755
+ paragraph: entry.paragraph,
40756
+ paragraphIndex: entry.paragraphIndex,
40757
+ topPx: Math.max(0, Math.round(paragraphTopPx - sliceStartPx)),
40758
+ layoutEntry: entry.layoutEntry
40759
+ });
40760
+ continue;
40761
+ }
40762
+ const paragraphLineRange = resolveLineRangeWithinVerticalSlice(
40763
+ entry.layoutEntry.lineTopOffsetsPx,
40764
+ entry.layoutEntry.lineHeightPx,
40765
+ sliceStartPx - textTopPx,
40766
+ sliceBottomPx - textTopPx
40767
+ );
40768
+ if (!paragraphLineRange) {
40769
+ continue;
40770
+ }
40771
+ const lineRangeTopPx = paragraphLineRange.startLineIndex > 0 ? textTopPx + entry.layoutEntry.lineTopOffsetsPx[paragraphLineRange.startLineIndex] : paragraphTopPx;
40772
+ plans.push({
40773
+ paragraph: entry.paragraph,
40774
+ paragraphIndex: entry.paragraphIndex,
40775
+ topPx: Math.max(0, Math.round(lineRangeTopPx - sliceStartPx)),
40776
+ layoutEntry: entry.layoutEntry,
40777
+ paragraphLineRange
40778
+ });
40779
+ }
40780
+ tableCellParagraphSlicePlanCacheRef.current.set(slicePlanCacheKey, plans);
40781
+ return plans;
40782
+ };
40783
+ const renderSlicedTableCellParagraph = (params) => {
40784
+ const {
40785
+ paragraph,
40786
+ paragraphIndex,
40787
+ tableIndex,
40788
+ rowIndex,
40789
+ cellIndex,
40790
+ contentIndex,
40791
+ cellContentWidthPx,
40792
+ applyWordTableDefaults,
40793
+ docGridLinePitchPx,
40794
+ layoutEntry,
40795
+ paragraphLineRange
40796
+ } = params;
40797
+ const numberingDefinitions = editor.model.metadata.numberingDefinitions;
40798
+ const paragraphForLayout = layoutEntry.paragraphForLayout;
40799
+ const hasPartialLineRange = paragraphSegmentHasPartialLineRange(paragraphLineRange);
40800
+ const paragraphSegmentLineHeightPx = Math.max(
40801
+ 1,
40802
+ paragraphLineRange?.lineHeightPx ?? layoutEntry.lineHeightPx
40803
+ );
40804
+ const paragraphSegmentStartLine = paragraphLineRange?.startLineIndex ?? 0;
40805
+ const paragraphSegmentEndLine = paragraphLineRange?.endLineIndex ?? paragraphLineRange?.totalLineCount ?? 1;
40806
+ const paragraphSegmentTotalLines = paragraphLineRange?.totalLineCount ?? Math.max(1, paragraphSegmentEndLine);
40807
+ const paragraphSegmentVisibleLineCount = Math.max(
40808
+ 1,
40809
+ paragraphSegmentEndLine - paragraphSegmentStartLine
40810
+ );
40811
+ const paragraphSegmentVisibleHeightPx = paragraphSegmentVisibleLineCount * paragraphSegmentLineHeightPx;
40812
+ const paragraphSegmentTranslateYPx = paragraphSegmentStartLine * paragraphSegmentLineHeightPx;
40813
+ const location = {
40814
+ kind: "table-cell",
40815
+ tableIndex,
40816
+ rowIndex,
40817
+ cellIndex,
40818
+ paragraphIndex
40819
+ };
40820
+ const numberingLabel = paragraphNumberingLabels.get(
40821
+ paragraphLocationKey(location)
40822
+ );
40823
+ const paragraphRenderTextWidthPx = paragraphAvailableTextWidthPx(
40824
+ paragraphForLayout,
40825
+ cellContentWidthPx,
40826
+ numberingDefinitions
40827
+ );
40828
+ const pretextParagraphLayout = hasPartialLineRange && layoutEntry.pretextSource ? layoutEntry.pretextLayout && Math.abs(paragraphSegmentLineHeightPx - layoutEntry.lineHeightPx) <= 1 ? layoutEntry.pretextLayout : layoutParagraphPretextSource(
40829
+ paragraphForLayout,
40830
+ layoutEntry.pretextSource,
40831
+ paragraphRenderTextWidthPx,
40832
+ paragraphSegmentLineHeightPx,
40833
+ []
40834
+ ) : void 0;
40835
+ const pretextParagraphTotalLines = Math.max(
40836
+ 0,
40837
+ pretextParagraphLayout?.lineCount ?? 0
40838
+ );
40839
+ const pretextParagraphSliceStartLine = hasPartialLineRange && paragraphLineRange && pretextParagraphTotalLines > 0 ? Math.max(
40840
+ 0,
40841
+ Math.min(
40842
+ paragraphLineRange.startLineIndex,
40843
+ pretextParagraphTotalLines
40844
+ )
40845
+ ) : void 0;
40846
+ const pretextParagraphSliceEndLine = hasPartialLineRange && paragraphLineRange && pretextParagraphTotalLines > 0 && pretextParagraphSliceStartLine !== void 0 ? Math.max(
40847
+ pretextParagraphSliceStartLine,
40848
+ Math.min(
40849
+ paragraphLineRange.endLineIndex,
40850
+ pretextParagraphTotalLines
40851
+ )
40852
+ ) : void 0;
40853
+ const pretextParagraphSliceLayout = hasPartialLineRange && pretextParagraphLayout && pretextParagraphSliceStartLine !== void 0 && pretextParagraphSliceEndLine !== void 0 && pretextParagraphLayout.lineCount > 0 ? sliceLayoutToLineRange(
40854
+ pretextParagraphLayout,
40855
+ pretextParagraphSliceStartLine,
40856
+ pretextParagraphSliceEndLine
40857
+ ) : void 0;
40858
+ const shouldRenderParagraphSegmentWithPretext = hasPartialLineRange && Boolean(layoutEntry.pretextSource) && Boolean(pretextParagraphLayout) && pretextParagraphTotalLines > 0;
40859
+ const paragraphSegmentClipBleed = shouldRenderParagraphSegmentWithPretext ? resolveParagraphSegmentClipBleedPx(paragraphLineRange) : resolveFallbackParagraphSegmentClipBleedPx(
40860
+ paragraphForLayout,
40861
+ paragraphLineRange
40862
+ );
40863
+ const paragraphSegmentClipBleedTopPx = paragraphSegmentClipBleed.topPx;
40864
+ const paragraphSegmentClipBleedBottomPx = paragraphSegmentClipBleed.bottomPx;
40865
+ const pretextSegmentNumberingMarkerBoxWidthPx = numberingLabel && paragraphSegmentStartLine === 0 ? resolveNumberingMarkerBoxWidthPx(
40866
+ paragraph,
40867
+ numberingDefinitions,
40868
+ numberingLabel
40869
+ ) ?? Math.max(
40870
+ 16,
40871
+ Math.ceil(
40872
+ measureTextWidthPx2(
40873
+ numberingLabel.imageSrc ? numberingLabel.trailingText ?? "" : numberingLabel.text ?? "",
40874
+ numberingLabel.style,
40875
+ paragraphBaseFontSizePx(paragraph)
40876
+ )
40877
+ ) + (numberingLabel.imageSrc ? Math.ceil(numberingLabel.imageWidthPx ?? 12) + 2 : 0) + 4
40878
+ ) : void 0;
40879
+ const pretextSegmentNumberingMarkerNode = shouldRenderParagraphSegmentWithPretext && numberingLabel && paragraphSegmentStartLine === 0 && Number.isFinite(pretextSegmentNumberingMarkerBoxWidthPx) ? /* @__PURE__ */ jsx(
40880
+ "span",
40881
+ {
40882
+ contentEditable: false,
40883
+ "data-docx-numbering-label": "true",
40884
+ style: {
40885
+ ...numberingMarkerStyle(
40886
+ paragraph,
40887
+ numberingDefinitions,
40888
+ numberingLabel,
40889
+ numberingLabel.style ? runStyleToCss(numberingLabel.style, documentContentTheme) : void 0,
40890
+ documentContentTheme
40891
+ ),
40892
+ position: "absolute",
40893
+ left: -Math.round(
40894
+ pretextSegmentNumberingMarkerBoxWidthPx
40895
+ ),
40896
+ top: 0,
40897
+ marginRight: 0,
40898
+ zIndex: 1,
40899
+ pointerEvents: "none"
40900
+ },
40901
+ children: numberingLabel.imageSrc ? /* @__PURE__ */ jsxs(Fragment2, { children: [
40902
+ /* @__PURE__ */ jsx(
40903
+ "img",
40904
+ {
40905
+ src: numberingLabel.imageSrc,
40906
+ alt: "",
40907
+ "aria-hidden": "true",
40908
+ draggable: false,
40909
+ style: {
40910
+ display: "inline-block",
40911
+ verticalAlign: "text-bottom",
40912
+ width: numberingLabel.imageWidthPx ?? 12,
40913
+ height: numberingLabel.imageHeightPx ?? 12,
40914
+ marginRight: 2,
40915
+ filter: documentContentFilter
40916
+ }
40917
+ }
40918
+ ),
40919
+ numberingLabel.trailingText ?? ""
40920
+ ] }) : numberingLabel.text ?? ""
40921
+ },
40922
+ `table-cell-${tableIndex}-${rowIndex}-${cellIndex}-${paragraphIndex}-numbering-marker-${paragraphSegmentStartLine}`
40923
+ ) : void 0;
40924
+ const baseParagraphStyle = tableCellParagraphBlockStyle(
40925
+ paragraph,
40926
+ numberingDefinitions,
40927
+ headingStyles,
40928
+ paragraphIndex,
40929
+ applyWordTableDefaults,
40930
+ docGridLinePitchPx
40931
+ );
40932
+ const paragraphStyle = {
40933
+ ...baseParagraphStyle,
40934
+ ...hasPartialLineRange ? {
40935
+ marginTop: paragraphSegmentStartLine === 0 ? baseParagraphStyle.marginTop : 0,
40936
+ marginBottom: paragraphSegmentEndLine >= paragraphSegmentTotalLines ? baseParagraphStyle.marginBottom : 0
40937
+ } : void 0,
40938
+ outline: "none"
40939
+ };
40940
+ const fallbackParagraphRuns = renderInteractiveParagraphRuns(
40941
+ paragraph,
40942
+ `body-cell-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
40943
+ location
40944
+ );
40945
+ const renderedInteractiveParagraphContent = shouldRenderParagraphSegmentWithPretext ? /* @__PURE__ */ jsx(
40946
+ "div",
40947
+ {
40948
+ style: {
40949
+ minHeight: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
40950
+ marginTop: -paragraphSegmentClipBleedTopPx,
40951
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
40952
+ paddingTop: paragraphSegmentClipBleedTopPx,
40953
+ paddingBottom: paragraphSegmentClipBleedBottomPx,
40954
+ overflow: "visible"
40955
+ },
40956
+ children: layoutEntry.pretextSource && pretextParagraphSliceLayout && pretextParagraphSliceLayout.lineCount > 0 ? renderWrappedPretextParagraph({
40957
+ location,
40958
+ keyPrefix: `body-cell-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}-lines-${paragraphSegmentStartLine}-${paragraphSegmentEndLine}`,
40959
+ source: layoutEntry.pretextSource,
40960
+ layout: pretextParagraphSliceLayout,
40961
+ lineHeightPx: paragraphSegmentLineHeightPx,
40962
+ baseTextStyle: firstRunStyle(paragraph),
40963
+ blockHeightPx: pretextParagraphSliceLayout.height,
40964
+ obstacleNodes: pretextSegmentNumberingMarkerNode
40965
+ }) : null
40966
+ }
40967
+ ) : hasPartialLineRange ? /* @__PURE__ */ jsx(
40968
+ "div",
40969
+ {
40970
+ style: {
40971
+ height: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
40972
+ marginTop: -paragraphSegmentClipBleedTopPx,
40973
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
40974
+ overflow: "hidden"
40975
+ },
40976
+ children: /* @__PURE__ */ jsx(
40977
+ "div",
40978
+ {
40979
+ style: {
40980
+ transform: `translateY(-${paragraphSegmentTranslateYPx - paragraphSegmentClipBleedTopPx}px)`
40981
+ },
40982
+ children: fallbackParagraphRuns
40983
+ }
40984
+ )
40985
+ }
40986
+ ) : fallbackParagraphRuns;
40987
+ return /* @__PURE__ */ jsx(
40988
+ "div",
40989
+ {
40990
+ "data-docx-paragraph-host": "true",
40991
+ "data-docx-paragraph-kind": "table-cell",
40992
+ "data-docx-table-index": tableIndex,
40993
+ "data-docx-row-index": rowIndex,
40994
+ "data-docx-cell-index": cellIndex,
40995
+ "data-docx-paragraph-index": paragraphIndex,
40996
+ "data-docx-table-paragraph-index": paragraphIndex,
40997
+ style: paragraphStyle,
40998
+ children: renderedInteractiveParagraphContent
40999
+ },
41000
+ `body-cell-slice-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}`
41001
+ );
41002
+ };
39005
41003
  const renderDocumentNode = (node, nodeIndex, tableRowRange, tableRowSlice, paragraphLineRange, options) => {
39006
41004
  const nodeDocGridLinePitchPx = docGridLinePitchPxByNodeIndex.get(nodeIndex);
39007
41005
  const nodeContentWidthPx = Math.max(
@@ -39039,7 +41037,7 @@ function DocxEditorViewer({
39039
41037
  paragraphLineRange
39040
41038
  );
39041
41039
  const paragraphHasActiveEditableSegment = activeEditableParagraphSegment?.nodeIndex === nodeIndex;
39042
- const shouldTrackParagraphElement = !hasPartialLineRange || paragraphSegmentIsActiveEditable || !paragraphHasActiveEditableSegment && paragraphSegmentStartLine === 0;
41040
+ const shouldTrackParagraphElement = options?.suppressParagraphElementTracking === true ? false : !hasPartialLineRange || paragraphSegmentIsActiveEditable || !paragraphHasActiveEditableSegment && paragraphSegmentStartLine === 0;
39043
41041
  const isManualPageBreakParagraph = paragraphIsOnlyExplicitPageBreak2(node);
39044
41042
  const paragraphContentWidthPx = nodeContentWidthPx;
39045
41043
  const paragraphRenderTextWidthPx = paragraphAvailableTextWidthPx(
@@ -39048,7 +41046,8 @@ function DocxEditorViewer({
39048
41046
  editor.model.metadata.numberingDefinitions
39049
41047
  );
39050
41048
  const pretextParagraphSource = hasPartialLineRange ? buildParagraphPretextLayoutSource(node, {
39051
- allowExplicitLineBreakText: true
41049
+ allowExplicitLineBreakText: true,
41050
+ expandTabsForLayout: true
39052
41051
  }) : void 0;
39053
41052
  const pretextParagraphLayout = hasPartialLineRange && pretextParagraphSource ? layoutParagraphPretextSource(
39054
41053
  node,
@@ -39143,7 +41142,13 @@ function DocxEditorViewer({
39143
41142
  },
39144
41143
  `node-${nodeIndex}-numbering-marker-${paragraphSegmentStartLine}`
39145
41144
  ) : void 0;
39146
- const editable = !hasImage && !isReadOnly && (!hasPartialLineRange || paragraphSegmentIsActiveEditable) && !isManualPageBreakParagraph;
41145
+ const resolvedBeforeSpacingPx = Number.isFinite(
41146
+ options?.overrideBeforeSpacingPx
41147
+ ) ? Math.max(0, Math.round(options?.overrideBeforeSpacingPx)) : void 0;
41148
+ const resolvedAfterSpacingPx = Number.isFinite(
41149
+ options?.overrideAfterSpacingPx
41150
+ ) ? Math.max(0, Math.round(options?.overrideAfterSpacingPx)) : void 0;
41151
+ const editable = !hasImage && !isReadOnly && options?.forceReadOnly !== true && (!hasPartialLineRange || paragraphSegmentIsActiveEditable) && !isManualPageBreakParagraph;
39147
41152
  const resolvedPageLayout = options?.pageLayout ?? documentLayout;
39148
41153
  const paragraphContainsLikelyFullPageCoverImage = node.children.some(
39149
41154
  (child) => child.type === "image" && shouldRenderAbsoluteFloatingImage(child) && likelyFullPageCoverImageRelativeToContentBox(
@@ -39213,8 +41218,11 @@ function DocxEditorViewer({
39213
41218
  const paragraphStyle = {
39214
41219
  ...baseParagraphStyle,
39215
41220
  ...hasPartialLineRange ? {
39216
- marginTop: paragraphSegmentStartLine === 0 ? beforeSpacingPx : 0,
39217
- marginBottom: paragraphSegmentEndLine >= paragraphSegmentTotalLines ? afterSpacingPx : 0
41221
+ marginTop: paragraphSegmentStartLine === 0 ? resolvedBeforeSpacingPx ?? beforeSpacingPx : 0,
41222
+ marginBottom: paragraphSegmentEndLine >= paragraphSegmentTotalLines ? resolvedAfterSpacingPx ?? afterSpacingPx : 0
41223
+ } : resolvedBeforeSpacingPx !== void 0 || resolvedAfterSpacingPx !== void 0 ? {
41224
+ ...resolvedBeforeSpacingPx !== void 0 ? { marginTop: resolvedBeforeSpacingPx } : void 0,
41225
+ ...resolvedAfterSpacingPx !== void 0 ? { marginBottom: resolvedAfterSpacingPx } : void 0
39218
41226
  } : void 0,
39219
41227
  ...letterheadStyleAdjustments ?? void 0,
39220
41228
  ...options?.suppressLetterheadColumnLayout && options?.isFirstInLetterheadColumn ? { marginTop: 0 } : void 0,
@@ -39253,7 +41261,8 @@ function DocxEditorViewer({
39253
41261
  {
39254
41262
  style: {
39255
41263
  minHeight: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
39256
- marginBottom: -(paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx),
41264
+ marginTop: -paragraphSegmentClipBleedTopPx,
41265
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
39257
41266
  paddingTop: paragraphSegmentClipBleedTopPx,
39258
41267
  paddingBottom: paragraphSegmentClipBleedBottomPx,
39259
41268
  overflow: "visible"
@@ -39277,7 +41286,8 @@ function DocxEditorViewer({
39277
41286
  {
39278
41287
  style: {
39279
41288
  height: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
39280
- marginBottom: -(paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx),
41289
+ marginTop: -paragraphSegmentClipBleedTopPx,
41290
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
39281
41291
  overflow: "hidden"
39282
41292
  },
39283
41293
  children: /* @__PURE__ */ jsx(
@@ -39863,7 +41873,7 @@ ${currentText.slice(end)}`;
39863
41873
  },
39864
41874
  children: !editable ? renderedInteractiveParagraphContent : null
39865
41875
  },
39866
- paragraphLineRange ? `epoch-${paragraphStructureEpoch}-node-${nodeIndex}-lines-${paragraphSegmentStartLine}-${paragraphSegmentEndLine}` : `epoch-${paragraphStructureEpoch}-node-${nodeIndex}`
41876
+ paragraphLineRange ? `epoch-${paragraphStructureEpoch}-node-${nodeIndex}-lines-${paragraphSegmentStartLine}-${paragraphSegmentEndLine}${options?.syntheticKeySuffix ? `-${options.syntheticKeySuffix}` : ""}` : `epoch-${paragraphStructureEpoch}-node-${nodeIndex}${options?.syntheticKeySuffix ? `-${options.syntheticKeySuffix}` : ""}`
39867
41877
  );
39868
41878
  }
39869
41879
  const tableRowSliceOffsetPxForWrapper = tableRowSlice ? Math.max(0, Math.round(tableRowSlice.startOffsetPx)) : 0;
@@ -39896,7 +41906,7 @@ ${currentText.slice(end)}`;
39896
41906
  paddingTop: tableRowSliceTopBleedPxForWrapper,
39897
41907
  paddingBottom: tableRowSliceBottomBleedPxForWrapper,
39898
41908
  boxSizing: "border-box",
39899
- overflow: "clip"
41909
+ overflow: "visible"
39900
41910
  } : void 0
39901
41911
  },
39902
41912
  onPointerEnter: () => {
@@ -39929,11 +41939,12 @@ ${currentText.slice(end)}`;
39929
41939
  },
39930
41940
  children: (() => {
39931
41941
  const tableIndentPx = twipsToSignedPixels(node.style?.indentTwips) ?? 0;
41942
+ const columnCount = tableColumnCount(node);
41943
+ const collapsedHorizontalBorderBleedPx = resolveCollapsedTableHorizontalOuterBleedPx(node, columnCount);
39932
41944
  const maxTableWidthPx = Math.max(
39933
41945
  120,
39934
- nodeContentWidthPx - tableIndentPx
41946
+ nodeContentWidthPx - tableIndentPx - collapsedHorizontalBorderBleedPx
39935
41947
  );
39936
- const columnCount = tableColumnCount(node);
39937
41948
  const tableWidthPx = twipsToPixels(node.style?.widthTwips);
39938
41949
  const hasStoredColumnWidths = (tableColumnWidths[nodeIndex]?.length ?? 0) === columnCount;
39939
41950
  const rawColumnWidthsPx = resolveTableColumnWidths(
@@ -40026,6 +42037,7 @@ ${currentText.slice(end)}`;
40026
42037
  "span",
40027
42038
  {
40028
42039
  contentEditable: false,
42040
+ "data-docx-pagination-ignore": "true",
40029
42041
  style: {
40030
42042
  position: "absolute",
40031
42043
  top: -TABLE_HANDLE_SAFEZONE_TOP_PX,
@@ -40043,6 +42055,7 @@ ${currentText.slice(end)}`;
40043
42055
  "span",
40044
42056
  {
40045
42057
  contentEditable: false,
42058
+ "data-docx-pagination-ignore": "true",
40046
42059
  style: {
40047
42060
  position: "absolute",
40048
42061
  right: -TABLE_HANDLE_SAFEZONE_RIGHT_PX,
@@ -40132,10 +42145,7 @@ ${currentText.slice(end)}`;
40132
42145
  style: {
40133
42146
  width: resolvedTableWidthPx > 0 ? `${resolvedTableWidthPx}px` : "100%",
40134
42147
  ...tableElementBorderStyle(node, tableBorderSpacingPx),
40135
- tableLayout: node.style?.layout === "autofit" ? "auto" : "fixed",
40136
- ...hasTableRowSlice && tableRowSliceOffsetPx > 0 ? {
40137
- transform: `translateY(-${tableRowSliceOffsetPx - tableRowSliceTopBleedPx}px)`
40138
- } : void 0
42148
+ tableLayout: node.style?.layout === "autofit" ? "auto" : "fixed"
40139
42149
  },
40140
42150
  children: [
40141
42151
  /* @__PURE__ */ jsx("colgroup", { children: columnWidthsPx.map((widthPx, columnIndex) => /* @__PURE__ */ jsx(
@@ -40183,7 +42193,7 @@ ${currentText.slice(end)}`;
40183
42193
  );
40184
42194
  const recursiveCellParagraphs = tableCellParagraphsRecursively(cell.nodes);
40185
42195
  const cellHasImage = tableCellHasImage(cell.nodes);
40186
- const editableCell = selectedByAnchor && !isMultiCellSelectionActive && !cellHasImage && !isReadOnly && cellParagraphs.length > 0;
42196
+ const editableCell = selectedByAnchor && !isSlicedRow && !isMultiCellSelectionActive && !cellHasImage && !isReadOnly && cellParagraphs.length > 0;
40187
42197
  const nestedParagraphIndexesByNode = /* @__PURE__ */ new Map();
40188
42198
  recursiveCellParagraphs.forEach(
40189
42199
  (paragraph, paragraphIndex) => {
@@ -40193,7 +42203,7 @@ ${currentText.slice(end)}`;
40193
42203
  );
40194
42204
  }
40195
42205
  );
40196
- const tableCellEditScope = recursiveCellParagraphs.length > 0 && !isReadOnly && !isMultiCellSelectionActive && !cellHasImage ? {
42206
+ const tableCellEditScope = recursiveCellParagraphs.length > 0 && !isReadOnly && !isSlicedRow && !isMultiCellSelectionActive && !cellHasImage ? {
40197
42207
  isEditable: true,
40198
42208
  draftKeyPrefix: `${nodeIndex}:${rowIndex}:${cellIndex}`,
40199
42209
  paragraphIndexesByNode: nestedParagraphIndexesByNode,
@@ -40234,6 +42244,38 @@ ${currentText.slice(end)}`;
40234
42244
  ).reduce((sum, widthPx) => sum + widthPx, 0);
40235
42245
  const cellBackgroundColor = cell.style?.backgroundColor ?? row.style?.backgroundColor;
40236
42246
  const hasCustomCellRowHeight = hasCustomRowHeight || hasResolvedRowHeight;
42247
+ const mergedCellMarginTwips = mergeTableSpacing(
42248
+ tableCellMarginTwips,
42249
+ cell.style?.marginTwips
42250
+ );
42251
+ const cellPaddingPx = resolveTableSpacingPaddingPx(
42252
+ mergedCellMarginTwips
42253
+ );
42254
+ const cellRenderedWidthPx = cellWidthPx ?? spannedWidthPx;
42255
+ const cellContentWidthPx = Math.max(
42256
+ 1,
42257
+ cellRenderedWidthPx - cellPaddingPx.left - cellPaddingPx.right
42258
+ );
42259
+ const slicedRowHeightPx = Math.max(
42260
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
42261
+ Math.round(
42262
+ rowBoundarySourceHeightsPx[rowIndex] ?? rowHeightPx ?? MIN_PARAGRAPH_LINE_HEIGHT_PX
42263
+ )
42264
+ );
42265
+ const slicedCellViewportHeightPx = isSlicedRow && tableRowSlice ? Math.max(
42266
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
42267
+ Math.round(tableRowSlice.sliceHeightPx)
42268
+ ) : void 0;
42269
+ const slicedParagraphPlans = isSlicedRow && tableRowSlice && !editableCell && slicedCellViewportHeightPx ? resolveTableCellParagraphSlicePlans({
42270
+ cell,
42271
+ rowHeightPx: slicedRowHeightPx,
42272
+ sliceStartPx: tableRowSliceOffsetPx,
42273
+ sliceHeightPx: slicedCellViewportHeightPx,
42274
+ cellContentWidthPx,
42275
+ tableCellMarginTwips,
42276
+ applyWordTableDefaults,
42277
+ docGridLinePitchPx: nodeDocGridLinePitchPx
42278
+ }) : void 0;
40237
42279
  const renderedEditableCellContent = editableCell ? (() => {
40238
42280
  let paragraphCursor = 0;
40239
42281
  return cell.nodes.map(
@@ -40331,10 +42373,7 @@ ${currentText.slice(end)}`;
40331
42373
  cell.style?.borders
40332
42374
  ),
40333
42375
  ...tableSpacingPaddingStyle(
40334
- mergeTableSpacing(
40335
- tableCellMarginTwips,
40336
- cell.style?.marginTwips
40337
- )
42376
+ mergedCellMarginTwips
40338
42377
  ),
40339
42378
  backgroundColor: cellBackgroundColor,
40340
42379
  verticalAlign: cell.style?.verticalAlign ?? "top",
@@ -41155,6 +43194,45 @@ ${currentText.slice(end)}`;
41155
43194
  );
41156
43195
  }
41157
43196
  }
43197
+ ) : slicedParagraphPlans && slicedCellViewportHeightPx ? /* @__PURE__ */ jsx(
43198
+ "div",
43199
+ {
43200
+ style: {
43201
+ position: "relative",
43202
+ height: slicedCellViewportHeightPx,
43203
+ overflow: "visible"
43204
+ },
43205
+ children: slicedParagraphPlans.map((plan) => {
43206
+ const contentIndex = cell.nodes.indexOf(
43207
+ plan.paragraph
43208
+ );
43209
+ return /* @__PURE__ */ jsx(
43210
+ "div",
43211
+ {
43212
+ style: {
43213
+ position: "absolute",
43214
+ left: 0,
43215
+ right: 0,
43216
+ top: plan.topPx
43217
+ },
43218
+ children: renderSlicedTableCellParagraph({
43219
+ paragraph: plan.paragraph,
43220
+ paragraphIndex: plan.paragraphIndex,
43221
+ tableIndex: nodeIndex,
43222
+ rowIndex,
43223
+ cellIndex,
43224
+ contentIndex,
43225
+ cellContentWidthPx,
43226
+ applyWordTableDefaults,
43227
+ docGridLinePitchPx: nodeDocGridLinePitchPx,
43228
+ layoutEntry: plan.layoutEntry,
43229
+ paragraphLineRange: plan.paragraphLineRange
43230
+ })
43231
+ },
43232
+ `body-cell-slice-host-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`
43233
+ );
43234
+ })
43235
+ }
41158
43236
  ) : /* @__PURE__ */ jsx("div", { style: { display: "grid", gap: 4 }, children: (() => {
41159
43237
  let paragraphCursor = 0;
41160
43238
  return cell.nodes.map(
@@ -42646,10 +44724,11 @@ ${currentText.slice(end)}`;
42646
44724
  pageLayout.pageHeightPx - pageLayout.marginsPx.top - pageLayout.marginsPx.bottom
42647
44725
  ),
42648
44726
  metricsBySection: paginationSectionMetrics,
42649
- measuredPageContentHeightsPxByPageIndex: measuredPageContentHeightByIndex,
44727
+ measuredPageContentHeightsPxByPageIndex: renderMeasuredPageContentHeightsPxByPageIndex,
42650
44728
  measuredPageContentIdentityKeysByPageIndex: measuredPageContentIdentityKeysByIndex,
42651
44729
  pageIdentityKey: pageNodeSegmentIdentityKeysByPage[pageIndex],
42652
- useMeasuredPageContentHeights: useMeasuredPageContentHeightsForRender
44730
+ useMeasuredPageContentHeights: useMeasuredPageContentHeightsForRender,
44731
+ pageContentHeightScale: renderPageContentHeightScale
42653
44732
  });
42654
44733
  const headerFooterBodyDimmed = pageHeaderFooterEditActive;
42655
44734
  const documentPageBackgroundColor = editor.model.metadata.documentBackgroundColor;
@@ -42943,6 +45022,7 @@ ${currentText.slice(end)}`;
42943
45022
  display: "flex",
42944
45023
  flexDirection: "column",
42945
45024
  minHeight: pageBodyAvailableHeightPx,
45025
+ overflow: "visible",
42946
45026
  ...documentContentFilter ? { filter: documentContentFilter } : void 0
42947
45027
  },
42948
45028
  children: [
@@ -43010,6 +45090,44 @@ ${currentText.slice(end)}`;
43010
45090
  if (!columnNode) {
43011
45091
  return null;
43012
45092
  }
45093
+ const explicitColumnBreakParagraphSegments = columnNode.type === "paragraph" && !columnSegment.tableRowRange && !columnSegment.tableRowSlice && !columnSegment.paragraphLineRange && !explicitColumnWidthsPx && (sectionColumns?.count ?? 0) > 1 ? splitParagraphAtExplicitColumnBreaks(columnNode) : void 0;
45094
+ if (explicitColumnBreakParagraphSegments && explicitColumnBreakParagraphSegments.length > 1) {
45095
+ return /* @__PURE__ */ jsx(
45096
+ React.Fragment,
45097
+ {
45098
+ children: explicitColumnBreakParagraphSegments.map(
45099
+ (segmentParagraph, segmentIndex) => {
45100
+ const isLastSegment = segmentIndex >= explicitColumnBreakParagraphSegments.length - 1;
45101
+ return /* @__PURE__ */ jsx(
45102
+ "div",
45103
+ {
45104
+ style: segmentIndex > 0 ? { breakBefore: "column" } : void 0,
45105
+ children: renderDocumentNode(
45106
+ segmentParagraph,
45107
+ columnSegment.nodeIndex,
45108
+ void 0,
45109
+ void 0,
45110
+ void 0,
45111
+ {
45112
+ pageLayout,
45113
+ contentWidthPxOverride: columnContentWidthPx,
45114
+ suppressLikelyFullPageCoverImageKeys: suppressedLikelyFullPageCoverImageKeys,
45115
+ forceReadOnly: true,
45116
+ suppressParagraphElementTracking: segmentIndex > 0,
45117
+ syntheticKeySuffix: `column-break-${segmentIndex}`,
45118
+ overrideBeforeSpacingPx: segmentIndex === 0 ? void 0 : 0,
45119
+ overrideAfterSpacingPx: isLastSegment ? void 0 : 0
45120
+ }
45121
+ )
45122
+ },
45123
+ `column-layout-node-${pageIndex}-${columnSegment.nodeIndex}-column-break-${segmentIndex}`
45124
+ );
45125
+ }
45126
+ )
45127
+ },
45128
+ `column-layout-node-${pageIndex}-${columnSegment.nodeIndex}-column-break-group`
45129
+ );
45130
+ }
43013
45131
  const renderedNode = renderDocumentNode(
43014
45132
  columnNode,
43015
45133
  columnSegment.nodeIndex,
@@ -44681,6 +46799,9 @@ var DEFAULT_MIN_PARAGRAPH_LINE_HEIGHT_PX = 14;
44681
46799
  var PARAGRAPH_SEGMENT_TOP_BLEED_PX2 = 22;
44682
46800
  var PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX2 = 6;
44683
46801
  var PARAGRAPH_SEGMENT_VISUAL_SAFETY_PX2 = 24;
46802
+ var LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_RATIO2 = 0.18;
46803
+ var LAST_RENDERED_PAGE_BREAK_HINT_MIN_REMAINING_SPACE_PX2 = DEFAULT_MIN_PARAGRAPH_LINE_HEIGHT_PX * 3;
46804
+ var LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_PX2 = 120;
44684
46805
  function paragraphSegmentHasPartialLineRange2(paragraphLineRange) {
44685
46806
  if (!paragraphLineRange) {
44686
46807
  return false;
@@ -44749,6 +46870,48 @@ function normalizedPositivePixelValue(value, fallback) {
44749
46870
  }
44750
46871
  return Math.max(1, Math.round(value));
44751
46872
  }
46873
+ function shouldHonorParagraphStartLastRenderedPageBreak2(params) {
46874
+ const pageConsumedHeightPx = Math.max(
46875
+ 0,
46876
+ Math.round(params.pageConsumedHeightPx)
46877
+ );
46878
+ const pageContentHeightPx = Math.max(
46879
+ 0,
46880
+ Math.round(params.pageContentHeightPx)
46881
+ );
46882
+ if (pageConsumedHeightPx <= 0 || pageContentHeightPx <= 0) {
46883
+ return false;
46884
+ }
46885
+ const remainingHeightPx = Math.max(
46886
+ 0,
46887
+ pageContentHeightPx - pageConsumedHeightPx
46888
+ );
46889
+ const maxAllowedRemainingHeightPx = Math.max(
46890
+ LAST_RENDERED_PAGE_BREAK_HINT_MIN_REMAINING_SPACE_PX2,
46891
+ Math.min(
46892
+ LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_PX2,
46893
+ Math.round(
46894
+ pageContentHeightPx * LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_RATIO2
46895
+ )
46896
+ )
46897
+ );
46898
+ return remainingHeightPx <= maxAllowedRemainingHeightPx;
46899
+ }
46900
+ function keepNextParagraphReservePx(paragraph, nextParagraph, callbacks, docGridLinePitchPx) {
46901
+ if (paragraph.style?.keepNext !== true || !nextParagraph || !Number.isFinite(paragraph.style?.headingLevel)) {
46902
+ return 0;
46903
+ }
46904
+ const nextParagraphText = nextParagraph.children.filter((child) => child.type === "text").map((child) => child.text).join(" ").replace(/\s+/g, " ").trim();
46905
+ if (nextParagraph.style?.numbering === void 0 && nextParagraphText.length < 80) {
46906
+ return 0;
46907
+ }
46908
+ return Math.max(
46909
+ nextParagraph.style?.numbering ? 10 : 6,
46910
+ Math.round(
46911
+ callbacks.estimateParagraphLineHeightPx(nextParagraph, docGridLinePitchPx) * (nextParagraph.style?.numbering ? 1 : 0.5)
46912
+ )
46913
+ );
46914
+ }
44752
46915
  function normalizedMeasuredTableRowHeights(measuredRowHeightsPx, expectedRowCount, minParagraphLineHeightPx) {
44753
46916
  if (!measuredRowHeightsPx || measuredRowHeightsPx.length !== expectedRowCount) {
44754
46917
  return void 0;
@@ -44941,6 +47104,12 @@ function collectDocxEstimatedOverflowBreakStartNodeIndexes(model, hardBreakStart
44941
47104
  paragraphBeforeSpacingPx2(nextChainNode)
44942
47105
  );
44943
47106
  requiredHeightPx += Math.max(1, nextRawHeightPx - collapsedChainMarginPx);
47107
+ requiredHeightPx += keepNextParagraphReservePx(
47108
+ currentChainNode,
47109
+ nextChainNode,
47110
+ callbacks,
47111
+ chainMetrics.docGridLinePitchPx
47112
+ );
44944
47113
  chainPreviousParagraphAfterPx = paragraphAfterSpacingPx2(nextChainNode);
44945
47114
  }
44946
47115
  }
@@ -45037,7 +47206,10 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
45037
47206
  nodeMetrics.pageContentHeightPx
45038
47207
  );
45039
47208
  }
45040
- if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak2(node) && currentPageSegments.length > 0) {
47209
+ if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak2(node) && shouldHonorParagraphStartLastRenderedPageBreak2({
47210
+ pageConsumedHeightPx,
47211
+ pageContentHeightPx: currentPageContentHeightPx
47212
+ }) && currentPageSegments.length > 0) {
45041
47213
  startNextPage();
45042
47214
  pageConsumedHeightPx = 0;
45043
47215
  previousParagraphAfterPx = 0;
@@ -45262,6 +47434,12 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
45262
47434
  paragraphBeforeSpacingPx2(nextChainNode)
45263
47435
  );
45264
47436
  requiredHeightPx += Math.max(1, nextRawHeightPx - collapsedChainMarginPx);
47437
+ requiredHeightPx += keepNextParagraphReservePx(
47438
+ currentChainNode,
47439
+ nextChainNode,
47440
+ callbacks,
47441
+ chainMetrics.docGridLinePitchPx
47442
+ );
45265
47443
  chainPreviousParagraphAfterPx = paragraphAfterSpacingPx2(nextChainNode);
45266
47444
  }
45267
47445
  }