@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.cjs CHANGED
@@ -4947,6 +4947,7 @@ function parseTable(tableXml2, context) {
4947
4947
  const rowHeightRuleRaw = rowHeightTag ? getAttribute(rowHeightTag, "w:hRule")?.toLowerCase() : void 0;
4948
4948
  const rowHeightRule = rowHeightRuleRaw === "atleast" || rowHeightRuleRaw === "exact" || rowHeightRuleRaw === "auto" ? rowHeightRuleRaw === "atleast" ? "atLeast" : rowHeightRuleRaw : void 0;
4949
4949
  const rowCantSplit = rowPropertiesXml ? parseOnOffAttribute(rowPropertiesXml, "cantSplit") : void 0;
4950
+ const rowIsHeader = rowPropertiesXml ? parseOnOffAttribute(rowPropertiesXml, "tblHeader") : void 0;
4950
4951
  const parsedCells = extractBalancedTagBlocks(rowXml, "w:tc").map(
4951
4952
  (cellXml) => parseTableCell(cellXml, context)
4952
4953
  );
@@ -5003,11 +5004,12 @@ function parseTable(tableXml2, context) {
5003
5004
  rows.push({
5004
5005
  type: "table-row",
5005
5006
  cells,
5006
- style: rowBackgroundColor !== void 0 || rowHeightTwips !== void 0 || rowHeightRule !== void 0 || rowCantSplit !== void 0 ? {
5007
+ style: rowBackgroundColor !== void 0 || rowHeightTwips !== void 0 || rowHeightRule !== void 0 || rowCantSplit !== void 0 || rowIsHeader !== void 0 ? {
5007
5008
  backgroundColor: rowBackgroundColor,
5008
5009
  heightTwips: rowHeightTwips,
5009
5010
  ...rowHeightRule !== void 0 ? { heightRule: rowHeightRule } : void 0,
5010
- ...rowCantSplit !== void 0 ? { cantSplit: rowCantSplit } : void 0
5011
+ ...rowCantSplit !== void 0 ? { cantSplit: rowCantSplit } : void 0,
5012
+ ...rowIsHeader !== void 0 ? { isHeader: rowIsHeader } : void 0
5011
5013
  } : void 0
5012
5014
  });
5013
5015
  }
@@ -9122,18 +9124,63 @@ function collectTopLevelExplicitPageBreakStartNodeIndexes(nodes) {
9122
9124
  }
9123
9125
 
9124
9126
  // src/page-count-reconciliation.ts
9127
+ var PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS = 10;
9125
9128
  function shouldAllowStoredPageCountReduction(options) {
9126
- const estimatedPageCount = Math.max(1, Math.round(options.estimatedPageCount));
9129
+ const estimatedPageCount = Math.max(
9130
+ 1,
9131
+ Math.round(options.estimatedPageCount)
9132
+ );
9127
9133
  const targetPageCount = Math.max(1, Math.round(options.targetPageCount));
9128
9134
  if (targetPageCount >= estimatedPageCount) {
9129
9135
  return true;
9130
9136
  }
9137
+ if (options.hasMeasuredBodyFooterOverlap === true) {
9138
+ return false;
9139
+ }
9131
9140
  if (options.hasLastRenderedPageBreakHints !== true) {
9132
9141
  return true;
9133
9142
  }
9134
- const renderedBreakHintPageCount = Number.isFinite(options.renderedBreakHintPageCount) ? Math.max(1, Math.round(options.renderedBreakHintPageCount)) : void 0;
9143
+ const renderedBreakHintPageCount = Number.isFinite(
9144
+ options.renderedBreakHintPageCount
9145
+ ) ? Math.max(1, Math.round(options.renderedBreakHintPageCount)) : void 0;
9135
9146
  return renderedBreakHintPageCount !== void 0 && targetPageCount >= renderedBreakHintPageCount;
9136
9147
  }
9148
+ function shouldLatchMeasuredBodyFooterOverlap(options) {
9149
+ if (options.measuredBodyFooterOverlap !== true) {
9150
+ return false;
9151
+ }
9152
+ const targetPageCount = Number.isFinite(options.targetPageCount) ? Math.max(1, Math.round(options.targetPageCount)) : void 0;
9153
+ if (targetPageCount === void 0) {
9154
+ return false;
9155
+ }
9156
+ const pageCount = Math.max(1, Math.round(options.pageCount));
9157
+ return pageCount <= targetPageCount;
9158
+ }
9159
+ function resolveMeasuredBodyFooterOverlapLatchState(options) {
9160
+ const shouldConsiderMeasuredBodyFooterOverlap = shouldLatchMeasuredBodyFooterOverlap({
9161
+ pageCount: options.pageCount,
9162
+ targetPageCount: options.targetPageCount,
9163
+ measuredBodyFooterOverlap: options.overlappingPageIndexes.length > 0
9164
+ });
9165
+ if (!shouldConsiderMeasuredBodyFooterOverlap) {
9166
+ return {
9167
+ signature: void 0,
9168
+ consecutivePasses: 0,
9169
+ shouldLatch: false
9170
+ };
9171
+ }
9172
+ const signature = options.overlappingPageIndexes.map((pageIndex) => `${pageIndex}`).join("|");
9173
+ const consecutivePasses = signature === options.previousSignature ? Math.max(0, Math.round(options.previousConsecutivePasses ?? 0)) + 1 : 1;
9174
+ const stabilityThreshold = Math.max(
9175
+ 1,
9176
+ Math.round(options.stabilityThreshold ?? 1)
9177
+ );
9178
+ return {
9179
+ signature,
9180
+ consecutivePasses,
9181
+ shouldLatch: consecutivePasses >= stabilityThreshold
9182
+ };
9183
+ }
9137
9184
  function isBetterCandidate(candidate, incumbent, targetPageCount) {
9138
9185
  const candidateDifference = Math.abs(candidate.pageCount - targetPageCount);
9139
9186
  const incumbentDifference = Math.abs(incumbent.pageCount - targetPageCount);
@@ -9147,7 +9194,7 @@ function isBetterCandidate(candidate, incumbent, targetPageCount) {
9147
9194
  }
9148
9195
  return candidate.pageCount === targetPageCount && incumbent.pageCount !== targetPageCount;
9149
9196
  }
9150
- function reconcilePagesToTargetCountByScalingHeight(options) {
9197
+ function reconcilePageCountCandidateToTargetCountByScalingHeight(options) {
9151
9198
  const {
9152
9199
  initialPages,
9153
9200
  targetPageCount,
@@ -9159,7 +9206,11 @@ function reconcilePagesToTargetCountByScalingHeight(options) {
9159
9206
  const initialPageCount = initialPages.length;
9160
9207
  const initialDifference = Math.abs(initialPageCount - safeTargetPageCount);
9161
9208
  if (initialDifference === 0 || initialDifference > maxDifference) {
9162
- return initialPages;
9209
+ return {
9210
+ pageCount: initialPageCount,
9211
+ pages: initialPages,
9212
+ scale: 1
9213
+ };
9163
9214
  }
9164
9215
  const bestCandidate = {
9165
9216
  pageCount: initialPageCount,
@@ -9209,30 +9260,81 @@ function reconcilePagesToTargetCountByScalingHeight(options) {
9209
9260
  0.24,
9210
9261
  0.22,
9211
9262
  0.2
9212
- ] : [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];
9213
- for (const scale of scales) {
9263
+ ] : [
9264
+ 1.02,
9265
+ 1.04,
9266
+ 1.06,
9267
+ 1.08,
9268
+ 1.1,
9269
+ 1.12,
9270
+ 1.14,
9271
+ 1.16,
9272
+ 1.18,
9273
+ 1.2,
9274
+ 1.22,
9275
+ 1.24,
9276
+ 1.26,
9277
+ 1.28,
9278
+ 1.3
9279
+ ];
9280
+ const buildCandidateAtScale = (scale) => {
9214
9281
  const pages = buildPagesAtScale(scale);
9215
- const candidate = {
9282
+ return {
9216
9283
  pageCount: pages.length,
9217
9284
  pages,
9218
9285
  scale
9219
9286
  };
9287
+ };
9288
+ const refineExactTargetCandidate = (lowerScale, upperScale) => {
9289
+ let bestExactCandidate;
9290
+ const interval = upperScale - lowerScale;
9291
+ if (!Number.isFinite(interval) || Math.abs(interval) < 1e-4) {
9292
+ return selectedCandidate;
9293
+ }
9294
+ for (let step = 1; step <= PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS; step += 1) {
9295
+ const scale = lowerScale + interval * step / PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS;
9296
+ const candidate = buildCandidateAtScale(scale);
9297
+ if (isBetterCandidate(candidate, selectedCandidate, safeTargetPageCount)) {
9298
+ selectedCandidate = candidate;
9299
+ }
9300
+ if (candidate.pageCount === safeTargetPageCount && (bestExactCandidate === void 0 || isBetterCandidate(
9301
+ candidate,
9302
+ bestExactCandidate,
9303
+ safeTargetPageCount
9304
+ ))) {
9305
+ bestExactCandidate = candidate;
9306
+ }
9307
+ }
9308
+ return bestExactCandidate ?? selectedCandidate;
9309
+ };
9310
+ let previousScale = 1;
9311
+ let previousPageCount = initialPageCount;
9312
+ for (const scale of scales) {
9313
+ const candidate = buildCandidateAtScale(scale);
9220
9314
  if (isBetterCandidate(candidate, selectedCandidate, safeTargetPageCount)) {
9221
9315
  selectedCandidate = candidate;
9222
9316
  }
9223
9317
  if (candidate.pageCount === safeTargetPageCount) {
9224
- return candidate.pages;
9318
+ const crossedIntoExactTarget = needMorePages ? previousPageCount < safeTargetPageCount : previousPageCount > safeTargetPageCount;
9319
+ if (crossedIntoExactTarget) {
9320
+ return refineExactTargetCandidate(previousScale, scale);
9321
+ }
9322
+ return candidate;
9225
9323
  }
9324
+ previousScale = scale;
9325
+ previousPageCount = candidate.pageCount;
9226
9326
  }
9227
- return selectedCandidate.pages;
9327
+ return selectedCandidate;
9228
9328
  }
9229
9329
 
9230
9330
  // src/pretext-layout.ts
9231
9331
  var import_pretext = require("@chenglou/pretext");
9232
- var PREPARED_TEXT_CACHE_MAX_ENTRIES = 512;
9233
- var LAYOUT_CACHE_MAX_ENTRIES = 256;
9332
+ var PREPARED_TEXT_CACHE_MAX_ENTRIES = 8192;
9333
+ var LAYOUT_CACHE_MAX_ENTRIES = 4096;
9334
+ var LINE_COUNT_CACHE_MAX_ENTRIES = 16384;
9234
9335
  var preparedTextByKey = /* @__PURE__ */ new Map();
9235
9336
  var layoutByKey = /* @__PURE__ */ new Map();
9337
+ var lineCountByKey = /* @__PURE__ */ new Map();
9236
9338
  var fragmentOffsetAdvancesByFragment = /* @__PURE__ */ new WeakMap();
9237
9339
  var graphemeOffsetsByText = /* @__PURE__ */ new Map();
9238
9340
  var measureCanvas;
@@ -9241,6 +9343,24 @@ var graphemeSegmenter;
9241
9343
  function canUsePretext() {
9242
9344
  return typeof OffscreenCanvas !== "undefined" || typeof document !== "undefined";
9243
9345
  }
9346
+ function getCachedValue(cache, key) {
9347
+ const cached = cache.get(key);
9348
+ if (cached === void 0) {
9349
+ return void 0;
9350
+ }
9351
+ cache.delete(key);
9352
+ cache.set(key, cached);
9353
+ return cached;
9354
+ }
9355
+ function trimCache(cache, maxEntries) {
9356
+ while (cache.size > maxEntries) {
9357
+ const firstKey = cache.keys().next().value;
9358
+ if (firstKey === void 0) {
9359
+ break;
9360
+ }
9361
+ cache.delete(firstKey);
9362
+ }
9363
+ }
9244
9364
  function getMeasureContext() {
9245
9365
  if (!canUsePretext()) {
9246
9366
  return void 0;
@@ -9427,7 +9547,7 @@ function prepareCached(text, font, wordBreak = "normal") {
9427
9547
  return void 0;
9428
9548
  }
9429
9549
  const cacheKey = `${font}\0${wordBreak}\0${text}`;
9430
- const cached = preparedTextByKey.get(cacheKey);
9550
+ const cached = getCachedValue(preparedTextByKey, cacheKey);
9431
9551
  if (cached) {
9432
9552
  return cached;
9433
9553
  }
@@ -9437,18 +9557,36 @@ function prepareCached(text, font, wordBreak = "normal") {
9437
9557
  wordBreak
9438
9558
  });
9439
9559
  preparedTextByKey.set(cacheKey, prepared);
9440
- while (preparedTextByKey.size > PREPARED_TEXT_CACHE_MAX_ENTRIES) {
9441
- const firstKey = preparedTextByKey.keys().next().value;
9442
- if (!firstKey) {
9443
- break;
9444
- }
9445
- preparedTextByKey.delete(firstKey);
9446
- }
9560
+ trimCache(preparedTextByKey, PREPARED_TEXT_CACHE_MAX_ENTRIES);
9447
9561
  return prepared;
9448
9562
  } catch {
9449
9563
  return void 0;
9450
9564
  }
9451
9565
  }
9566
+ function measurePretextPlainTextLineCount(text, font, containerWidthPx, options) {
9567
+ if (!text) {
9568
+ return 0;
9569
+ }
9570
+ const wordBreak = options?.wordBreak ?? "normal";
9571
+ const safeWidth = Math.max(1, Math.round(containerWidthPx));
9572
+ const cacheKey = `line-count\0${font}\0${wordBreak}\0${safeWidth}\0${text}`;
9573
+ const cached = getCachedValue(lineCountByKey, cacheKey);
9574
+ if (cached !== void 0) {
9575
+ return cached;
9576
+ }
9577
+ const prepared = prepareCached(text, font, wordBreak);
9578
+ if (!prepared) {
9579
+ return void 0;
9580
+ }
9581
+ try {
9582
+ const lineCount = (0, import_pretext.measureLineStats)(prepared, safeWidth).lineCount;
9583
+ lineCountByKey.set(cacheKey, lineCount);
9584
+ trimCache(lineCountByKey, LINE_COUNT_CACHE_MAX_ENTRIES);
9585
+ return lineCount;
9586
+ } catch {
9587
+ return void 0;
9588
+ }
9589
+ }
9452
9590
  function cloneItemCursor(cursor) {
9453
9591
  return {
9454
9592
  itemIndex: cursor.itemIndex,
@@ -9704,7 +9842,7 @@ function layoutTextWithPretextAroundExclusions(text, font, containerWidthPx, lin
9704
9842
  safeLineHeightPx,
9705
9843
  normalizedExclusions
9706
9844
  );
9707
- const cachedLayout = layoutByKey.get(cacheKey);
9845
+ const cachedLayout = getCachedValue(layoutByKey, cacheKey);
9708
9846
  if (cachedLayout) {
9709
9847
  return cachedLayout;
9710
9848
  }
@@ -9778,13 +9916,7 @@ function layoutTextWithPretextAroundExclusions(text, font, containerWidthPx, lin
9778
9916
  exclusions: normalizedExclusions
9779
9917
  };
9780
9918
  layoutByKey.set(cacheKey, nextLayout);
9781
- while (layoutByKey.size > LAYOUT_CACHE_MAX_ENTRIES) {
9782
- const firstKey = layoutByKey.keys().next().value;
9783
- if (!firstKey) {
9784
- break;
9785
- }
9786
- layoutByKey.delete(firstKey);
9787
- }
9919
+ trimCache(layoutByKey, LAYOUT_CACHE_MAX_ENTRIES);
9788
9920
  return nextLayout;
9789
9921
  }
9790
9922
  function layoutItemsWithPretextAroundExclusions(text, items, containerWidthPx, lineHeightPx, exclusions, fallbackFont) {
@@ -9836,7 +9968,7 @@ function layoutItemsWithPretextAroundExclusions(text, items, containerWidthPx, l
9836
9968
  safeLineHeightPx,
9837
9969
  normalizedExclusions
9838
9970
  );
9839
- const cachedLayout = layoutByKey.get(cacheKey);
9971
+ const cachedLayout = getCachedValue(layoutByKey, cacheKey);
9840
9972
  if (cachedLayout) {
9841
9973
  return cachedLayout;
9842
9974
  }
@@ -9950,13 +10082,7 @@ function layoutItemsWithPretextAroundExclusions(text, items, containerWidthPx, l
9950
10082
  exclusions: normalizedExclusions
9951
10083
  };
9952
10084
  layoutByKey.set(cacheKey, nextLayout);
9953
- while (layoutByKey.size > LAYOUT_CACHE_MAX_ENTRIES) {
9954
- const firstKey = layoutByKey.keys().next().value;
9955
- if (!firstKey) {
9956
- break;
9957
- }
9958
- layoutByKey.delete(firstKey);
9959
- }
10085
+ trimCache(layoutByKey, LAYOUT_CACHE_MAX_ENTRIES);
9960
10086
  return nextLayout;
9961
10087
  }
9962
10088
  function resolveOffsetAtPoint(layout, x, y) {
@@ -10190,7 +10316,7 @@ var SCRIPT_FONT_SCALE = 0.65;
10190
10316
  var DEFAULT_PARAGRAPH_LINE_MULTIPLE = 1;
10191
10317
  var WORD_SINGLE_LINE_AUTO_SCALE = 0.88;
10192
10318
  var WORD_SINGLE_LINE_AUTO_SCALE_SANS = 0.9;
10193
- var WORD_SINGLE_LINE_AUTO_SCALE_SERIF = 1.12;
10319
+ var WORD_SINGLE_LINE_AUTO_SCALE_SERIF = 1.08;
10194
10320
  var WORD_AUTO_LINE_SCALE_BLEND_END_MULTIPLE = 1.08;
10195
10321
  var MIN_AUTO_LINE_MULTIPLE = 0.1;
10196
10322
  var MIN_PARAGRAPH_LINE_HEIGHT_PX = 14;
@@ -10200,10 +10326,12 @@ var MEASURED_PAGE_FOOTER_CLEARANCE_BUFFER_PX = 24;
10200
10326
  var UNOVERLAPPED_FOOTER_MIN_CLEARANCE_PX = 16;
10201
10327
  var FLOATING_FOOTER_BASELINE_CLEARANCE_RESERVE_PX = 16;
10202
10328
  var PAGINATION_MEASUREMENT_INTERACTION_DEBOUNCE_MS = 180;
10329
+ var MEASURED_BODY_FOOTER_OVERLAP_STABILITY_THRESHOLD = 3;
10203
10330
  var WORD_TABLE_CELL_PARAGRAPH_AUTO_LINE_TWIPS = 240;
10204
10331
  var WORD_TABLE_CELL_PARAGRAPH_BEFORE_TWIPS = 0;
10205
10332
  var WORD_TABLE_CELL_PARAGRAPH_AFTER_TWIPS = 0;
10206
10333
  var TABLE_ROW_SLICE_VISUAL_BLEED_PX = 1;
10334
+ var TABLE_CELL_SLICE_FULLY_VISIBLE_BOTTOM_BUFFER_PX = 4;
10207
10335
  var DEFAULT_SPLIT_PARAGRAPH_LINE_TWIPS = 259;
10208
10336
  var DEFAULT_SPLIT_PARAGRAPH_AFTER_TWIPS = 160;
10209
10337
  var PAGE_CONTENT_MEASUREMENT_IGNORE_ATTRIBUTE = "data-docx-pagination-ignore";
@@ -10236,15 +10364,21 @@ var LEADING_COVER_SPACER_EXTRA_HEIGHT_PX = 2;
10236
10364
  var PARAGRAPH_SEGMENT_TOP_BLEED_PX = 22;
10237
10365
  var PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX = 6;
10238
10366
  var PARAGRAPH_SEGMENT_VISUAL_SAFETY_PX = 24;
10367
+ var LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_RATIO = 0.18;
10368
+ var LAST_RENDERED_PAGE_BREAK_HINT_MIN_REMAINING_SPACE_PX = MIN_PARAGRAPH_LINE_HEIGHT_PX * 3;
10369
+ var LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_PX = 120;
10239
10370
  var PARAGRAPH_SEGMENT_FALLBACK_TOP_BLEED_MAX_PX = 4;
10240
10371
  var PARAGRAPH_SEGMENT_FALLBACK_BOTTOM_BLEED_MAX_PX = 0;
10241
10372
  var PARAGRAPH_SEGMENT_FALLBACK_VISUAL_SAFETY_PX = 4;
10242
10373
  var INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT = 8;
10243
10374
  var INITIAL_PAGINATION_PAGE_COUNT_OSCILLATION_DISTINCT_THRESHOLD = 2;
10244
10375
  var INITIAL_PAGINATION_PAGE_COUNT_OSCILLATION_CHANGE_THRESHOLD = 4;
10376
+ var INITIAL_PAGINATION_BACKGROUND_REFINEMENT_DELAY_MS = 96;
10245
10377
  var DEFAULT_PAGE_VIRTUALIZATION_OVERSCAN = 2;
10378
+ var LARGE_TABLE_PAGE_VIRTUALIZATION_OVERSCAN = 0;
10379
+ var LARGE_TABLE_PAGE_ADJACENT_RENDER_COUNT = 1;
10246
10380
  var DEFAULT_PAGE_VIRTUALIZATION_SETTLE_DELAY_MS = 350;
10247
- var ENABLE_TABLE_ROW_SLICING = false;
10381
+ var ENABLE_TABLE_ROW_SLICING = true;
10248
10382
  var TOP_AND_BOTTOM_VERTICAL_DRAG_SNAP_PX = 10;
10249
10383
  var HEADER_FOOTER_INACTIVE_OPACITY = 0.5;
10250
10384
  var LETTERHEAD_INDENT_MIN_TWIPS = 900;
@@ -10549,7 +10683,11 @@ function nearestScrollableAncestor(element) {
10549
10683
  }
10550
10684
  current = current.parentElement;
10551
10685
  }
10552
- return null;
10686
+ const scrollingElement = typeof document !== "undefined" ? document.scrollingElement : null;
10687
+ if (scrollingElement instanceof HTMLElement) {
10688
+ return scrollingElement;
10689
+ }
10690
+ return typeof document !== "undefined" ? document.documentElement : null;
10553
10691
  }
10554
10692
  function resolveEffectiveZoomScale(element) {
10555
10693
  let current = element;
@@ -10651,7 +10789,7 @@ function normalizeMeasuredTableRowHeightPx(heightPx) {
10651
10789
  }
10652
10790
  return Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, Math.round(heightPx));
10653
10791
  }
10654
- function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowHeights, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx) {
10792
+ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowHeights, maxAvailableWidthPx, pageContentHeightPx, numberingDefinitions, docGridLinePitchPx) {
10655
10793
  if (measuredRowHeights.length !== table.rows.length) {
10656
10794
  return void 0;
10657
10795
  }
@@ -10659,7 +10797,8 @@ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowH
10659
10797
  table,
10660
10798
  maxAvailableWidthPx,
10661
10799
  numberingDefinitions,
10662
- docGridLinePitchPx
10800
+ docGridLinePitchPx,
10801
+ pageContentHeightPx
10663
10802
  );
10664
10803
  if (estimatedRowHeights.length !== table.rows.length) {
10665
10804
  return void 0;
@@ -10667,6 +10806,7 @@ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowH
10667
10806
  return measuredRowHeights.map((heightPx, rowIndex) => {
10668
10807
  const row = table.rows[rowIndex];
10669
10808
  const normalizedMeasuredHeightPx = normalizeMeasuredTableRowHeightPx(heightPx);
10809
+ const normalizedPageContentHeightPx = Number.isFinite(pageContentHeightPx) && pageContentHeightPx > 0 ? Math.max(120, Math.round(pageContentHeightPx)) : void 0;
10670
10810
  const estimatedHeightPx = Math.max(
10671
10811
  MIN_PARAGRAPH_LINE_HEIGHT_PX,
10672
10812
  Math.round(estimatedRowHeights[rowIndex] ?? MIN_PARAGRAPH_LINE_HEIGHT_PX)
@@ -10684,6 +10824,9 @@ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowH
10684
10824
  if (rowAllowsPageSplit(row) && row.style?.heightRule !== "exact") {
10685
10825
  return Math.max(explicitMinimumHeightPx, normalizedMeasuredHeightPx);
10686
10826
  }
10827
+ if (Number.isFinite(normalizedPageContentHeightPx) && normalizedMeasuredHeightPx > normalizedPageContentHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
10828
+ return Math.max(explicitMinimumHeightPx, normalizedMeasuredHeightPx);
10829
+ }
10687
10830
  const minimumHeightPx = Math.max(
10688
10831
  estimatedHeightPx,
10689
10832
  explicitMinimumHeightPx
@@ -10729,6 +10872,7 @@ function resolveTableMeasuredRowHeightsForPagination(nodes, tableMeasuredRowHeig
10729
10872
  tableNode,
10730
10873
  measuredRowHeights,
10731
10874
  options?.pageContentWidthPxByNodeIndex?.get(tableIndex),
10875
+ options?.pageContentHeightPxByNodeIndex?.get(tableIndex),
10732
10876
  options?.numberingDefinitions,
10733
10877
  options?.docGridLinePitchPxByNodeIndex?.get(tableIndex)
10734
10878
  ) ?? measuredRowHeights.map(
@@ -11493,9 +11637,9 @@ function resolveFooterPaginationReservePx(footerSections, layout) {
11493
11637
  )
11494
11638
  );
11495
11639
  const footerBodyOverlapPx = estimatedFooterHeightPx + layout.footerDistancePx - layout.marginsPx.bottom;
11496
- const explicitFooterOverlapReservePx = Math.max(
11640
+ const explicitFooterBoundaryReservePx = Math.max(
11497
11641
  0,
11498
- Math.round(footerBodyOverlapPx)
11642
+ Math.round(footerBodyOverlapPx + UNOVERLAPPED_FOOTER_MIN_CLEARANCE_PX)
11499
11643
  );
11500
11644
  const floatingFooterBoundaryReservePx = Number.isFinite(
11501
11645
  floatingFooterBoundaryTopPx
@@ -11507,13 +11651,13 @@ function resolveFooterPaginationReservePx(footerSections, layout) {
11507
11651
  ) : 0;
11508
11652
  if (hasFloatingFooterBodyIntrusionRisk) {
11509
11653
  return Math.max(
11510
- explicitFooterOverlapReservePx,
11654
+ explicitFooterBoundaryReservePx,
11511
11655
  floatingFooterBoundaryReservePx,
11512
11656
  FLOATING_FOOTER_BASELINE_CLEARANCE_RESERVE_PX
11513
11657
  );
11514
11658
  }
11515
11659
  return Math.max(
11516
- explicitFooterOverlapReservePx,
11660
+ explicitFooterBoundaryReservePx,
11517
11661
  floatingFooterBoundaryReservePx
11518
11662
  );
11519
11663
  }
@@ -11733,7 +11877,7 @@ function resolvePageContentHeightPxForPageSegments(pageSegments, pageIndex, defa
11733
11877
  );
11734
11878
  }
11735
11879
  function resolveRenderPageContentHeightPxForPageSegments(params) {
11736
- return resolvePageContentHeightPxForPageSegments(
11880
+ const resolvedHeightPx = resolvePageContentHeightPxForPageSegments(
11737
11881
  params.pageSegments,
11738
11882
  params.pageIndex,
11739
11883
  params.defaultPageContentHeightPx,
@@ -11742,6 +11886,13 @@ function resolveRenderPageContentHeightPxForPageSegments(params) {
11742
11886
  params.useMeasuredPageContentHeights === false ? void 0 : params.measuredPageContentIdentityKeysByPageIndex,
11743
11887
  params.pageIdentityKey
11744
11888
  );
11889
+ if (params.useMeasuredPageContentHeights === false && Number.isFinite(params.pageContentHeightScale) && Math.abs(params.pageContentHeightScale - 1) >= 1e-3) {
11890
+ return Math.max(
11891
+ 120,
11892
+ Math.round(resolvedHeightPx * params.pageContentHeightScale)
11893
+ );
11894
+ }
11895
+ return resolvedHeightPx;
11745
11896
  }
11746
11897
  function documentPageContainsOnlySplitParagraphSegments(pageSegments) {
11747
11898
  return pageSegments.length > 0 && pageSegments.every(
@@ -12278,28 +12429,74 @@ function nodeTreeContainsExplicitFontFamily(nodes) {
12278
12429
  return false;
12279
12430
  });
12280
12431
  }
12432
+ function firstExplicitFontFamilyInNodeTree(nodes) {
12433
+ for (const node of nodes) {
12434
+ if (node.type === "paragraph") {
12435
+ for (const child of node.children) {
12436
+ if (child.type !== "text" && child.type !== "form-field") {
12437
+ continue;
12438
+ }
12439
+ const fontFamily = child.style?.fontFamily?.trim();
12440
+ if (fontFamily) {
12441
+ return fontFamily;
12442
+ }
12443
+ }
12444
+ continue;
12445
+ }
12446
+ if (node.type === "table") {
12447
+ for (const row of node.rows) {
12448
+ for (const cell of row.cells) {
12449
+ const nestedFontFamily = firstExplicitFontFamilyInNodeTree(cell.nodes);
12450
+ if (nestedFontFamily) {
12451
+ return nestedFontFamily;
12452
+ }
12453
+ }
12454
+ }
12455
+ }
12456
+ }
12457
+ return void 0;
12458
+ }
12281
12459
  function resolveDocumentInheritedFontFamily(model) {
12282
12460
  const paragraphStyles = model.metadata.paragraphStyles ?? [];
12283
- const styleDefinesFontFamily = paragraphStyles.some(
12461
+ const normalizedDefaultStyleId = model.metadata.defaultParagraphStyleId?.trim().toLowerCase() ?? "";
12462
+ const defaultParagraphStyle = paragraphStyles.find(
12463
+ (style) => style.id.trim().toLowerCase() === normalizedDefaultStyleId
12464
+ ) ?? paragraphStyles.find((style) => style.isDefault) ?? paragraphStyles.find((style) => style.id.trim().toLowerCase() === "normal");
12465
+ const defaultStyleFontFamily = defaultParagraphStyle?.runStyle?.fontFamily?.trim();
12466
+ if (defaultStyleFontFamily) {
12467
+ return cssFontFamily(defaultStyleFontFamily);
12468
+ }
12469
+ const paragraphStyleFontFamily = paragraphStyles.find(
12284
12470
  (style) => Boolean(style.runStyle?.fontFamily?.trim())
12285
- );
12286
- if (styleDefinesFontFamily) {
12287
- return void 0;
12471
+ )?.runStyle?.fontFamily;
12472
+ if (paragraphStyleFontFamily) {
12473
+ return cssFontFamily(paragraphStyleFontFamily);
12288
12474
  }
12289
- if (nodeTreeContainsExplicitFontFamily(model.nodes)) {
12290
- return void 0;
12475
+ const explicitBodyFontFamily = firstExplicitFontFamilyInNodeTree(model.nodes);
12476
+ if (explicitBodyFontFamily) {
12477
+ return cssFontFamily(explicitBodyFontFamily);
12291
12478
  }
12292
- if ((model.metadata.headerSections ?? []).some(
12293
- (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12294
- )) {
12295
- return void 0;
12479
+ for (const section of model.metadata.headerSections ?? []) {
12480
+ const explicitHeaderFontFamily = firstExplicitFontFamilyInNodeTree(
12481
+ section.nodes
12482
+ );
12483
+ if (explicitHeaderFontFamily) {
12484
+ return cssFontFamily(explicitHeaderFontFamily);
12485
+ }
12296
12486
  }
12297
- if ((model.metadata.footerSections ?? []).some(
12298
- (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12299
- )) {
12300
- return void 0;
12487
+ for (const section of model.metadata.footerSections ?? []) {
12488
+ const explicitFooterFontFamily = firstExplicitFontFamilyInNodeTree(
12489
+ section.nodes
12490
+ );
12491
+ if (explicitFooterFontFamily) {
12492
+ return cssFontFamily(explicitFooterFontFamily);
12493
+ }
12301
12494
  }
12302
- return cssFontFamily(DEFAULT_UNSPECIFIED_DOCX_FONT_FAMILY);
12495
+ return nodeTreeContainsExplicitFontFamily(model.nodes) || (model.metadata.headerSections ?? []).some(
12496
+ (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12497
+ ) || (model.metadata.footerSections ?? []).some(
12498
+ (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12499
+ ) ? void 0 : cssFontFamily(DEFAULT_UNSPECIFIED_DOCX_FONT_FAMILY);
12303
12500
  }
12304
12501
  function replaceTabLayoutMarkersWithTabText(root) {
12305
12502
  const centerLayouts = Array.from(
@@ -12667,6 +12864,11 @@ function sectionNodesNeedFullPageFooterOverlay(nodes) {
12667
12864
  function paragraphHasFormField2(paragraph) {
12668
12865
  return paragraph.children.some((child) => child.type === "form-field");
12669
12866
  }
12867
+ function paragraphHasCheckboxFormField(paragraph) {
12868
+ return paragraph.children.some(
12869
+ (child) => child.type === "form-field" && child.fieldType === "checkbox"
12870
+ );
12871
+ }
12670
12872
  function paragraphHasVisibleText2(paragraph) {
12671
12873
  return paragraph.children.some(
12672
12874
  (child) => child.type === "text" && child.text.trim().length > 0 || child.type === "form-field" && formFieldDisplayValue2(child).trim().length > 0
@@ -12985,6 +13187,9 @@ function paragraphLooksLikeCheckboxChoiceRow(paragraph) {
12985
13187
  }
12986
13188
  var KEEP_ALL_SCRIPT_RE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u;
12987
13189
  var MIN_DUAL_WRAPPED_INTERIOR_BAND_PX = 72;
13190
+ var paragraphPretextLayoutSourceCache = /* @__PURE__ */ new WeakMap();
13191
+ var paragraphPretextLayoutItemsBySource = /* @__PURE__ */ new WeakMap();
13192
+ var paragraphPretextUniformFontBySource = /* @__PURE__ */ new WeakMap();
12988
13193
  function imageWrapModeFromFloating(floating) {
12989
13194
  if (!floating) {
12990
13195
  return "inline";
@@ -13130,16 +13335,67 @@ function resolveFloatingForImageWrapMode(mode, currentFloating, seedFloating) {
13130
13335
  };
13131
13336
  }
13132
13337
  }
13338
+ function buildParagraphPretextTabSpacerText(widthPx, style, paragraphBaseFontPx) {
13339
+ const safeWidthPx = Math.max(8, Math.round(widthPx));
13340
+ const spacerCharacter = "\xA0";
13341
+ const spacerAdvancePx = Math.max(
13342
+ 1,
13343
+ measureTextWidthPx2(spacerCharacter, style, paragraphBaseFontPx)
13344
+ );
13345
+ let spacerCount = Math.max(1, Math.round(safeWidthPx / spacerAdvancePx));
13346
+ let spacerText = spacerCharacter.repeat(spacerCount);
13347
+ let measuredWidthPx = measureTextWidthPx2(
13348
+ spacerText,
13349
+ style,
13350
+ paragraphBaseFontPx
13351
+ );
13352
+ while (measuredWidthPx + spacerAdvancePx * 0.5 < safeWidthPx && spacerCount < 64) {
13353
+ spacerCount += 1;
13354
+ spacerText = spacerCharacter.repeat(spacerCount);
13355
+ measuredWidthPx = measureTextWidthPx2(spacerText, style, paragraphBaseFontPx);
13356
+ }
13357
+ while (spacerCount > 1) {
13358
+ const nextText = spacerCharacter.repeat(spacerCount - 1);
13359
+ const nextWidthPx = measureTextWidthPx2(nextText, style, paragraphBaseFontPx);
13360
+ if (Math.abs(nextWidthPx - safeWidthPx) >= Math.abs(measuredWidthPx - safeWidthPx)) {
13361
+ break;
13362
+ }
13363
+ spacerCount -= 1;
13364
+ spacerText = nextText;
13365
+ measuredWidthPx = nextWidthPx;
13366
+ }
13367
+ return spacerText;
13368
+ }
13133
13369
  function buildParagraphPretextLayoutSource(paragraph, options) {
13370
+ const cacheKey = (options?.allowExplicitLineBreakText ? 1 : 0) | (options?.expandTabsForLayout ? 2 : 0);
13371
+ const cachedVariants = paragraphPretextLayoutSourceCache.get(paragraph);
13372
+ const cachedSource = cachedVariants?.get(cacheKey);
13373
+ if (cachedSource !== void 0) {
13374
+ return cachedSource ?? void 0;
13375
+ }
13376
+ const storeCachedSource = (source) => {
13377
+ if (!cachedVariants) {
13378
+ paragraphPretextLayoutSourceCache.set(
13379
+ paragraph,
13380
+ /* @__PURE__ */ new Map([[cacheKey, source ?? null]])
13381
+ );
13382
+ } else {
13383
+ cachedVariants.set(cacheKey, source ?? null);
13384
+ }
13385
+ return source;
13386
+ };
13134
13387
  if (paragraphHasFormField2(paragraph)) {
13135
- return void 0;
13388
+ return storeCachedSource(void 0);
13136
13389
  }
13137
13390
  if (!options?.allowExplicitLineBreakText && paragraphContainsExplicitLineBreakText(paragraph)) {
13138
- return void 0;
13391
+ return storeCachedSource(void 0);
13139
13392
  }
13140
13393
  const runs = [];
13141
13394
  let combinedText = "";
13142
13395
  const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
13396
+ const tabStopPositionsPx = options?.expandTabsForLayout ? resolveParagraphTabStopsPx(paragraph) : [];
13397
+ const fallbackTabWidthPx = paragraphLooksLikeCheckboxChoiceRow(paragraph) ? checkboxChoiceRowTabWidthPx(paragraph) : DEFAULT_TAB_STOP_PX;
13398
+ let approximateLineWidthPx = 0;
13143
13399
  let lastTextStyle = firstRunStyle(paragraph);
13144
13400
  for (let childIndex = 0; childIndex < paragraph.children.length; childIndex += 1) {
13145
13401
  const child = paragraph.children[childIndex];
@@ -13169,10 +13425,63 @@ function buildParagraphPretextLayoutSource(paragraph, options) {
13169
13425
  continue;
13170
13426
  }
13171
13427
  if (child.type !== "text") {
13172
- return void 0;
13173
- }
13174
- if (child.noteReference || child.text.includes(" ")) {
13175
- return void 0;
13428
+ return storeCachedSource(void 0);
13429
+ }
13430
+ if (child.noteReference) {
13431
+ return storeCachedSource(void 0);
13432
+ }
13433
+ if (child.text.includes(" ")) {
13434
+ if (!options?.expandTabsForLayout) {
13435
+ return storeCachedSource(void 0);
13436
+ }
13437
+ const tabSegments = child.text.split(" ");
13438
+ tabSegments.forEach((segmentText, segmentIndex) => {
13439
+ if (segmentText.length > 0) {
13440
+ const startOffset3 = combinedText.length;
13441
+ combinedText += segmentText;
13442
+ runs.push({
13443
+ kind: "text",
13444
+ key: `run-${childIndex}-${segmentIndex}`,
13445
+ text: segmentText,
13446
+ startOffset: startOffset3,
13447
+ endOffset: combinedText.length,
13448
+ style: child.style,
13449
+ link: child.link
13450
+ });
13451
+ approximateLineWidthPx = updateEstimatedLineWidthPxForText(
13452
+ approximateLineWidthPx,
13453
+ segmentText,
13454
+ child.style
13455
+ );
13456
+ }
13457
+ if (segmentIndex >= tabSegments.length - 1) {
13458
+ return;
13459
+ }
13460
+ const tabWidthPx = resolveTabSpacerWidthPx(
13461
+ tabStopPositionsPx,
13462
+ approximateLineWidthPx,
13463
+ fallbackTabWidthPx
13464
+ );
13465
+ const spacerText = buildParagraphPretextTabSpacerText(
13466
+ tabWidthPx,
13467
+ child.style,
13468
+ paragraphBaseFontPx
13469
+ );
13470
+ const startOffset2 = combinedText.length;
13471
+ combinedText += spacerText;
13472
+ runs.push({
13473
+ kind: "tab",
13474
+ key: `run-${childIndex}-${segmentIndex}-tab`,
13475
+ text: spacerText,
13476
+ startOffset: startOffset2,
13477
+ endOffset: combinedText.length,
13478
+ style: child.style,
13479
+ tabWidthPx
13480
+ });
13481
+ approximateLineWidthPx += tabWidthPx;
13482
+ });
13483
+ lastTextStyle = child.style ?? lastTextStyle;
13484
+ continue;
13176
13485
  }
13177
13486
  const startOffset = combinedText.length;
13178
13487
  combinedText += child.text;
@@ -13185,15 +13494,142 @@ function buildParagraphPretextLayoutSource(paragraph, options) {
13185
13494
  style: child.style,
13186
13495
  link: child.link
13187
13496
  });
13497
+ approximateLineWidthPx = updateEstimatedLineWidthPxForText(
13498
+ approximateLineWidthPx,
13499
+ child.text,
13500
+ child.style
13501
+ );
13188
13502
  lastTextStyle = child.style ?? lastTextStyle;
13189
13503
  }
13190
13504
  if (combinedText.length === 0) {
13191
- return void 0;
13505
+ return storeCachedSource(void 0);
13192
13506
  }
13193
- return {
13507
+ return storeCachedSource({
13194
13508
  text: combinedText,
13195
13509
  runs
13510
+ });
13511
+ }
13512
+ function splitParagraphAtExplicitColumnBreaks(paragraph) {
13513
+ if (!paragraphHasExplicitColumnBreak(paragraph)) {
13514
+ return void 0;
13515
+ }
13516
+ const paragraphChildren = [];
13517
+ let currentChildren = [];
13518
+ let sawExplicitColumnBreak = false;
13519
+ const appendCurrentSegment = () => {
13520
+ paragraphChildren.push(currentChildren);
13521
+ currentChildren = [];
13196
13522
  };
13523
+ for (let childIndex = 0; childIndex < paragraph.children.length; childIndex += 1) {
13524
+ const child = paragraph.children[childIndex];
13525
+ if (!child) {
13526
+ continue;
13527
+ }
13528
+ if (child.type === "text") {
13529
+ if (/^[\r\n]+$/.test(child.text)) {
13530
+ const explicitBreakCount = child.text.replace(/[^\n]/g, "").length;
13531
+ if (explicitBreakCount > 0) {
13532
+ for (let breakIndex = 0; breakIndex < explicitBreakCount; breakIndex += 1) {
13533
+ sawExplicitColumnBreak = true;
13534
+ appendCurrentSegment();
13535
+ }
13536
+ continue;
13537
+ }
13538
+ }
13539
+ currentChildren.push(cloneTextRunWithMetadata(child));
13540
+ continue;
13541
+ }
13542
+ if (child.type === "form-field") {
13543
+ currentChildren.push(cloneFormFieldRun2(child));
13544
+ continue;
13545
+ }
13546
+ return void 0;
13547
+ }
13548
+ if (!sawExplicitColumnBreak) {
13549
+ return void 0;
13550
+ }
13551
+ appendCurrentSegment();
13552
+ return paragraphChildren.map((children, segmentIndex) => {
13553
+ const nextStyle = cloneParagraphStyle2(paragraph.style);
13554
+ if (segmentIndex > 0 && nextStyle?.numbering) {
13555
+ nextStyle.numbering = void 0;
13556
+ }
13557
+ return {
13558
+ ...paragraph,
13559
+ style: nextStyle,
13560
+ sourceXml: void 0,
13561
+ children: children.length > 0 ? children : [
13562
+ {
13563
+ type: "text",
13564
+ text: ""
13565
+ }
13566
+ ]
13567
+ };
13568
+ });
13569
+ }
13570
+ function estimateParagraphContentHeightPx(paragraph, availableWidthPx, numberingDefinitions, docGridLinePitchPx) {
13571
+ if (!paragraphHasImage2(paragraph) && !paragraphHasFormField2(paragraph)) {
13572
+ const lineHeightPx = estimateParagraphLineHeightPx(
13573
+ paragraph,
13574
+ docGridLinePitchPx
13575
+ );
13576
+ const lineCount = paragraphLineCountWithinWidth(
13577
+ paragraph,
13578
+ availableWidthPx,
13579
+ numberingDefinitions
13580
+ );
13581
+ return Math.max(1, lineHeightPx * Math.max(1, lineCount));
13582
+ }
13583
+ return Math.max(
13584
+ 1,
13585
+ estimateParagraphHeightPx(
13586
+ paragraph,
13587
+ availableWidthPx,
13588
+ numberingDefinitions,
13589
+ docGridLinePitchPx
13590
+ ) - paragraphBeforeSpacingPx(paragraph) - paragraphAfterSpacingPx(paragraph)
13591
+ );
13592
+ }
13593
+ function projectParagraphConsumedHeightWithExplicitColumnBreaks(paragraphSegments, pageConsumedHeightPx, pageContentHeightPx, sectionFlowOriginPx, columnCount, availableWidthPx, beforeSpacingPx, afterSpacingPx, collapsedMarginPx, numberingDefinitions, docGridLinePitchPx) {
13594
+ if (paragraphSegments.length <= 1 || columnCount <= 1) {
13595
+ return void 0;
13596
+ }
13597
+ const normalizedParagraphStartPx = Math.max(
13598
+ 0,
13599
+ Math.max(pageConsumedHeightPx, sectionFlowOriginPx)
13600
+ );
13601
+ const firstSegmentTopSpacingPx = pageConsumedHeightPx > 0 ? Math.max(0, beforeSpacingPx - collapsedMarginPx) : beforeSpacingPx;
13602
+ const tallestSegmentHeightPx = paragraphSegments.reduce(
13603
+ (tallest, segment) => {
13604
+ return Math.max(
13605
+ tallest,
13606
+ estimateParagraphContentHeightPx(
13607
+ segment,
13608
+ availableWidthPx,
13609
+ numberingDefinitions,
13610
+ docGridLinePitchPx
13611
+ )
13612
+ );
13613
+ },
13614
+ 0
13615
+ );
13616
+ const projectedConsumedHeightPx = normalizedParagraphStartPx + firstSegmentTopSpacingPx + tallestSegmentHeightPx + afterSpacingPx;
13617
+ const sectionFlowCapacityPx = Math.max(
13618
+ 0,
13619
+ pageContentHeightPx - sectionFlowOriginPx
13620
+ );
13621
+ const sectionConsumedPx = Math.max(
13622
+ 0,
13623
+ pageConsumedHeightPx - sectionFlowOriginPx
13624
+ );
13625
+ const remainingColumnHeightPx = Math.max(
13626
+ 0,
13627
+ sectionFlowCapacityPx / columnCount - sectionConsumedPx
13628
+ );
13629
+ if (projectedConsumedHeightPx - pageConsumedHeightPx > remainingColumnHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
13630
+ return void 0;
13631
+ }
13632
+ return projectedConsumedHeightPx;
13197
13633
  }
13198
13634
  function buildSyntheticPretextLayoutSource(text, style) {
13199
13635
  return {
@@ -13217,16 +13653,50 @@ function sanitizeRenderedPretextFragmentText(text) {
13217
13653
  return text.replace(/\r\n?|\n/g, "");
13218
13654
  }
13219
13655
  function buildParagraphPretextLayoutItems(paragraph, source) {
13656
+ const cachedItems = paragraphPretextLayoutItemsBySource.get(source);
13657
+ if (cachedItems) {
13658
+ return cachedItems;
13659
+ }
13220
13660
  const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
13221
13661
  const wordBreak = pretextWordBreakModeForText(source.text);
13222
- return source.runs.filter((run) => run.endOffset > run.startOffset).map((run) => ({
13662
+ const items = source.runs.filter((run) => run.endOffset > run.startOffset).map((run) => ({
13223
13663
  text: run.text,
13224
13664
  font: resolveMeasureFont(run.style, paragraphBaseFontPx),
13225
13665
  startOffset: run.startOffset,
13226
13666
  endOffset: run.endOffset,
13227
- break: run.kind === "image" ? "never" : "normal",
13667
+ break: run.kind === "image" || run.kind === "tab" ? "never" : "normal",
13228
13668
  wordBreak
13229
13669
  }));
13670
+ paragraphPretextLayoutItemsBySource.set(source, items);
13671
+ return items;
13672
+ }
13673
+ function resolveUniformPretextSourceFont(paragraph, source) {
13674
+ const cachedUniformFont = paragraphPretextUniformFontBySource.get(source);
13675
+ if (cachedUniformFont !== void 0) {
13676
+ return cachedUniformFont ?? void 0;
13677
+ }
13678
+ const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
13679
+ let uniformFont;
13680
+ for (const run of source.runs) {
13681
+ if (run.endOffset <= run.startOffset) {
13682
+ continue;
13683
+ }
13684
+ if (run.kind !== "text") {
13685
+ paragraphPretextUniformFontBySource.set(source, null);
13686
+ return void 0;
13687
+ }
13688
+ const runFont = resolveMeasureFont(run.style, paragraphBaseFontPx);
13689
+ if (uniformFont === void 0) {
13690
+ uniformFont = runFont;
13691
+ continue;
13692
+ }
13693
+ if (runFont !== uniformFont) {
13694
+ paragraphPretextUniformFontBySource.set(source, null);
13695
+ return void 0;
13696
+ }
13697
+ }
13698
+ paragraphPretextUniformFontBySource.set(source, uniformFont ?? null);
13699
+ return uniformFont;
13230
13700
  }
13231
13701
  function buildMeasureSegmentsPretextLayoutItems(segments, paragraphBaseFontPx, text) {
13232
13702
  const wordBreak = pretextWordBreakModeForText(text);
@@ -14013,6 +14483,31 @@ function paragraphStartsWithLastRenderedPageBreak(paragraph) {
14013
14483
  ).replace(/<\/?w:(?:ins|smartTag)\b[^>]*>/gi, "").replace(/\s+/g, "");
14014
14484
  return leadingXml.length === 0;
14015
14485
  }
14486
+ function shouldHonorParagraphStartLastRenderedPageBreak(params) {
14487
+ const pageConsumedHeightPx = Math.max(
14488
+ 0,
14489
+ Math.round(params.pageConsumedHeightPx)
14490
+ );
14491
+ const pageContentHeightPx = Math.max(
14492
+ 0,
14493
+ Math.round(params.pageContentHeightPx)
14494
+ );
14495
+ if (pageConsumedHeightPx <= 0 || pageContentHeightPx <= 0) {
14496
+ return false;
14497
+ }
14498
+ const remainingHeightPx = Math.max(
14499
+ 0,
14500
+ pageContentHeightPx - pageConsumedHeightPx
14501
+ );
14502
+ const maxAllowedRemainingHeightPx = clampNumber(
14503
+ Math.round(
14504
+ pageContentHeightPx * LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_RATIO
14505
+ ),
14506
+ LAST_RENDERED_PAGE_BREAK_HINT_MIN_REMAINING_SPACE_PX,
14507
+ LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_PX
14508
+ );
14509
+ return remainingHeightPx <= maxAllowedRemainingHeightPx;
14510
+ }
14016
14511
  function isOnOffTagEnabled2(tagXml) {
14017
14512
  if (!tagXml) {
14018
14513
  return false;
@@ -14156,7 +14651,8 @@ function sectionBreakAfterParagraphStartsNewPage(paragraph) {
14156
14651
  if (cached) {
14157
14652
  return cached.sectionBreakStartsNewPage;
14158
14653
  }
14159
- return paragraphHasExplicitPageBreak2(paragraph) ? paragraphBreakFlagsBySourceXml.get(xml)?.sectionBreakStartsNewPage ?? false : false;
14654
+ paragraphHasExplicitPageBreak2(paragraph);
14655
+ return paragraphBreakFlagsBySourceXml.get(xml)?.sectionBreakStartsNewPage ?? false;
14160
14656
  }
14161
14657
  function nodeAlreadyEndsAtExplicitPageBoundary(node) {
14162
14658
  if (!node || node.type !== "paragraph") {
@@ -14396,6 +14892,10 @@ function singleLineAutoScaleForFontFamily(fontFamily) {
14396
14892
  }
14397
14893
  return WORD_SINGLE_LINE_AUTO_SCALE;
14398
14894
  }
14895
+ function resolveParagraphSingleLineAutoScale(paragraph, fontFamily) {
14896
+ const baseScale = singleLineAutoScaleForFontFamily(fontFamily);
14897
+ return paragraphHasCheckboxFormField(paragraph) ? Math.max(1.08, baseScale) : baseScale;
14898
+ }
14399
14899
  function paragraphContainsExplicitLineBreakText(paragraph) {
14400
14900
  return paragraph.children.some(
14401
14901
  (child) => child.type === "text" && /[\r\n]/.test(child.text)
@@ -14484,6 +14984,23 @@ function resolveParagraphTabStopsPx(paragraph) {
14484
14984
  ).map((value) => Math.round(value)).sort((left, right) => left - right);
14485
14985
  return stopsPx;
14486
14986
  }
14987
+ function resolveParagraphFirstLineOriginPx(paragraph) {
14988
+ const leftIndentPx = twipsToSignedPixels(paragraph.style?.indent?.leftTwips);
14989
+ const firstLineIndentPx = twipsToSignedPixels(
14990
+ paragraph.style?.indent?.firstLineTwips
14991
+ );
14992
+ const hangingIndentPx = twipsToSignedPixels(
14993
+ paragraph.style?.indent?.hangingTwips
14994
+ );
14995
+ const textIndentPx = firstLineIndentPx ?? (Number.isFinite(hangingIndentPx) ? -hangingIndentPx : 0);
14996
+ return (Number.isFinite(leftIndentPx) ? leftIndentPx : 0) + (Number.isFinite(textIndentPx) ? textIndentPx : 0);
14997
+ }
14998
+ function resolveParagraphFirstLineLeftTabStopsPx(paragraph) {
14999
+ const firstLineOriginPx = resolveParagraphFirstLineOriginPx(paragraph);
15000
+ return (paragraph.style?.tabStops ?? []).filter((tabStop) => tabStop.alignment !== "right").map((tabStop) => twipsToPixels(tabStop.positionTwips)).filter(
15001
+ (value) => Number.isFinite(value) && value > firstLineOriginPx + 0.5
15002
+ ).map((value) => Math.round(value - firstLineOriginPx)).sort((left, right) => left - right);
15003
+ }
14487
15004
  function resolveNextTabStopPx(currentLineWidthPx, tabStopsPx) {
14488
15005
  const nextExplicit = tabStopsPx.find(
14489
15006
  (stopPx) => stopPx > currentLineWidthPx + 0.5
@@ -14697,12 +15214,37 @@ function estimateTabLeaderWrappedLineCountForParagraph(paragraph, maxLineWidthPx
14697
15214
  paragraphBaseFontPx
14698
15215
  );
14699
15216
  }
15217
+ var wrappedLineCountByParagraph = /* @__PURE__ */ new WeakMap();
15218
+ function cachedWrappedLineCountForParagraph(paragraph, widthPx) {
15219
+ return wrappedLineCountByParagraph.get(paragraph)?.get(widthPx);
15220
+ }
15221
+ function rememberWrappedLineCountForParagraph(paragraph, widthPx, lineCount) {
15222
+ let countsByWidth = wrappedLineCountByParagraph.get(paragraph);
15223
+ if (!countsByWidth) {
15224
+ countsByWidth = /* @__PURE__ */ new Map();
15225
+ wrappedLineCountByParagraph.set(paragraph, countsByWidth);
15226
+ }
15227
+ countsByWidth.set(widthPx, lineCount);
15228
+ return lineCount;
15229
+ }
14700
15230
  function estimateWrappedLineCountForParagraph(paragraph, availableWidthPx) {
14701
15231
  const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
14702
15232
  const maxLineWidthPx = Math.max(
14703
15233
  paragraphBaseFontPx * 2,
14704
15234
  Math.round(availableWidthPx)
14705
15235
  );
15236
+ const cachedLineCount = cachedWrappedLineCountForParagraph(
15237
+ paragraph,
15238
+ maxLineWidthPx
15239
+ );
15240
+ if (cachedLineCount !== void 0) {
15241
+ return cachedLineCount;
15242
+ }
15243
+ const rememberLineCount = (lineCount2) => rememberWrappedLineCountForParagraph(
15244
+ paragraph,
15245
+ maxLineWidthPx,
15246
+ Math.max(1, Math.round(lineCount2))
15247
+ );
14706
15248
  const tabStopsPx = resolveParagraphTabStopsPx(paragraph);
14707
15249
  const useTabLeaderLayout = paragraphUsesTabLeaders(paragraph);
14708
15250
  const anchoredTabLayout = paragraphAnchoredTabLayout(paragraph);
@@ -14717,6 +15259,21 @@ function estimateWrappedLineCountForParagraph(paragraph, availableWidthPx) {
14717
15259
  if (!pretextSource) {
14718
15260
  return void 0;
14719
15261
  }
15262
+ const uniformFont = resolveUniformPretextSourceFont(
15263
+ paragraph,
15264
+ pretextSource
15265
+ );
15266
+ if (uniformFont !== void 0) {
15267
+ const fastLineCount = measurePretextPlainTextLineCount(
15268
+ pretextSource.text,
15269
+ uniformFont,
15270
+ maxLineWidthPx,
15271
+ { wordBreak: pretextWordBreakModeForText(pretextSource.text) }
15272
+ );
15273
+ if (fastLineCount !== void 0) {
15274
+ return fastLineCount;
15275
+ }
15276
+ }
14720
15277
  const lineHeightPx = estimateParagraphLineHeightPx(paragraph);
14721
15278
  const layout = layoutParagraphPretextSource(
14722
15279
  paragraph,
@@ -14728,7 +15285,7 @@ function estimateWrappedLineCountForParagraph(paragraph, availableWidthPx) {
14728
15285
  return layout?.lineCount;
14729
15286
  })();
14730
15287
  if (pretextPlainLineCount) {
14731
- return Math.max(1, pretextPlainLineCount);
15288
+ return rememberLineCount(pretextPlainLineCount);
14732
15289
  }
14733
15290
  }
14734
15291
  if (useTabLeaderLayout) {
@@ -14738,7 +15295,7 @@ function estimateWrappedLineCountForParagraph(paragraph, availableWidthPx) {
14738
15295
  paragraphBaseFontPx
14739
15296
  );
14740
15297
  if (tabLeaderLineCount !== void 0) {
14741
- return tabLeaderLineCount;
15298
+ return rememberLineCount(tabLeaderLineCount);
14742
15299
  }
14743
15300
  }
14744
15301
  let lineCount = 1;
@@ -14856,7 +15413,7 @@ function estimateWrappedLineCountForParagraph(paragraph, availableWidthPx) {
14856
15413
  commitToken(token, child.style);
14857
15414
  }
14858
15415
  }
14859
- return hasVisibleContent ? Math.max(1, lineCount) : 1;
15416
+ return rememberLineCount(hasVisibleContent ? lineCount : 1);
14860
15417
  }
14861
15418
  function paragraphAvailableTextWidthPx(paragraph, availableWidthPx, numberingDefinitions) {
14862
15419
  const safeAvailableWidthPx = Math.max(24, Math.round(availableWidthPx));
@@ -14971,6 +15528,58 @@ function wrappedPretextParagraphBlockHeightPx(layout) {
14971
15528
  }
14972
15529
  return Math.max(1, Math.round(layout.height));
14973
15530
  }
15531
+ function resolvePretextLineRangeContentHeightPx(layout, startLineIndex, endLineIndex) {
15532
+ if (layout.lines.length === 0) {
15533
+ return 0;
15534
+ }
15535
+ const lineHeightPx = Math.max(1, Math.round(layout.lineHeightPx ?? 1));
15536
+ const safeStart = Math.max(
15537
+ 0,
15538
+ Math.min(Math.round(startLineIndex), layout.lines.length)
15539
+ );
15540
+ const safeEnd = Math.max(
15541
+ safeStart,
15542
+ Math.min(Math.round(endLineIndex), layout.lines.length)
15543
+ );
15544
+ if (safeEnd <= safeStart) {
15545
+ return 0;
15546
+ }
15547
+ const firstLineTopPx = layout.lines[safeStart]?.y ?? safeStart * lineHeightPx;
15548
+ const lastLineTopPx = layout.lines[safeEnd - 1]?.y ?? (safeEnd - 1) * lineHeightPx;
15549
+ return Math.max(1, Math.round(lastLineTopPx - firstLineTopPx + lineHeightPx));
15550
+ }
15551
+ function resolveMaxPretextLineRangeEndIndexThatFits(layout, startLineIndex, maxEndLineIndex, availableHeightPx) {
15552
+ const safeStart = Math.max(
15553
+ 0,
15554
+ Math.min(Math.round(startLineIndex), layout.lines.length)
15555
+ );
15556
+ const safeMaxEnd = Math.max(
15557
+ safeStart,
15558
+ Math.min(Math.round(maxEndLineIndex), layout.lines.length)
15559
+ );
15560
+ const safeAvailableHeightPx = Math.max(0, Math.round(availableHeightPx));
15561
+ if (safeAvailableHeightPx <= 0 || safeMaxEnd <= safeStart) {
15562
+ return safeStart;
15563
+ }
15564
+ let low = safeStart;
15565
+ let high = safeMaxEnd;
15566
+ let bestEnd = safeStart;
15567
+ while (low <= high) {
15568
+ const mid = Math.floor((low + high) / 2);
15569
+ const candidateHeightPx = resolvePretextLineRangeContentHeightPx(
15570
+ layout,
15571
+ safeStart,
15572
+ mid
15573
+ );
15574
+ if (candidateHeightPx <= safeAvailableHeightPx) {
15575
+ bestEnd = mid;
15576
+ low = mid + 1;
15577
+ continue;
15578
+ }
15579
+ high = mid - 1;
15580
+ }
15581
+ return bestEnd;
15582
+ }
14974
15583
  function estimateAbsoluteFloatingImageFootprintPx(paragraph, image) {
14975
15584
  if (!shouldRenderAbsoluteFloatingImage(image)) {
14976
15585
  return 0;
@@ -15010,10 +15619,7 @@ function resolveAutoLineSpacingMultiple(lineTwips, fallbackMultiple) {
15010
15619
  function autoLineHeightScaleForMultiple(multiple, singleLineScale) {
15011
15620
  const safeSingleLineScale = Math.max(
15012
15621
  MIN_AUTO_LINE_MULTIPLE,
15013
- Math.min(
15014
- 1,
15015
- Number.isFinite(singleLineScale) ? singleLineScale : WORD_SINGLE_LINE_AUTO_SCALE
15016
- )
15622
+ Number.isFinite(singleLineScale) ? singleLineScale : WORD_SINGLE_LINE_AUTO_SCALE
15017
15623
  );
15018
15624
  if (!Number.isFinite(multiple)) {
15019
15625
  return safeSingleLineScale;
@@ -15029,9 +15635,9 @@ function autoLineHeightScaleForMultiple(multiple, singleLineScale) {
15029
15635
  (safeSingleLineScale + (1 - safeSingleLineScale) * blendProgress).toFixed(4)
15030
15636
  );
15031
15637
  }
15032
- function calibrateAutoLineSpacingMultiple(multiple, fontFamily) {
15638
+ function calibrateAutoLineSpacingMultiple(multiple, fontFamily, singleLineScaleOverride) {
15033
15639
  const normalizedMultiple = Math.max(MIN_AUTO_LINE_MULTIPLE, multiple);
15034
- const singleLineScale = singleLineAutoScaleForFontFamily(fontFamily);
15640
+ const singleLineScale = singleLineScaleOverride ?? singleLineAutoScaleForFontFamily(fontFamily);
15035
15641
  return Math.max(
15036
15642
  MIN_AUTO_LINE_MULTIPLE,
15037
15643
  Number(
@@ -15075,13 +15681,18 @@ function estimateParagraphLineHeightPx(paragraph, docGridLinePitchPx, disableDoc
15075
15681
  );
15076
15682
  const baseFontPx = paragraphBaseFontSizePx(paragraph);
15077
15683
  const baseFontFamily = paragraphDominantFontFamily(paragraph);
15684
+ const singleLineScale = resolveParagraphSingleLineAutoScale(
15685
+ paragraph,
15686
+ baseFontFamily
15687
+ );
15078
15688
  const defaultLineMultiple = isTableOfContentsParagraph(paragraph) ? 1.05 : DEFAULT_PARAGRAPH_LINE_MULTIPLE;
15079
15689
  const normalLineHeightPx = Math.max(
15080
15690
  1,
15081
15691
  Math.round(
15082
15692
  baseFontPx * calibrateAutoLineSpacingMultiple(
15083
15693
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
15084
- baseFontFamily
15694
+ baseFontFamily,
15695
+ singleLineScale
15085
15696
  )
15086
15697
  )
15087
15698
  );
@@ -15098,7 +15709,8 @@ function estimateParagraphLineHeightPx(paragraph, docGridLinePitchPx, disableDoc
15098
15709
  }
15099
15710
  const multiple = calibrateAutoLineSpacingMultiple(
15100
15711
  resolveAutoLineSpacingMultiple(lineTwips, defaultLineMultiple),
15101
- baseFontFamily
15712
+ baseFontFamily,
15713
+ singleLineScale
15102
15714
  );
15103
15715
  const autoLineHeightPx = Math.max(1, Math.round(baseFontPx * multiple));
15104
15716
  const minimumReadableAutoLineHeightPx = paragraph.style?.numbering ? Math.ceil(baseFontPx) : 0;
@@ -15264,14 +15876,17 @@ function suppressFirstTableCellParagraphTopSpacing(paragraph) {
15264
15876
  }
15265
15877
  function estimateTableCellContentHeightPx(nodeContent, availableWidthPx, numberingDefinitions, applyWordTableDefaults = false, docGridLinePitchPx) {
15266
15878
  let paragraphIndex = 0;
15267
- return nodeContent.reduce((sum, contentNode) => {
15879
+ let expandedWithPretextLayout = false;
15880
+ let totalHeightPx = 0;
15881
+ for (const contentNode of nodeContent) {
15268
15882
  if (!isParagraphCellContentNode(contentNode)) {
15269
- return sum + estimateTableHeightPx(
15883
+ totalHeightPx += estimateTableHeightPx(
15270
15884
  contentNode,
15271
15885
  availableWidthPx,
15272
15886
  numberingDefinitions,
15273
15887
  docGridLinePitchPx
15274
15888
  );
15889
+ continue;
15275
15890
  }
15276
15891
  const disableDocGridSnap = paragraphDocGridSnapState(contentNode) === "disable";
15277
15892
  const paragraphForLayout = wordLikeTableCellParagraph(
@@ -15285,14 +15900,55 @@ function estimateTableCellContentHeightPx(nodeContent, availableWidthPx, numberi
15285
15900
  docGridLinePitchPx,
15286
15901
  disableDocGridSnap
15287
15902
  );
15903
+ const lineHeightPx = Math.max(
15904
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
15905
+ estimateParagraphLineHeightPx(
15906
+ paragraphForLayout,
15907
+ docGridLinePitchPx,
15908
+ disableDocGridSnap
15909
+ )
15910
+ );
15911
+ const pretextSource = buildParagraphPretextLayoutSource(
15912
+ paragraphForLayout,
15913
+ {
15914
+ allowExplicitLineBreakText: true,
15915
+ expandTabsForLayout: true
15916
+ }
15917
+ );
15918
+ const paragraphTextWidthPx = typeof availableWidthPx === "number" && availableWidthPx > 0 ? paragraphAvailableTextWidthPx(
15919
+ paragraphForLayout,
15920
+ availableWidthPx,
15921
+ numberingDefinitions
15922
+ ) : void 0;
15923
+ const pretextLayout = pretextSource && typeof paragraphTextWidthPx === "number" && paragraphTextWidthPx > 0 ? layoutParagraphPretextSource(
15924
+ paragraphForLayout,
15925
+ pretextSource,
15926
+ paragraphTextWidthPx,
15927
+ lineHeightPx,
15928
+ []
15929
+ ) : void 0;
15288
15930
  const suppressTopSpacing = paragraphIndex === 0 && suppressFirstTableCellParagraphTopSpacing(contentNode);
15289
15931
  paragraphIndex += 1;
15932
+ const beforeSpacing = suppressTopSpacing ? 0 : twipsToPixels(paragraphForLayout.style?.spacing?.beforeTwips) ?? 0;
15933
+ const afterSpacing = twipsToPixels(paragraphForLayout.style?.spacing?.afterTwips) ?? 0;
15934
+ const topBorderInsetPx = paragraphBorderInsetPx(
15935
+ paragraphForLayout.style?.borders?.top
15936
+ );
15937
+ const bottomBorderInsetPx = paragraphBorderInsetPx(
15938
+ paragraphForLayout.style?.borders?.bottom
15939
+ );
15940
+ const pretextHeightPx = pretextLayout ? beforeSpacing + afterSpacing + topBorderInsetPx + bottomBorderInsetPx + wrappedPretextParagraphBlockHeightPx(pretextLayout) : 0;
15941
+ const resolvedBaseHeight = pretextHeightPx > 0 ? Math.max(baseHeight, pretextHeightPx) : baseHeight;
15942
+ if (pretextHeightPx > baseHeight) {
15943
+ expandedWithPretextLayout = true;
15944
+ }
15290
15945
  if (!suppressTopSpacing) {
15291
- return sum + baseHeight;
15946
+ totalHeightPx += resolvedBaseHeight;
15947
+ continue;
15292
15948
  }
15293
- const beforeSpacing = twipsToPixels(paragraphForLayout.style?.spacing?.beforeTwips) ?? 0;
15294
- return sum + Math.max(1, baseHeight - beforeSpacing);
15295
- }, 0);
15949
+ totalHeightPx += Math.max(1, resolvedBaseHeight - beforeSpacing);
15950
+ }
15951
+ return totalHeightPx + (expandedWithPretextLayout ? Math.max(1, MIN_PARAGRAPH_LINE_HEIGHT_PX) : 0);
15296
15952
  }
15297
15953
  function rowAllowsPageSplit(row) {
15298
15954
  return row.style?.cantSplit !== true && row.style?.heightRule !== "exact";
@@ -15310,7 +15966,7 @@ function rowHasDeepFlowContent(row) {
15310
15966
  }
15311
15967
  return nestedTableCount > 0 || blockNodeCount >= SPLITTABLE_TABLE_ROW_DEEP_CONTENT_NODE_THRESHOLD;
15312
15968
  }
15313
- function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitHeightPx) {
15969
+ function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitHeightPx, pageContentHeightPx) {
15314
15970
  if (!rowAllowsPageSplit(row)) {
15315
15971
  return estimatedRowHeightPx;
15316
15972
  }
@@ -15324,6 +15980,13 @@ function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitH
15324
15980
  MIN_PARAGRAPH_LINE_HEIGHT_PX * 2,
15325
15981
  Math.round(explicitHeightPx)
15326
15982
  );
15983
+ const safePageContentHeightPx = Number.isFinite(pageContentHeightPx) && pageContentHeightPx > 0 ? Math.max(
15984
+ MIN_PARAGRAPH_LINE_HEIGHT_PX * 4,
15985
+ Math.round(pageContentHeightPx)
15986
+ ) : void 0;
15987
+ if (safePageContentHeightPx !== void 0 && estimatedRowHeightPx > safePageContentHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
15988
+ return estimatedRowHeightPx;
15989
+ }
15327
15990
  const cappedHeightPx = safeExplicitHeightPx + MIN_PARAGRAPH_LINE_HEIGHT_PX * SPLITTABLE_TABLE_ROW_ESTIMATE_EXTRA_LINE_COUNT;
15328
15991
  return Math.min(estimatedRowHeightPx, cappedHeightPx);
15329
15992
  }
@@ -15361,7 +16024,7 @@ function tableUsesWordLikeParagraphDefaults(table) {
15361
16024
  }
15362
16025
  return table.style?.layout === "fixed" && tableHasVisibleBorders(table) && tableContainsParagraphsWithoutExplicitSpacing(table);
15363
16026
  }
15364
- function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx) {
16027
+ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx, pageContentHeightPx) {
15365
16028
  const defaultCellMargin = table.style?.cellMarginTwips;
15366
16029
  const columnCount = tableColumnCount(table);
15367
16030
  const tableWidthPx = twipsToPixels(table.style?.widthTwips);
@@ -15379,7 +16042,11 @@ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefiniti
15379
16042
  return normalizeColumnWidthsPx(widthsPx, columnCount, tableWidthPx, 1);
15380
16043
  })();
15381
16044
  const rawResolvedTableWidthPx = tableWidthPx ?? rawTableColumnWidthsPx.reduce((sum, widthPx) => sum + widthPx, 0);
15382
- const maxTableWidthPx = Number.isFinite(maxAvailableWidthPx) && maxAvailableWidthPx > 0 ? Math.max(120, maxAvailableWidthPx) : void 0;
16045
+ const collapsedHorizontalBorderBleedPx = resolveCollapsedTableHorizontalOuterBleedPx(table, columnCount);
16046
+ const maxTableWidthPx = Number.isFinite(maxAvailableWidthPx) && maxAvailableWidthPx > 0 ? Math.max(
16047
+ 120,
16048
+ maxAvailableWidthPx - collapsedHorizontalBorderBleedPx
16049
+ ) : void 0;
15383
16050
  const resolvedTableWidthPx = clampTableWidthPx(
15384
16051
  rawResolvedTableWidthPx,
15385
16052
  maxTableWidthPx
@@ -15426,7 +16093,8 @@ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefiniti
15426
16093
  rowHeightPx = capSplitFriendlyTableRowEstimatePx(
15427
16094
  row,
15428
16095
  rowHeightPx,
15429
- explicitHeightPx
16096
+ explicitHeightPx,
16097
+ pageContentHeightPx
15430
16098
  );
15431
16099
  return Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, rowHeightPx);
15432
16100
  });
@@ -15527,6 +16195,45 @@ function paragraphSegmentHasPartialLineRange(paragraphLineRange) {
15527
16195
  }
15528
16196
  return paragraphLineRange.startLineIndex > 0 || paragraphLineRange.endLineIndex < paragraphLineRange.totalLineCount;
15529
16197
  }
16198
+ function resolveLineRangeWithinVerticalSlice(lineTopOffsetsPx, lineHeightPx, sliceTopPx, sliceBottomPx) {
16199
+ if (lineTopOffsetsPx.length === 0 || !Number.isFinite(lineHeightPx) || lineHeightPx <= 0) {
16200
+ return void 0;
16201
+ }
16202
+ const safeSliceTopPx = Math.max(0, sliceTopPx);
16203
+ const safeSliceBottomPx = Math.max(safeSliceTopPx, sliceBottomPx);
16204
+ const sliceHasHeight = safeSliceBottomPx > safeSliceTopPx;
16205
+ let startLineIndex;
16206
+ let endLineIndex;
16207
+ for (let lineIndex = 0; lineIndex < lineTopOffsetsPx.length; lineIndex += 1) {
16208
+ const lineTopPx = lineTopOffsetsPx[lineIndex] ?? lineIndex * lineHeightPx;
16209
+ const lineBottomPx = lineTopPx + lineHeightPx;
16210
+ const lineBelongsToSlice = sliceHasHeight && lineBottomPx > safeSliceTopPx + PAGE_OVERFLOW_TOLERANCE_PX && lineBottomPx <= safeSliceBottomPx + PAGE_OVERFLOW_TOLERANCE_PX;
16211
+ if (lineBelongsToSlice) {
16212
+ if (startLineIndex === void 0) {
16213
+ startLineIndex = lineIndex;
16214
+ }
16215
+ endLineIndex = lineIndex + 1;
16216
+ }
16217
+ }
16218
+ if (startLineIndex === void 0 || endLineIndex === void 0 || endLineIndex <= startLineIndex) {
16219
+ return void 0;
16220
+ }
16221
+ return {
16222
+ startLineIndex,
16223
+ endLineIndex,
16224
+ totalLineCount: lineTopOffsetsPx.length,
16225
+ lineHeightPx
16226
+ };
16227
+ }
16228
+ function resolveTableCellParagraphVisualBottomPx(params) {
16229
+ return Math.max(
16230
+ Math.round(params.paragraphTopPx + params.paragraphHeightPx),
16231
+ Math.round(params.textBottomPx)
16232
+ );
16233
+ }
16234
+ function tableCellParagraphFitsFullyWithinSlice(params) {
16235
+ 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;
16236
+ }
15530
16237
  function resolveParagraphSegmentClipBleedPx(paragraphLineRange) {
15531
16238
  if (!paragraphSegmentHasPartialLineRange(paragraphLineRange)) {
15532
16239
  return {
@@ -15536,7 +16243,7 @@ function resolveParagraphSegmentClipBleedPx(paragraphLineRange) {
15536
16243
  }
15537
16244
  return {
15538
16245
  topPx: paragraphLineRange && paragraphLineRange.startLineIndex > 0 ? Math.max(0, PARAGRAPH_SEGMENT_TOP_BLEED_PX) : 0,
15539
- bottomPx: Math.max(0, PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX)
16246
+ bottomPx: paragraphLineRange && paragraphLineRange.endLineIndex < paragraphLineRange.totalLineCount ? Math.max(0, PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX) : 0
15540
16247
  };
15541
16248
  }
15542
16249
  function resolveFallbackParagraphSegmentClipBleedPx(paragraph, paragraphLineRange) {
@@ -15610,12 +16317,32 @@ function estimateRenderedPageSegmentHeightPx(node, segment, model, availableWidt
15610
16317
  false
15611
16318
  ) : 0;
15612
16319
  const afterSpacingPx = paragraphLineRange.endLineIndex >= paragraphLineRange.totalLineCount ? effectiveParagraphAfterSpacingPx(model, segment.nodeIndex, node) : 0;
16320
+ const paragraphPretextSource = buildParagraphPretextLayoutSource(node, {
16321
+ allowExplicitLineBreakText: true,
16322
+ expandTabsForLayout: true
16323
+ });
16324
+ const paragraphPretextLayout = paragraphPretextSource ? layoutParagraphPretextSource(
16325
+ node,
16326
+ paragraphPretextSource,
16327
+ paragraphAvailableTextWidthPx(
16328
+ node,
16329
+ availableWidthPx,
16330
+ numberingDefinitions
16331
+ ),
16332
+ Math.max(1, paragraphLineRange.lineHeightPx),
16333
+ []
16334
+ ) : void 0;
16335
+ const segmentContentHeightPx = paragraphPretextLayout && paragraphPretextLayout.lineCount > 0 ? resolvePretextLineRangeContentHeightPx(
16336
+ paragraphPretextLayout,
16337
+ paragraphLineRange.startLineIndex,
16338
+ paragraphLineRange.endLineIndex
16339
+ ) : Math.max(
16340
+ 1,
16341
+ paragraphLineRange.endLineIndex - paragraphLineRange.startLineIndex
16342
+ ) * Math.max(1, paragraphLineRange.lineHeightPx);
15613
16343
  return Math.max(
15614
16344
  1,
15615
- beforeSpacingPx + Math.max(
15616
- 1,
15617
- paragraphLineRange.endLineIndex - paragraphLineRange.startLineIndex
15618
- ) * Math.max(1, paragraphLineRange.lineHeightPx) + afterSpacingPx
16345
+ beforeSpacingPx + segmentContentHeightPx + afterSpacingPx
15619
16346
  );
15620
16347
  }
15621
16348
  return Math.max(
@@ -15756,6 +16483,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15756
16483
  let pageConsumedHeightPx = 0;
15757
16484
  let previousParagraphAfterPx = 0;
15758
16485
  let currentMetricsIndex = 0;
16486
+ let currentSectionPageFlowOriginPx = 0;
15759
16487
  let currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15760
16488
  0,
15761
16489
  metricsBySection[0]
@@ -15797,11 +16525,13 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15797
16525
  currentPageIndex,
15798
16526
  nodeMetrics
15799
16527
  );
16528
+ currentSectionPageFlowOriginPx = pageConsumedHeightPx;
15800
16529
  }
15801
16530
  if (hardBreakStartNodeIndexes.has(nodeIndex) && currentPageSegments.length > 0) {
15802
16531
  startNextPage();
15803
16532
  pageConsumedHeightPx = 0;
15804
16533
  previousParagraphAfterPx = 0;
16534
+ currentSectionPageFlowOriginPx = 0;
15805
16535
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15806
16536
  currentPageIndex,
15807
16537
  nodeMetrics
@@ -15856,6 +16586,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15856
16586
  startNextPage();
15857
16587
  pageConsumedHeightPx = 0;
15858
16588
  previousParagraphAfterPx = 0;
16589
+ currentSectionPageFlowOriginPx = 0;
15859
16590
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15860
16591
  currentPageIndex,
15861
16592
  nodeMetrics
@@ -15865,15 +16596,20 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15865
16596
  startNextPage();
15866
16597
  pageConsumedHeightPx = 0;
15867
16598
  previousParagraphAfterPx = 0;
16599
+ currentSectionPageFlowOriginPx = 0;
15868
16600
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15869
16601
  currentPageIndex,
15870
16602
  nodeMetrics
15871
16603
  );
15872
16604
  }
15873
- if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak(node) && !nodeAlreadyEndsAtExplicitPageBoundary(model.nodes[nodeIndex - 1]) && currentPageSegments.length > 0) {
16605
+ if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak(node) && shouldHonorParagraphStartLastRenderedPageBreak({
16606
+ pageConsumedHeightPx,
16607
+ pageContentHeightPx: currentPageContentHeightPx
16608
+ }) && !nodeAlreadyEndsAtExplicitPageBoundary(model.nodes[nodeIndex - 1]) && currentPageSegments.length > 0) {
15874
16609
  startNextPage();
15875
16610
  pageConsumedHeightPx = 0;
15876
16611
  previousParagraphAfterPx = 0;
16612
+ currentSectionPageFlowOriginPx = 0;
15877
16613
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15878
16614
  currentPageIndex,
15879
16615
  nodeMetrics
@@ -15893,7 +16629,36 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15893
16629
  nodeIndex,
15894
16630
  node
15895
16631
  );
15896
- const rawNodeHeightPx = Math.max(
16632
+ const paragraphLineHeightPx = estimateParagraphLineHeightPx(
16633
+ node,
16634
+ nodeMetrics.docGridLinePitchPx
16635
+ );
16636
+ const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
16637
+ node,
16638
+ nodeMetrics.pageContentWidthPx,
16639
+ numberingDefinitions
16640
+ );
16641
+ const paragraphPretextSourceForSegmentRendering = buildParagraphPretextLayoutSource(node, {
16642
+ allowExplicitLineBreakText: true,
16643
+ expandTabsForLayout: true
16644
+ });
16645
+ let paragraphPretextLayoutForSegmentRendering;
16646
+ let paragraphPretextLayoutForSegmentRenderingResolved = false;
16647
+ const resolveParagraphPretextLayoutForSegmentRendering = () => {
16648
+ if (paragraphPretextLayoutForSegmentRenderingResolved) {
16649
+ return paragraphPretextLayoutForSegmentRendering;
16650
+ }
16651
+ paragraphPretextLayoutForSegmentRenderingResolved = true;
16652
+ paragraphPretextLayoutForSegmentRendering = paragraphPretextSourceForSegmentRendering ? layoutParagraphPretextSource(
16653
+ node,
16654
+ paragraphPretextSourceForSegmentRendering,
16655
+ paragraphTextWidthPx,
16656
+ paragraphLineHeightPx,
16657
+ []
16658
+ ) : void 0;
16659
+ return paragraphPretextLayoutForSegmentRendering;
16660
+ };
16661
+ let rawNodeHeightPx = Math.max(
15897
16662
  1,
15898
16663
  estimateParagraphHeightPx(
15899
16664
  node,
@@ -15917,6 +16682,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15917
16682
  startNextPage();
15918
16683
  pageConsumedHeightPx = 0;
15919
16684
  previousParagraphAfterPx = 0;
16685
+ currentSectionPageFlowOriginPx = 0;
15920
16686
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15921
16687
  currentPageIndex,
15922
16688
  nodeMetrics
@@ -15927,38 +16693,33 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15927
16693
  1,
15928
16694
  Math.max(rawNodeHeightPx, coverFootprintPx) - collapsedMarginPx
15929
16695
  );
15930
- const paragraphLineHeightPx = estimateParagraphLineHeightPx(
15931
- node,
15932
- nodeMetrics.docGridLinePitchPx
15933
- );
15934
- const paragraphPretextSourceForSegmentRendering = buildParagraphPretextLayoutSource(node, {
15935
- allowExplicitLineBreakText: true
15936
- });
15937
16696
  const paragraphSupportsPretextSegmentRendering = Boolean(
15938
16697
  paragraphPretextSourceForSegmentRendering
15939
16698
  );
15940
- const paragraphPretextLineCount = (() => {
15941
- if (!paragraphContainsExplicitLineBreakText(node)) {
15942
- return void 0;
15943
- }
15944
- const pretextSource = paragraphPretextSourceForSegmentRendering;
15945
- if (!pretextSource) {
15946
- return void 0;
16699
+ const remainingHeightBeforeParagraphPx = Math.max(
16700
+ 0,
16701
+ currentPageContentHeightPx - pageConsumedHeightPx
16702
+ );
16703
+ if (paragraphSupportsPretextSegmentRendering && remainingHeightBeforeParagraphPx <= collapsedNodeHeightPx + paragraphLineHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
16704
+ const pretextLayout = resolveParagraphPretextLayoutForSegmentRendering();
16705
+ const pretextContentHeightPx = pretextLayout ? wrappedPretextParagraphBlockHeightPx(pretextLayout) : void 0;
16706
+ if (Number.isFinite(pretextContentHeightPx)) {
16707
+ rawNodeHeightPx = Math.max(
16708
+ rawNodeHeightPx,
16709
+ Math.max(
16710
+ 1,
16711
+ Math.round(
16712
+ beforeSpacingPx + pretextContentHeightPx + afterSpacingPx
16713
+ )
16714
+ )
16715
+ );
15947
16716
  }
15948
- const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
15949
- node,
15950
- nodeMetrics.pageContentWidthPx,
15951
- numberingDefinitions
15952
- );
15953
- const pretextLayout = layoutParagraphPretextSource(
15954
- node,
15955
- pretextSource,
15956
- paragraphTextWidthPx,
15957
- paragraphLineHeightPx,
15958
- []
15959
- );
15960
- return pretextLayout?.lineCount;
15961
- })();
16717
+ }
16718
+ const collapsedNodeHeightPxAdjusted = Math.max(
16719
+ 1,
16720
+ Math.max(rawNodeHeightPx, coverFootprintPx) - collapsedMarginPx
16721
+ );
16722
+ const paragraphPretextLineCount = paragraphContainsExplicitLineBreakText(node) || paragraphContainsTabCharacter(node) ? resolveParagraphPretextLayoutForSegmentRendering()?.lineCount : void 0;
15962
16723
  const supportsImageParagraphLineSplit = paragraphHasImage2(node) && paragraphSupportsPretextSegmentRendering;
15963
16724
  const paragraphLineCount = paragraphLineCountWithinWidth(
15964
16725
  node,
@@ -15966,6 +16727,54 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15966
16727
  numberingDefinitions
15967
16728
  );
15968
16729
  const resolvedParagraphLineCount = Number.isFinite(paragraphPretextLineCount) && paragraphPretextLineCount > 0 ? Math.max(1, Math.round(paragraphPretextLineCount)) : paragraphLineCount;
16730
+ const explicitColumnBreakParagraphSegments = (nodeMetrics.pageContentHeightMultiplier ?? 1) > 1 ? splitParagraphAtExplicitColumnBreaks(node) : void 0;
16731
+ const tryConsumeExplicitColumnBreakParagraph = () => {
16732
+ if (!explicitColumnBreakParagraphSegments || explicitColumnBreakParagraphSegments.length <= 1) {
16733
+ return false;
16734
+ }
16735
+ const projectedConsumedHeightPx = projectParagraphConsumedHeightWithExplicitColumnBreaks(
16736
+ explicitColumnBreakParagraphSegments,
16737
+ pageConsumedHeightPx,
16738
+ currentPageContentHeightPx,
16739
+ currentSectionPageFlowOriginPx,
16740
+ Math.max(
16741
+ 1,
16742
+ Math.round(nodeMetrics.pageContentHeightMultiplier ?? 1)
16743
+ ),
16744
+ nodeMetrics.pageContentWidthPx,
16745
+ beforeSpacingPx,
16746
+ afterSpacingPx,
16747
+ collapsedMarginPx,
16748
+ numberingDefinitions,
16749
+ nodeMetrics.docGridLinePitchPx
16750
+ );
16751
+ if (!Number.isFinite(projectedConsumedHeightPx)) {
16752
+ return false;
16753
+ }
16754
+ currentPageSegments.push({ nodeIndex });
16755
+ pageConsumedHeightPx = Math.max(
16756
+ pageConsumedHeightPx,
16757
+ Math.round(projectedConsumedHeightPx)
16758
+ );
16759
+ previousParagraphAfterPx = afterSpacingPx;
16760
+ return true;
16761
+ };
16762
+ if (tryConsumeExplicitColumnBreakParagraph()) {
16763
+ continue;
16764
+ }
16765
+ if (explicitColumnBreakParagraphSegments && explicitColumnBreakParagraphSegments.length > 1 && pageConsumedHeightPx > 0 && currentPageSegments.length > 0) {
16766
+ startNextPage();
16767
+ pageConsumedHeightPx = 0;
16768
+ previousParagraphAfterPx = 0;
16769
+ currentSectionPageFlowOriginPx = 0;
16770
+ currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16771
+ currentPageIndex,
16772
+ nodeMetrics
16773
+ );
16774
+ if (tryConsumeExplicitColumnBreakParagraph()) {
16775
+ continue;
16776
+ }
16777
+ }
15969
16778
  const widowControlEnabled = paragraphWidowControlEnabled(node);
15970
16779
  const minLinesPerSegment = widowControlEnabled ? 2 : 1;
15971
16780
  const canSplitParagraphAcrossPages = paragraphCanSplitAcrossPages(node, resolvedParagraphLineCount, {
@@ -15974,6 +16783,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15974
16783
  allowImageParagraphSplit: supportsImageParagraphLineSplit
15975
16784
  }) && (!widowControlEnabled || resolvedParagraphLineCount > 3);
15976
16785
  if (canSplitParagraphAcrossPages && allowParagraphLineSplitting) {
16786
+ const pretextLayoutForSegmentSplitting = resolveParagraphPretextLayoutForSegmentRendering();
15977
16787
  const resolveSegmentReservePx = (startLineIndex, endLineIndex) => {
15978
16788
  const paragraphSegmentRange = {
15979
16789
  startLineIndex,
@@ -15986,6 +16796,16 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15986
16796
  paragraphSegmentRange
15987
16797
  );
15988
16798
  };
16799
+ const resolveSegmentContentHeightPx = (startLineIndex, endLineIndex) => {
16800
+ if (pretextLayoutForSegmentSplitting && pretextLayoutForSegmentSplitting.lineCount > 0) {
16801
+ return resolvePretextLineRangeContentHeightPx(
16802
+ pretextLayoutForSegmentSplitting,
16803
+ startLineIndex,
16804
+ endLineIndex
16805
+ );
16806
+ }
16807
+ return Math.max(1, endLineIndex - startLineIndex) * paragraphLineHeightPx;
16808
+ };
15989
16809
  let lineCursor = 0;
15990
16810
  let isFirstSegment = true;
15991
16811
  while (lineCursor < resolvedParagraphLineCount) {
@@ -16001,7 +16821,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16001
16821
  lineCursor,
16002
16822
  resolvedParagraphLineCount
16003
16823
  );
16004
- const allRemainingHeightPx = topSpacingPx + linesRemaining * paragraphLineHeightPx + bottomSpacingPx;
16824
+ const allRemainingHeightPx = topSpacingPx + resolveSegmentContentHeightPx(
16825
+ lineCursor,
16826
+ resolvedParagraphLineCount
16827
+ ) + bottomSpacingPx;
16005
16828
  if (allRemainingHeightPx + allRemainingSegmentReservePx <= remainingHeightPx2) {
16006
16829
  currentPageSegments.push({
16007
16830
  nodeIndex,
@@ -16033,11 +16856,27 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16033
16856
  availableForLinesPx / paragraphLineHeightPx
16034
16857
  );
16035
16858
  linesThatFit = Math.min(linesThatFit, maxLinesThisPage);
16859
+ if (pretextLayoutForSegmentSplitting && pretextLayoutForSegmentSplitting.lineCount > 0 && linesThatFit > 0) {
16860
+ const exactSegmentEndLineIndex = resolveMaxPretextLineRangeEndIndexThatFits(
16861
+ pretextLayoutForSegmentSplitting,
16862
+ lineCursor,
16863
+ Math.min(
16864
+ resolvedParagraphLineCount,
16865
+ lineCursor + linesThatFit
16866
+ ),
16867
+ availableForLinesPx
16868
+ );
16869
+ linesThatFit = Math.max(
16870
+ 0,
16871
+ exactSegmentEndLineIndex - lineCursor
16872
+ );
16873
+ }
16036
16874
  if (linesThatFit < minLinesPerSegment) {
16037
16875
  if (currentPageSegments.length > 0) {
16038
16876
  startNextPage();
16039
16877
  pageConsumedHeightPx = 0;
16040
16878
  previousParagraphAfterPx = 0;
16879
+ currentSectionPageFlowOriginPx = 0;
16041
16880
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16042
16881
  currentPageIndex,
16043
16882
  nodeMetrics
@@ -16067,7 +16906,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16067
16906
  lineCursor,
16068
16907
  segmentEndLineIndex
16069
16908
  );
16070
- if (topSpacingPx + (segmentEndLineIndex - lineCursor) * paragraphLineHeightPx + segmentReservePx <= remainingHeightPx2) {
16909
+ if (topSpacingPx + resolveSegmentContentHeightPx(
16910
+ lineCursor,
16911
+ segmentEndLineIndex
16912
+ ) + segmentReservePx <= remainingHeightPx2) {
16071
16913
  break;
16072
16914
  }
16073
16915
  linesThatFit -= 1;
@@ -16089,7 +16931,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16089
16931
  lineHeightPx: paragraphLineHeightPx
16090
16932
  }
16091
16933
  });
16092
- pageConsumedHeightPx += topSpacingPx + (safeSegmentEndLineIndex - lineCursor) * paragraphLineHeightPx;
16934
+ pageConsumedHeightPx += topSpacingPx + resolveSegmentContentHeightPx(lineCursor, safeSegmentEndLineIndex);
16093
16935
  previousParagraphAfterPx = 0;
16094
16936
  lineCursor = safeSegmentEndLineIndex;
16095
16937
  isFirstSegment = false;
@@ -16097,6 +16939,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16097
16939
  startNextPage();
16098
16940
  pageConsumedHeightPx = 0;
16099
16941
  previousParagraphAfterPx = 0;
16942
+ currentSectionPageFlowOriginPx = 0;
16100
16943
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16101
16944
  currentPageIndex,
16102
16945
  nodeMetrics
@@ -16105,7 +16948,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16105
16948
  }
16106
16949
  continue;
16107
16950
  }
16108
- let requiredHeightPx = collapsedNodeHeightPx;
16951
+ let requiredHeightPx = collapsedNodeHeightPxAdjusted;
16109
16952
  if (node.style?.keepNext === true && paragraphHasVisibleText2(node)) {
16110
16953
  let chainCursor = nodeIndex;
16111
16954
  let chainPreviousParagraphAfterPx = afterSpacingPx;
@@ -16159,6 +17002,11 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16159
17002
  1,
16160
17003
  nextRawHeightPx - collapsedChainMarginPx
16161
17004
  );
17005
+ requiredHeightPx += keepNextPaginationReservePx(
17006
+ currentChainNode,
17007
+ nextChainNode,
17008
+ chainMetrics.docGridLinePitchPx
17009
+ );
16162
17010
  chainPreviousParagraphAfterPx = nextAfterSpacingPx;
16163
17011
  }
16164
17012
  }
@@ -16196,6 +17044,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16196
17044
  startNextPage();
16197
17045
  pageConsumedHeightPx = 0;
16198
17046
  previousParagraphAfterPx = 0;
17047
+ currentSectionPageFlowOriginPx = 0;
16199
17048
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16200
17049
  currentPageIndex,
16201
17050
  nodeMetrics
@@ -16221,7 +17070,8 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16221
17070
  node,
16222
17071
  nodeMetrics.pageContentWidthPx,
16223
17072
  numberingDefinitions,
16224
- nodeMetrics.docGridLinePitchPx
17073
+ nodeMetrics.docGridLinePitchPx,
17074
+ nodeMetrics.pageContentHeightPx
16225
17075
  );
16226
17076
  if (!measuredRowHeightsPx && !estimatedRowHeightsByTableNodeIndex.has(nodeIndex)) {
16227
17077
  estimatedRowHeightsByTableNodeIndex.set(nodeIndex, estimatedRowHeightsPx);
@@ -16237,14 +17087,45 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16237
17087
  startNextPage();
16238
17088
  pageConsumedHeightPx = 0;
16239
17089
  previousParagraphAfterPx = 0;
17090
+ currentSectionPageFlowOriginPx = 0;
16240
17091
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16241
17092
  currentPageIndex,
16242
17093
  nodeMetrics
16243
17094
  );
16244
17095
  }
17096
+ let headerRunLength = 0;
17097
+ for (const row of node.rows) {
17098
+ if (row.style?.isHeader === true) {
17099
+ headerRunLength += 1;
17100
+ } else {
17101
+ break;
17102
+ }
17103
+ }
17104
+ const headerRunHeightPx = headerRunLength > 0 ? sumEstimatedTableRowHeightsPx(
17105
+ estimatedRowHeightsPx,
17106
+ 0,
17107
+ headerRunLength
17108
+ ) : 0;
17109
+ const canRepeatHeader = headerRunLength > 0 && headerRunHeightPx > 0 && headerRunHeightPx + MIN_PARAGRAPH_LINE_HEIGHT_PX * 2 < currentPageContentHeightPx;
16245
17110
  let rowStartIndex = 0;
16246
17111
  let rowSliceOffsetPx = 0;
17112
+ let repeatedHeaderHeightPxOnThisPage = 0;
16247
17113
  while (rowStartIndex < estimatedRowHeightsPx.length) {
17114
+ if (currentPageSegments.length === 0) {
17115
+ repeatedHeaderHeightPxOnThisPage = 0;
17116
+ }
17117
+ if (canRepeatHeader && rowStartIndex >= headerRunLength && currentPageSegments.length === 0) {
17118
+ currentPageSegments.push({
17119
+ nodeIndex,
17120
+ tableRowRange: {
17121
+ startRowIndex: 0,
17122
+ endRowIndex: headerRunLength
17123
+ }
17124
+ });
17125
+ pageConsumedHeightPx += headerRunHeightPx;
17126
+ previousParagraphAfterPx = 0;
17127
+ repeatedHeaderHeightPxOnThisPage = headerRunHeightPx;
17128
+ }
16248
17129
  const remainingHeightPx = Math.max(
16249
17130
  0,
16250
17131
  currentPageContentHeightPx - pageConsumedHeightPx
@@ -16258,7 +17139,11 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16258
17139
  0,
16259
17140
  currentRowTotalHeightPx - rowSliceOffsetPx
16260
17141
  );
16261
- const rowExceedsFreshPageHeightPx = currentRowTotalHeightPx > currentPageContentHeightPx + PAGE_OVERFLOW_TOLERANCE_PX;
17142
+ const freshPageAvailableHeightPx = Math.max(
17143
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
17144
+ currentPageContentHeightPx - repeatedHeaderHeightPxOnThisPage
17145
+ );
17146
+ const rowExceedsFreshPageHeightPx = currentRowTotalHeightPx > freshPageAvailableHeightPx + PAGE_OVERFLOW_TOLERANCE_PX;
16262
17147
  const canSplitCurrentRow = rowSliceOffsetPx > 0 || rowAllowsPageSplit(currentRow) || rowExceedsFreshPageHeightPx;
16263
17148
  const shouldContinueExistingRowSlice = rowSliceOffsetPx > 0;
16264
17149
  const rowNeedsSliceOnThisPage = ENABLE_TABLE_ROW_SLICING && canSplitCurrentRow && currentRowRemainingHeightPx > remainingHeightPx + PAGE_OVERFLOW_TOLERANCE_PX && (shouldContinueExistingRowSlice || rowExceedsFreshPageHeightPx);
@@ -16266,6 +17151,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16266
17151
  startNextPage();
16267
17152
  pageConsumedHeightPx = 0;
16268
17153
  previousParagraphAfterPx = 0;
17154
+ currentSectionPageFlowOriginPx = 0;
16269
17155
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16270
17156
  currentPageIndex,
16271
17157
  nodeMetrics
@@ -16277,6 +17163,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16277
17163
  startNextPage();
16278
17164
  pageConsumedHeightPx = 0;
16279
17165
  previousParagraphAfterPx = 0;
17166
+ currentSectionPageFlowOriginPx = 0;
16280
17167
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16281
17168
  currentPageIndex,
16282
17169
  nodeMetrics
@@ -16318,6 +17205,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16318
17205
  startNextPage();
16319
17206
  pageConsumedHeightPx = 0;
16320
17207
  previousParagraphAfterPx = 0;
17208
+ currentSectionPageFlowOriginPx = 0;
16321
17209
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16322
17210
  currentPageIndex,
16323
17211
  nodeMetrics
@@ -16326,6 +17214,24 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16326
17214
  continue;
16327
17215
  }
16328
17216
  if (rowSliceOffsetPx > 0) {
17217
+ currentPageSegments.push({
17218
+ nodeIndex,
17219
+ tableRowRange: {
17220
+ startRowIndex: rowStartIndex,
17221
+ endRowIndex: Math.min(
17222
+ estimatedRowHeightsPx.length,
17223
+ rowStartIndex + 1
17224
+ )
17225
+ },
17226
+ tableRowSlice: {
17227
+ rowIndex: rowStartIndex,
17228
+ startOffsetPx: rowSliceOffsetPx,
17229
+ sliceHeightPx: currentRowRemainingHeightPx,
17230
+ totalRowHeightPx: currentRowTotalHeightPx
17231
+ }
17232
+ });
17233
+ pageConsumedHeightPx += currentRowRemainingHeightPx;
17234
+ previousParagraphAfterPx = 0;
16329
17235
  rowStartIndex += 1;
16330
17236
  rowSliceOffsetPx = 0;
16331
17237
  continue;
@@ -16348,6 +17254,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16348
17254
  startNextPage();
16349
17255
  pageConsumedHeightPx = 0;
16350
17256
  previousParagraphAfterPx = 0;
17257
+ currentSectionPageFlowOriginPx = 0;
16351
17258
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16352
17259
  currentPageIndex,
16353
17260
  nodeMetrics
@@ -16378,6 +17285,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16378
17285
  startNextPage();
16379
17286
  pageConsumedHeightPx = 0;
16380
17287
  previousParagraphAfterPx = 0;
17288
+ currentSectionPageFlowOriginPx = 0;
16381
17289
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16382
17290
  currentPageIndex,
16383
17291
  nodeMetrics
@@ -16406,6 +17314,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16406
17314
  startNextPage();
16407
17315
  pageConsumedHeightPx = 0;
16408
17316
  previousParagraphAfterPx = 0;
17317
+ currentSectionPageFlowOriginPx = 0;
16409
17318
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16410
17319
  currentPageIndex,
16411
17320
  nodeMetrics
@@ -16877,6 +17786,10 @@ function resolveHighlightColor(value) {
16877
17786
  }
16878
17787
  function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap = false) {
16879
17788
  const baseFontFamily = paragraphDominantFontFamily(paragraph);
17789
+ const singleLineScale = resolveParagraphSingleLineAutoScale(
17790
+ paragraph,
17791
+ baseFontFamily
17792
+ );
16880
17793
  const lineTwips = paragraph.style?.spacing?.lineTwips;
16881
17794
  const docGridMinimumLineHeightPx = resolveParagraphDocGridLinePitchPx(
16882
17795
  paragraph,
@@ -16893,7 +17806,8 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16893
17806
  }
16894
17807
  return calibrateAutoLineSpacingMultiple(
16895
17808
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16896
- baseFontFamily
17809
+ baseFontFamily,
17810
+ singleLineScale
16897
17811
  );
16898
17812
  }
16899
17813
  const lineRule = paragraph.style?.spacing?.lineRule ?? "auto";
@@ -16910,7 +17824,8 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16910
17824
  lineTwips,
16911
17825
  DEFAULT_PARAGRAPH_LINE_MULTIPLE
16912
17826
  ),
16913
- baseFontFamily
17827
+ baseFontFamily,
17828
+ singleLineScale
16914
17829
  );
16915
17830
  return Number(lineMultiple.toFixed(3));
16916
17831
  }
@@ -16921,7 +17836,8 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16921
17836
  Math.round(
16922
17837
  paragraphBaseFontSizePx(paragraph) * calibrateAutoLineSpacingMultiple(
16923
17838
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16924
- baseFontFamily
17839
+ baseFontFamily,
17840
+ singleLineScale
16925
17841
  )
16926
17842
  )
16927
17843
  );
@@ -16937,12 +17853,29 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16937
17853
  if (lineRule === "exact") {
16938
17854
  return calibrateAutoLineSpacingMultiple(
16939
17855
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16940
- baseFontFamily
17856
+ baseFontFamily,
17857
+ singleLineScale
16941
17858
  );
16942
17859
  }
16943
17860
  return calibrateAutoLineSpacingMultiple(
16944
17861
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16945
- baseFontFamily
17862
+ baseFontFamily,
17863
+ singleLineScale
17864
+ );
17865
+ }
17866
+ function keepNextPaginationReservePx(paragraph, nextParagraph, docGridLinePitchPx) {
17867
+ if (paragraph.style?.keepNext !== true || !nextParagraph || !Number.isFinite(paragraph.style?.headingLevel)) {
17868
+ return 0;
17869
+ }
17870
+ const nextParagraphText = paragraphText(nextParagraph).replace(/\s+/g, " ").trim();
17871
+ if (nextParagraph.style?.numbering === void 0 && nextParagraphText.length < 80) {
17872
+ return 0;
17873
+ }
17874
+ return Math.max(
17875
+ nextParagraph.style?.numbering ? 10 : 6,
17876
+ Math.round(
17877
+ estimateParagraphLineHeightPx(nextParagraph, docGridLinePitchPx) * (nextParagraph.style?.numbering ? 1 : 0.5)
17878
+ )
16946
17879
  );
16947
17880
  }
16948
17881
  function paragraphBorderToCss(border) {
@@ -17516,6 +18449,17 @@ function tableOfContentsLeadingLeftTabStopPx(paragraph) {
17516
18449
  ).sort((left, right) => left - right);
17517
18450
  return leftTabStopPositionsPx[0];
17518
18451
  }
18452
+ function paragraphContainsTabCharacter(paragraph) {
18453
+ return paragraph.children.some((child) => {
18454
+ if (child.type === "text") {
18455
+ return child.text.includes(" ");
18456
+ }
18457
+ if (child.type === "form-field") {
18458
+ return formFieldDisplayValue2(child).includes(" ");
18459
+ }
18460
+ return false;
18461
+ });
18462
+ }
17519
18463
  function paragraphTabCharacterCount(paragraph) {
17520
18464
  return paragraph.children.reduce((count, child) => {
17521
18465
  const text = child.type === "text" ? child.text : child.type === "form-field" ? formFieldDisplayValue2(child) : "";
@@ -18910,6 +19854,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
18910
19854
  ) ? Math.round(options?.floatingAnchorOriginCorrectionXPx) : 0;
18911
19855
  const checkboxChoiceRow = paragraphLooksLikeCheckboxChoiceRow(paragraph);
18912
19856
  const fallbackTabWidthPx = checkboxChoiceRow ? checkboxChoiceRowTabWidthPx(paragraph) : DEFAULT_TAB_STOP_PX;
19857
+ const tabLeaderLeftTabStopPositionsPx = useTabLeaderLayout ? resolveParagraphFirstLineLeftTabStopsPx(paragraph) : [];
18913
19858
  const shouldTrackTabLineWidth = !useTabLeaderLayout && !useAnchoredTabLayout;
18914
19859
  let approximateLineWidthPx = 0;
18915
19860
  let trackedVisibleChildCursor = 0;
@@ -19028,6 +19973,32 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19028
19973
  lineHeight: "1em"
19029
19974
  };
19030
19975
  };
19976
+ const renderTabLeaderLeftSpacer = (target, key, style, trackedInlineChange, widthPx) => {
19977
+ const textStyle = trackedInlineStyle(
19978
+ runStyleToCss(style, documentTheme),
19979
+ trackedInlineChange
19980
+ );
19981
+ const hasUnderline = Boolean(style?.underline);
19982
+ target.push(
19983
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
19984
+ "span",
19985
+ {
19986
+ style: {
19987
+ ...textStyle,
19988
+ display: "inline-block",
19989
+ width: widthPx,
19990
+ minWidth: widthPx,
19991
+ whiteSpace: "pre",
19992
+ textDecoration: hasUnderline ? "none" : textStyle.textDecoration,
19993
+ borderBottom: hasUnderline ? "1px solid currentColor" : void 0,
19994
+ lineHeight: "1em"
19995
+ },
19996
+ children: "\xA0"
19997
+ },
19998
+ key
19999
+ )
20000
+ );
20001
+ };
19031
20002
  const resolvePageFieldText = (value, preferredZone) => {
19032
20003
  if (!hasPageField || value.trim().length === 0) {
19033
20004
  return value;
@@ -19317,7 +20288,10 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19317
20288
  (() => {
19318
20289
  const cropLayout = imageCropLayout(child, widthPx, heightPx);
19319
20290
  const imageVisualStyle = {
19320
- filter: appendCssFilters(child.cssFilter, options?.imageFilterSuffix),
20291
+ filter: appendCssFilters(
20292
+ child.cssFilter,
20293
+ options?.imageFilterSuffix
20294
+ ),
19321
20295
  opacity: child.cssOpacity
19322
20296
  };
19323
20297
  const imageTransformStyle = resolveImageRenderTransformStyle(child, {
@@ -19638,14 +20612,42 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19638
20612
  return;
19639
20613
  }
19640
20614
  if (leftText.length > 0) {
19641
- renderRun(
19642
- runsLeft,
19643
- child,
19644
- `${keyPrefix}-run-${childIndex}-left`,
19645
- resolveFieldText(leftText, 0),
19646
- trackedInlineChange,
19647
- childIndex
19648
- );
20615
+ let tabLeaderLeftLineWidthPx = 0;
20616
+ const leftTextParts = leftText.split(" ");
20617
+ leftTextParts.forEach((part, partIndex) => {
20618
+ if (part.length > 0) {
20619
+ const resolvedPart = resolveFieldText(part, 0);
20620
+ renderRun(
20621
+ runsLeft,
20622
+ child,
20623
+ `${keyPrefix}-run-${childIndex}-left-${partIndex}`,
20624
+ resolvedPart,
20625
+ trackedInlineChange,
20626
+ childIndex
20627
+ );
20628
+ tabLeaderLeftLineWidthPx = updateEstimatedLineWidthPxForText(
20629
+ tabLeaderLeftLineWidthPx,
20630
+ resolvedPart,
20631
+ child.style
20632
+ );
20633
+ }
20634
+ if (partIndex >= leftTextParts.length - 1) {
20635
+ return;
20636
+ }
20637
+ const tabWidthPx = resolveTabSpacerWidthPx(
20638
+ tabLeaderLeftTabStopPositionsPx,
20639
+ tabLeaderLeftLineWidthPx,
20640
+ fallbackTabWidthPx
20641
+ );
20642
+ renderTabLeaderLeftSpacer(
20643
+ runsLeft,
20644
+ `${keyPrefix}-run-${childIndex}-left-tab-${partIndex}`,
20645
+ child.style,
20646
+ trackedInlineChange,
20647
+ tabWidthPx
20648
+ );
20649
+ tabLeaderLeftLineWidthPx += tabWidthPx;
20650
+ });
19649
20651
  }
19650
20652
  renderRun(
19651
20653
  runsRight,
@@ -19871,10 +20873,10 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19871
20873
  {
19872
20874
  "data-docx-tab-zone": "left",
19873
20875
  style: {
19874
- display: "inline-flex",
20876
+ display: "block",
20877
+ flex: "0 1 auto",
19875
20878
  minWidth: 0,
19876
- whiteSpace: "pre-wrap",
19877
- alignItems: "baseline"
20879
+ whiteSpace: "pre-wrap"
19878
20880
  },
19879
20881
  children: runsLeft
19880
20882
  }
@@ -19902,12 +20904,13 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19902
20904
  {
19903
20905
  "data-docx-tab-zone": "right",
19904
20906
  style: {
19905
- display: "inline-flex",
19906
- minWidth: 0,
19907
- justifyContent: "flex-end",
20907
+ display: "block",
20908
+ flex: "0 0 max-content",
20909
+ minWidth: "max-content",
20910
+ width: "max-content",
19908
20911
  textAlign: "right",
19909
- whiteSpace: "pre-wrap",
19910
- alignItems: "baseline"
20912
+ whiteSpace: "nowrap",
20913
+ textIndent: 0
19911
20914
  },
19912
20915
  children: runsRight
19913
20916
  }
@@ -20157,20 +21160,7 @@ function buildParagraphNumberingLabels(model) {
20157
21160
  ])
20158
21161
  );
20159
21162
  const countersByNumId = /* @__PURE__ */ new Map();
20160
- const headingCountersByAbstractNumId = /* @__PURE__ */ new Map();
20161
- const isHeadingLikeParagraph = (paragraph) => {
20162
- if (Number.isFinite(paragraph.style?.headingLevel)) {
20163
- return true;
20164
- }
20165
- if (isTableOfContentsParagraph(paragraph)) {
20166
- return true;
20167
- }
20168
- const styleId = paragraph.style?.styleId?.trim().toLowerCase();
20169
- if (!styleId) {
20170
- return false;
20171
- }
20172
- return /(?:^|[\s_-])heading(?:[\s_-]?\d+)?$/.test(styleId) || /^heading\d*$/.test(styleId);
20173
- };
21163
+ const abstractCountersByAbstractNumId = /* @__PURE__ */ new Map();
20174
21164
  const registerParagraph = (paragraph, key) => {
20175
21165
  const paragraphNumbering = paragraph.style?.numbering;
20176
21166
  if (!paragraphNumbering || paragraphNumbering.numId <= 0) {
@@ -20181,13 +21171,12 @@ function buildParagraphNumberingLabels(model) {
20181
21171
  const level = findNumberingLevelDefinition(numbering, numId, ilvl);
20182
21172
  const numberingInstance = numberingInstanceByNumId.get(numId);
20183
21173
  const abstractNumId = numberingInstance?.abstractNumId;
20184
- const isSharedCounterParagraph = isHeadingLikeParagraph(paragraph);
20185
21174
  const template = level?.text ?? `%${ilvl + 1}.`;
20186
21175
  if (!template || template.trim().length === 0) {
20187
21176
  return;
20188
21177
  }
20189
21178
  const counters = countersByNumId.get(numId) ?? [];
20190
- const sharedAbstractCounters = isSharedCounterParagraph && Number.isFinite(abstractNumId) ? headingCountersByAbstractNumId.get(abstractNumId) ?? [] : void 0;
21179
+ const sharedAbstractCounters = Number.isFinite(abstractNumId) ? abstractCountersByAbstractNumId.get(abstractNumId) ?? [] : void 0;
20191
21180
  let parentCountersChanged = false;
20192
21181
  for (let index = 0; index < ilvl; index += 1) {
20193
21182
  const abstractCounterValue = sharedAbstractCounters && Number.isFinite(sharedAbstractCounters[index]) ? Math.max(1, Math.round(sharedAbstractCounters[index])) : void 0;
@@ -20216,7 +21205,7 @@ function buildParagraphNumberingLabels(model) {
20216
21205
  for (let index = ilvl + 1; index < sharedAbstractCounters.length; index += 1) {
20217
21206
  sharedAbstractCounters[index] = void 0;
20218
21207
  }
20219
- headingCountersByAbstractNumId.set(
21208
+ abstractCountersByAbstractNumId.set(
20220
21209
  abstractNumId,
20221
21210
  sharedAbstractCounters
20222
21211
  );
@@ -20962,6 +21951,14 @@ function tableBorderToCss(border) {
20962
21951
  const color = border?.color ?? "#000000";
20963
21952
  return `${widthPx}px ${cssStyle} ${color}`;
20964
21953
  }
21954
+ function tableBorderStrokeWidthPx(border) {
21955
+ const type = normalizeBorderType(border?.type);
21956
+ if (!type || type === "none" || type === "nil") {
21957
+ return 0;
21958
+ }
21959
+ const sizeEighthPt = border?.sizeEighthPt;
21960
+ return Number.isFinite(sizeEighthPt) && sizeEighthPt > 0 ? Math.max(0.5, Number((sizeEighthPt / 6).toFixed(2))) : 1;
21961
+ }
20965
21962
  function borderTypeVisible(type) {
20966
21963
  const normalizedType = normalizeBorderType(type);
20967
21964
  return Boolean(
@@ -21413,6 +22410,68 @@ function resolveTableCellBorderCss(tableBorders, cellBorders, rowIndex, rowCount
21413
22410
  ...left !== void 0 ? { borderLeft: left } : void 0
21414
22411
  };
21415
22412
  }
22413
+ function resolveCollapsedTableHorizontalOuterBleedPx(table, columnCount = tableColumnCount(table)) {
22414
+ if (columnCount <= 0 || tableUsesSeparateBorderModel(table)) {
22415
+ return 0;
22416
+ }
22417
+ const rowCount = table.rows.length;
22418
+ const tableBorders = table.style?.borders;
22419
+ let maxLeftBorderWidthPx = tableBorderStrokeWidthPx(tableBorders?.left);
22420
+ let maxRightBorderWidthPx = tableBorderStrokeWidthPx(tableBorders?.right);
22421
+ table.rows.forEach((row, rowIndex) => {
22422
+ let columnCursor = 0;
22423
+ row.cells.forEach((cell) => {
22424
+ const columnSpan = cell.style?.gridSpan && cell.style.gridSpan > 1 ? cell.style.gridSpan : 1;
22425
+ const startColumnIndex = columnCursor;
22426
+ const endColumnIndex = Math.min(
22427
+ columnCount - 1,
22428
+ startColumnIndex + columnSpan - 1
22429
+ );
22430
+ columnCursor += columnSpan;
22431
+ if (cell.style?.vMergeContinuation) {
22432
+ return;
22433
+ }
22434
+ if (startColumnIndex === 0) {
22435
+ maxLeftBorderWidthPx = Math.max(
22436
+ maxLeftBorderWidthPx,
22437
+ tableBorderStrokeWidthPx(
22438
+ resolveTableBorder(
22439
+ tableBorders,
22440
+ cell.style?.borders,
22441
+ "left",
22442
+ rowIndex,
22443
+ rowCount,
22444
+ startColumnIndex,
22445
+ endColumnIndex,
22446
+ columnCount
22447
+ )
22448
+ )
22449
+ );
22450
+ }
22451
+ if (endColumnIndex >= columnCount - 1) {
22452
+ maxRightBorderWidthPx = Math.max(
22453
+ maxRightBorderWidthPx,
22454
+ tableBorderStrokeWidthPx(
22455
+ resolveTableBorder(
22456
+ tableBorders,
22457
+ cell.style?.borders,
22458
+ "right",
22459
+ rowIndex,
22460
+ rowCount,
22461
+ startColumnIndex,
22462
+ endColumnIndex,
22463
+ columnCount
22464
+ )
22465
+ )
22466
+ );
22467
+ }
22468
+ });
22469
+ });
22470
+ return Math.max(
22471
+ 0,
22472
+ Math.ceil((maxLeftBorderWidthPx + maxRightBorderWidthPx) / 2)
22473
+ );
22474
+ }
21416
22475
  function resolveTableCellDiagonalOverlayCss(tableBorders, cellBorders) {
21417
22476
  const diagonalDownBorder = cellBorders?.tl2br ?? tableBorders?.tl2br;
21418
22477
  const diagonalUpBorder = cellBorders?.tr2bl ?? tableBorders?.tr2bl;
@@ -23304,6 +24363,7 @@ function useDocxEditor(options = {}) {
23304
24363
  const [status, setStatus] = React.useState(
23305
24364
  options.initialStatus ?? "Ready"
23306
24365
  );
24366
+ const isImporting = false;
23307
24367
  const [documentTheme, setDocumentThemeState] = React.useState(options.initialDocumentTheme ?? "light");
23308
24368
  const [showTrackedChanges, setShowTrackedChangesState] = React.useState(options.initialShowTrackedChanges ?? false);
23309
24369
  const [paginationInfo, setPaginationInfo] = React.useState({
@@ -26770,6 +27830,7 @@ function useDocxEditor(options = {}) {
26770
27830
  documentLoadNonce,
26771
27831
  fileName,
26772
27832
  status,
27833
+ isImporting,
26773
27834
  documentTheme,
26774
27835
  trackedChanges,
26775
27836
  showTrackedChanges,
@@ -27054,12 +28115,9 @@ function useDocxPageThumbnails(editor, options = {}) {
27054
28115
  [pageSurfaceRegistryEditor]
27055
28116
  );
27056
28117
  React.useEffect(
27057
- () => subscribeDocxViewerPageSurfaces(
27058
- pageSurfaceRegistryEditor,
27059
- () => {
27060
- setPageSurfaceEpoch((current) => current + 1);
27061
- }
27062
- ),
28118
+ () => subscribeDocxViewerPageSurfaces(pageSurfaceRegistryEditor, () => {
28119
+ setPageSurfaceEpoch((current) => current + 1);
28120
+ }),
27063
28121
  [pageSurfaceRegistryEditor]
27064
28122
  );
27065
28123
  const mountedPageElements = React.useMemo(
@@ -27146,7 +28204,9 @@ function useDocxPageThumbnails(editor, options = {}) {
27146
28204
  );
27147
28205
  await Promise.all(tasks);
27148
28206
  }, [renderPageThumbnailToCanvas]);
27149
- const renderPageThumbnailToCanvasRef = React.useRef(renderPageThumbnailToCanvas);
28207
+ const renderPageThumbnailToCanvasRef = React.useRef(
28208
+ renderPageThumbnailToCanvas
28209
+ );
27150
28210
  React.useEffect(() => {
27151
28211
  renderPageThumbnailToCanvasRef.current = renderPageThumbnailToCanvas;
27152
28212
  }, [renderPageThumbnailToCanvas]);
@@ -27781,7 +28841,11 @@ function renderHeaderNode(node, keyPrefix, documentTheme, numberingDefinitions,
27781
28841
  return normalizeColumnWidthsPx(widthsPx, columnCount, tableWidthPx, 1);
27782
28842
  })();
27783
28843
  const rawResolvedTableWidthPx = tableWidthPx ?? rawTableColumnWidthsPx.reduce((sum, widthPx) => sum + widthPx, 0);
27784
- const maxTableWidthPx = Number.isFinite(maxContentWidthPx) && maxContentWidthPx > 0 ? Math.max(120, maxContentWidthPx - tableIndentPx) : void 0;
28844
+ const collapsedHorizontalBorderBleedPx = resolveCollapsedTableHorizontalOuterBleedPx(node, columnCount);
28845
+ const maxTableWidthPx = Number.isFinite(maxContentWidthPx) && maxContentWidthPx > 0 ? Math.max(
28846
+ 120,
28847
+ maxContentWidthPx - tableIndentPx - collapsedHorizontalBorderBleedPx
28848
+ ) : void 0;
27785
28849
  const resolvedTableWidthPx = clampTableWidthPx(
27786
28850
  rawResolvedTableWidthPx,
27787
28851
  maxTableWidthPx
@@ -27894,6 +28958,7 @@ function renderHeaderNode(node, keyPrefix, documentTheme, numberingDefinitions,
27894
28958
  "span",
27895
28959
  {
27896
28960
  contentEditable: false,
28961
+ "data-docx-pagination-ignore": "true",
27897
28962
  style: {
27898
28963
  position: "absolute",
27899
28964
  top: -TABLE_HANDLE_SAFEZONE_TOP_PX,
@@ -27911,6 +28976,7 @@ function renderHeaderNode(node, keyPrefix, documentTheme, numberingDefinitions,
27911
28976
  "span",
27912
28977
  {
27913
28978
  contentEditable: false,
28979
+ "data-docx-pagination-ignore": "true",
27914
28980
  style: {
27915
28981
  position: "absolute",
27916
28982
  right: -TABLE_HANDLE_SAFEZONE_RIGHT_PX,
@@ -28522,6 +29588,11 @@ function DocxEditorViewer({
28522
29588
  measuredPageContentIdentityKeysByIndex,
28523
29589
  setMeasuredPageContentIdentityKeysByIndex
28524
29590
  ] = React.useState([]);
29591
+ const [hasMeasuredBodyFooterOverlap, setHasMeasuredBodyFooterOverlap] = React.useState(false);
29592
+ const measuredBodyFooterOverlapCandidateRef = React.useRef({
29593
+ signature: void 0,
29594
+ consecutivePasses: 0
29595
+ });
28525
29596
  const [, setRenderableImageSourceRevision] = React.useState(0);
28526
29597
  const [activeEditableParagraphSegment, setActiveEditableParagraphSegment] = React.useState(void 0);
28527
29598
  const wrappedParagraphTextareaRef = React.useRef(
@@ -28531,6 +29602,10 @@ function DocxEditorViewer({
28531
29602
  const wrappedParagraphSelectionDragRef = React.useRef(void 0);
28532
29603
  const wrappedParagraphSurfaceRegistryRef = React.useRef(/* @__PURE__ */ new Map());
28533
29604
  const [isInitialPaginationSettled, setIsInitialPaginationSettled] = React.useState(!deferInitialPaginationPaint);
29605
+ const [
29606
+ initialPaginationBackgroundRefinementUnlocked,
29607
+ setInitialPaginationBackgroundRefinementUnlocked
29608
+ ] = React.useState(!deferInitialPaginationPaint);
28534
29609
  const [postImportPaginationUnlocked, setPostImportPaginationUnlocked] = React.useState(false);
28535
29610
  const [
28536
29611
  initialPaginationReservedLayoutState,
@@ -28572,6 +29647,11 @@ function DocxEditorViewer({
28572
29647
  React.useEffect(() => {
28573
29648
  setMeasuredPageContentHeightByIndex([]);
28574
29649
  setMeasuredPageContentIdentityKeysByIndex([]);
29650
+ setHasMeasuredBodyFooterOverlap(false);
29651
+ measuredBodyFooterOverlapCandidateRef.current = {
29652
+ signature: void 0,
29653
+ consecutivePasses: 0
29654
+ };
28575
29655
  setTableMeasuredRowHeights({});
28576
29656
  setTableRowHeights({});
28577
29657
  setTableColumnWidths({});
@@ -28615,6 +29695,9 @@ function DocxEditorViewer({
28615
29695
  }
28616
29696
  initialPaginationRevealFrameRef.current = null;
28617
29697
  setIsInitialPaginationSettled(!deferInitialPaginationPaint);
29698
+ setInitialPaginationBackgroundRefinementUnlocked(
29699
+ !deferInitialPaginationPaint
29700
+ );
28618
29701
  }, [deferInitialPaginationPaint, editor.documentLoadNonce]);
28619
29702
  const [activeRowResize, setActiveRowResize] = React.useState();
28620
29703
  const [activeEmbeddedRowResize, setActiveEmbeddedRowResize] = React.useState();
@@ -28903,6 +29986,28 @@ function DocxEditorViewer({
28903
29986
  }
28904
29987
  return widthByNodeIndex;
28905
29988
  }, [editor.model.nodes, paginationSectionMetrics]);
29989
+ const pageContentHeightPxByNodeIndex = React.useMemo(() => {
29990
+ const heightByNodeIndex = /* @__PURE__ */ new Map();
29991
+ if (editor.model.nodes.length === 0 || paginationSectionMetrics.length === 0) {
29992
+ return heightByNodeIndex;
29993
+ }
29994
+ let currentMetricsIndex = 0;
29995
+ for (let nodeIndex = 0; nodeIndex < editor.model.nodes.length; nodeIndex += 1) {
29996
+ currentMetricsIndex = resolvePaginationSectionMetricsIndexForNodeIndex(
29997
+ paginationSectionMetrics,
29998
+ nodeIndex,
29999
+ currentMetricsIndex
30000
+ );
30001
+ const pageContentHeightPx = paginationSectionMetrics[currentMetricsIndex]?.pageContentHeightPx;
30002
+ if (Number.isFinite(pageContentHeightPx) && pageContentHeightPx > 0) {
30003
+ heightByNodeIndex.set(
30004
+ nodeIndex,
30005
+ Math.round(pageContentHeightPx)
30006
+ );
30007
+ }
30008
+ }
30009
+ return heightByNodeIndex;
30010
+ }, [editor.model.nodes, paginationSectionMetrics]);
28906
30011
  const sectionColumnsBySectionIndex = React.useMemo(
28907
30012
  () => documentSections.map(
28908
30013
  (section) => parseSectionColumns(section.sectionPropertiesXml)
@@ -28952,6 +30057,7 @@ function DocxEditorViewer({
28952
30057
  activeDraftKeys,
28953
30058
  numberingDefinitions: editor.model.metadata.numberingDefinitions,
28954
30059
  pageContentWidthPxByNodeIndex,
30060
+ pageContentHeightPxByNodeIndex,
28955
30061
  docGridLinePitchPxByNodeIndex
28956
30062
  }
28957
30063
  );
@@ -28961,6 +30067,7 @@ function DocxEditorViewer({
28961
30067
  editor.canUndo,
28962
30068
  editor.model.metadata.numberingDefinitions,
28963
30069
  editor.model.nodes,
30070
+ pageContentHeightPxByNodeIndex,
28964
30071
  pageContentWidthPxByNodeIndex,
28965
30072
  disableMeasuredImportPagination,
28966
30073
  tableDraftLayoutEpoch,
@@ -29018,17 +30125,43 @@ function DocxEditorViewer({
29018
30125
  (count, node) => count + (node.type === "paragraph" && paragraphHasLastRenderedPageBreak(node) ? 1 : 0),
29019
30126
  0
29020
30127
  ) : void 0;
30128
+ const hasMultiColumnRenderedPageBreakHints = editor.model.nodes.some(
30129
+ (node, nodeIndex) => {
30130
+ if (node.type !== "paragraph" || !paragraphStartsWithLastRenderedPageBreak(node)) {
30131
+ return false;
30132
+ }
30133
+ const metricsIndex = resolvePaginationSectionMetricsIndexForNodeIndex(
30134
+ paginationSectionMetrics,
30135
+ nodeIndex,
30136
+ 0
30137
+ );
30138
+ return (paginationSectionMetrics[metricsIndex]?.pageContentHeightMultiplier ?? 1) > 1;
30139
+ }
30140
+ );
29021
30141
  const minimumPageCount = Math.max(1, hardBreakCount + 1);
29022
30142
  const targetPageCount = Number.isFinite(storedDocumentPageCount2) && storedDocumentPageCount2 > 0 ? Math.max(
29023
30143
  minimumPageCount,
29024
30144
  Math.round(storedDocumentPageCount2)
29025
30145
  ) : void 0;
30146
+ let estimatedPages = buildEstimatedPages(
30147
+ tableMeasuredRowHeightsForPagination
30148
+ );
30149
+ let estimatedPagesUseMeasuredPageContentHeightsForRender = canUseMeasuredPageContentHeights;
30150
+ let estimatedRenderMeasuredPageContentHeightsPxByPageIndex = canUseMeasuredPageContentHeights ? measuredPageContentHeightByIndex : void 0;
30151
+ let estimatedRenderPageContentHeightScale = void 0;
30152
+ const deferExpensiveInitialPaginationReconciliation = deferInitialPaginationPaint && !initialPaginationBackgroundRefinementUnlocked;
30153
+ if (deferExpensiveInitialPaginationReconciliation) {
30154
+ return {
30155
+ pages: estimatedPages,
30156
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30157
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30158
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
30159
+ };
30160
+ }
29026
30161
  const pureEstimatedPages = buildEstimatedPages(
29027
30162
  tableMeasuredRowHeightsForPagination,
29028
30163
  null
29029
30164
  );
29030
- let estimatedPages = buildEstimatedPages(tableMeasuredRowHeightsForPagination);
29031
- let estimatedPagesUseMeasuredPageContentHeightsForRender = canUseMeasuredPageContentHeights;
29032
30165
  if (measuredPageContentHeightByIndex && measuredPageContentHeightByIndex.length > 0) {
29033
30166
  const measuredPagesAreOnlySplitParagraphs = estimatedPages.length > 0 && estimatedPages.every(
29034
30167
  (pageSegments) => documentPageContainsOnlySplitParagraphSegments(pageSegments)
@@ -29039,21 +30172,29 @@ function DocxEditorViewer({
29039
30172
  if (measuredPagesAreOnlySplitParagraphs && purePagesAreOnlySplitParagraphs && pureEstimatedPages.length < estimatedPages.length) {
29040
30173
  estimatedPages = pureEstimatedPages;
29041
30174
  estimatedPagesUseMeasuredPageContentHeightsForRender = false;
30175
+ estimatedRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30176
+ estimatedRenderPageContentHeightScale = void 0;
29042
30177
  }
29043
30178
  }
29044
- if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && tableMeasuredRowHeightsForPagination) {
30179
+ if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && tableMeasuredRowHeightsForPagination && !hasMultiColumnRenderedPageBreakHints) {
29045
30180
  const candidatePages = [
29046
30181
  {
29047
30182
  pages: estimatedPages,
29048
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30183
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30184
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30185
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
29049
30186
  },
29050
30187
  {
29051
30188
  pages: buildEstimatedPages(void 0),
29052
- useMeasuredPageContentHeightsForRender: canUseMeasuredPageContentHeights
30189
+ useMeasuredPageContentHeightsForRender: canUseMeasuredPageContentHeights,
30190
+ renderMeasuredPageContentHeightsPxByPageIndex: canUseMeasuredPageContentHeights ? measuredPageContentHeightByIndex : void 0,
30191
+ renderPageContentHeightScale: void 0
29053
30192
  },
29054
30193
  {
29055
30194
  pages: buildEstimatedPages(void 0, null),
29056
- useMeasuredPageContentHeightsForRender: false
30195
+ useMeasuredPageContentHeightsForRender: false,
30196
+ renderMeasuredPageContentHeightsPxByPageIndex: void 0,
30197
+ renderPageContentHeightScale: void 0
29057
30198
  }
29058
30199
  ];
29059
30200
  const bestCandidate = candidatePages.reduce((best, candidate) => {
@@ -29065,11 +30206,15 @@ function DocxEditorViewer({
29065
30206
  });
29066
30207
  estimatedPages = bestCandidate.pages;
29067
30208
  estimatedPagesUseMeasuredPageContentHeightsForRender = bestCandidate.useMeasuredPageContentHeightsForRender;
29068
- } else if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0) {
30209
+ estimatedRenderMeasuredPageContentHeightsPxByPageIndex = bestCandidate.renderMeasuredPageContentHeightsPxByPageIndex;
30210
+ estimatedRenderPageContentHeightScale = bestCandidate.renderPageContentHeightScale;
30211
+ } else if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && !hasMultiColumnRenderedPageBreakHints) {
29069
30212
  const pureEstimatedPages2 = buildEstimatedPages(void 0, null);
29070
30213
  if (Math.abs(pureEstimatedPages2.length - targetPageCount) < Math.abs(estimatedPages.length - targetPageCount)) {
29071
30214
  estimatedPages = pureEstimatedPages2;
29072
30215
  estimatedPagesUseMeasuredPageContentHeightsForRender = false;
30216
+ estimatedRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30217
+ estimatedRenderPageContentHeightScale = void 0;
29073
30218
  }
29074
30219
  }
29075
30220
  const measuredPageHeightOverridesReduceContent = !editor.canUndo && !editor.canRedo && !floatingMovePreview && !dropCapMovePreview && estimatedPages.some((segments, pageIndex) => {
@@ -29096,7 +30241,9 @@ function DocxEditorViewer({
29096
30241
  if (!Number.isFinite(storedDocumentPageCount2) || storedDocumentPageCount2 <= 0) {
29097
30242
  return {
29098
30243
  pages: estimatedPages,
29099
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30244
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30245
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30246
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
29100
30247
  };
29101
30248
  }
29102
30249
  const resolvedTargetPageCount = targetPageCount ?? minimumPageCount;
@@ -29106,22 +30253,26 @@ function DocxEditorViewer({
29106
30253
  )
29107
30254
  );
29108
30255
  const allowMeasuredReductionOverPaginationReconciliation = measuredPageHeightOverridesReduceContent && estimatedPages.length > resolvedTargetPageCount;
29109
- const allowStoredPageCountReconciliation = !editor.canUndo && !editor.canRedo && !hasPageAnchoredFloatingFooterContent && shouldAllowStoredPageCountReduction({
30256
+ const allowStoredPageCountReconciliation = !editor.canUndo && !editor.canRedo && !hasPageAnchoredFloatingFooterContent && !hasMultiColumnRenderedPageBreakHints && shouldAllowStoredPageCountReduction({
29110
30257
  estimatedPageCount: estimatedPages.length,
29111
30258
  targetPageCount: resolvedTargetPageCount,
29112
30259
  hasLastRenderedPageBreakHints,
29113
- renderedBreakHintPageCount
30260
+ renderedBreakHintPageCount,
30261
+ hasMeasuredBodyFooterOverlap
29114
30262
  }) && (!measuredPageHeightOverridesReduceContent || allowMeasuredReductionOverPaginationReconciliation);
29115
30263
  if (!allowStoredPageCountReconciliation) {
29116
30264
  return {
29117
30265
  pages: estimatedPages,
29118
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30266
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30267
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30268
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
29119
30269
  };
29120
30270
  }
29121
30271
  if (estimatedPages.length === resolvedTargetPageCount) {
29122
30272
  return {
29123
30273
  pages: estimatedPages,
29124
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30274
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30275
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex
29125
30276
  };
29126
30277
  }
29127
30278
  const reconciliationScales = allowMeasuredReductionOverPaginationReconciliation ? [
@@ -29141,7 +30292,7 @@ function DocxEditorViewer({
29141
30292
  1.28,
29142
30293
  1.3
29143
30294
  ] : void 0;
29144
- const reconcileCandidatePages = (initialPages, measuredTableRowHeightsByNodeIndex, measuredPageContentHeightsOverride) => reconcilePagesToTargetCountByScalingHeight({
30295
+ const reconcileCandidatePages = (initialPages, measuredTableRowHeightsByNodeIndex, measuredPageContentHeightsOverride) => reconcilePageCountCandidateToTargetCountByScalingHeight({
29145
30296
  initialPages,
29146
30297
  targetPageCount: resolvedTargetPageCount,
29147
30298
  maxDifference: hasTableInternalPageBreaks ? 2 : 3,
@@ -29167,27 +30318,38 @@ function DocxEditorViewer({
29167
30318
  }
29168
30319
  )
29169
30320
  });
29170
- let reconciledPages = reconcileCandidatePages(
30321
+ let reconciledCandidate = reconcileCandidatePages(
29171
30322
  estimatedPages,
29172
30323
  tableMeasuredRowHeightsForPagination,
29173
30324
  estimatedPagesUseMeasuredPageContentHeightsForRender ? measuredPageContentHeightByIndex : null
29174
30325
  );
30326
+ let reconciledPages = reconciledCandidate.pages;
29175
30327
  let reconciledPagesUseMeasuredPageContentHeightsForRender = estimatedPagesUseMeasuredPageContentHeightsForRender;
30328
+ let reconciledRenderMeasuredPageContentHeightsPxByPageIndex = reconciledPagesUseMeasuredPageContentHeightsForRender ? scaleMeasuredPageContentHeights(
30329
+ measuredPageContentHeightByIndex,
30330
+ reconciledCandidate.scale
30331
+ ) : void 0;
30332
+ let reconciledRenderPageContentHeightScale = reconciledPagesUseMeasuredPageContentHeightsForRender ? void 0 : reconciledCandidate.scale;
29176
30333
  if (!editor.canUndo && !editor.canRedo) {
29177
30334
  const pureEstimatedPages2 = buildEstimatedPages(void 0, null);
29178
- const pureReconciledPages = reconcileCandidatePages(
30335
+ const pureReconciledCandidate = reconcileCandidatePages(
29179
30336
  pureEstimatedPages2,
29180
30337
  void 0,
29181
30338
  null
29182
30339
  );
30340
+ const pureReconciledPages = pureReconciledCandidate.pages;
29183
30341
  if (Math.abs(pureReconciledPages.length - resolvedTargetPageCount) < Math.abs(reconciledPages.length - resolvedTargetPageCount)) {
29184
30342
  reconciledPages = pureReconciledPages;
29185
30343
  reconciledPagesUseMeasuredPageContentHeightsForRender = false;
30344
+ reconciledRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30345
+ reconciledRenderPageContentHeightScale = pureReconciledCandidate.scale;
29186
30346
  }
29187
30347
  }
29188
30348
  return {
29189
30349
  pages: reconciledPages,
29190
- useMeasuredPageContentHeightsForRender: reconciledPagesUseMeasuredPageContentHeightsForRender
30350
+ useMeasuredPageContentHeightsForRender: reconciledPagesUseMeasuredPageContentHeightsForRender,
30351
+ renderMeasuredPageContentHeightsPxByPageIndex: reconciledRenderMeasuredPageContentHeightsPxByPageIndex,
30352
+ renderPageContentHeightScale: reconciledRenderPageContentHeightScale
29191
30353
  };
29192
30354
  }, [
29193
30355
  editor.canRedo,
@@ -29206,12 +30368,17 @@ function DocxEditorViewer({
29206
30368
  isReadOnly,
29207
30369
  floatingMovePreview,
29208
30370
  dropCapMovePreview,
30371
+ deferInitialPaginationPaint,
29209
30372
  disableMeasuredImportPagination,
30373
+ hasMeasuredBodyFooterOverlap,
30374
+ initialPaginationBackgroundRefinementUnlocked,
29210
30375
  measuredPageContentHeightByIndex,
29211
30376
  tableMeasuredRowHeightsForPagination
29212
30377
  ]);
29213
30378
  const pageNodeSegmentsByPage = pageSegmentationPlan.pages;
29214
30379
  const useMeasuredPageContentHeightsForRender = pageSegmentationPlan.useMeasuredPageContentHeightsForRender;
30380
+ const renderMeasuredPageContentHeightsPxByPageIndex = pageSegmentationPlan.renderMeasuredPageContentHeightsPxByPageIndex;
30381
+ const renderPageContentHeightScale = pageSegmentationPlan.renderPageContentHeightScale;
29215
30382
  const pageNodeSegmentIdentityKeysByPage = React.useMemo(
29216
30383
  () => pageNodeSegmentsByPage.map(
29217
30384
  (pageSegments) => documentPageNodeSegmentsIdentityKey(pageSegments)
@@ -29427,6 +30594,32 @@ function DocxEditorViewer({
29427
30594
  };
29428
30595
  }, [editor.model.nodes, pageNodeSegmentsByPage]);
29429
30596
  const pageCount = pageNodeSegmentsByPage.length;
30597
+ const hasLargeTableLayoutSurface = React.useMemo(() => {
30598
+ let tableParagraphCount = 0;
30599
+ let tableCellCount = 0;
30600
+ let largestRowParagraphCount = 0;
30601
+ for (const node of editor.model.nodes) {
30602
+ if (node.type !== "table") {
30603
+ continue;
30604
+ }
30605
+ for (const row of node.rows) {
30606
+ let rowParagraphCount = 0;
30607
+ tableCellCount += row.cells.length;
30608
+ for (const cell of row.cells) {
30609
+ const paragraphCount = tableCellParagraphsRecursively(
30610
+ cell.nodes
30611
+ ).length;
30612
+ tableParagraphCount += paragraphCount;
30613
+ rowParagraphCount += paragraphCount;
30614
+ }
30615
+ largestRowParagraphCount = Math.max(
30616
+ largestRowParagraphCount,
30617
+ rowParagraphCount
30618
+ );
30619
+ }
30620
+ }
30621
+ return tableParagraphCount >= 1e3 || tableCellCount >= 240 || largestRowParagraphCount >= 100;
30622
+ }, [editor.model.nodes]);
29430
30623
  const hideDocumentUntilPaginationSettled = deferInitialPaginationPaint && !isInitialPaginationSettled;
29431
30624
  const estimateDocumentStackHeightPx = React.useCallback(
29432
30625
  (count) => {
@@ -29498,28 +30691,34 @@ function DocxEditorViewer({
29498
30691
  const hasExternalVisiblePageRange = Number.isFinite(Number(visiblePageRange?.startPageIndex)) || Number.isFinite(Number(visiblePageRange?.endPageIndex));
29499
30692
  const [deferInternalPageVirtualization, setDeferInternalPageVirtualization] = React.useState(false);
29500
30693
  const [internalVirtualScrollElement, setInternalVirtualScrollElement] = React.useState(null);
30694
+ const [observedVisiblePageRange, setObservedVisiblePageRange] = React.useState(void 0);
29501
30695
  const pageVirtualizationSettleDelayMs = Math.max(
29502
30696
  0,
29503
30697
  Math.round(
29504
30698
  Number.isFinite(pageVirtualization?.settleDelayMs) ? pageVirtualization?.settleDelayMs : DEFAULT_PAGE_VIRTUALIZATION_SETTLE_DELAY_MS
29505
30699
  )
29506
30700
  );
29507
- const pageVirtualizationOverscan = Math.max(
30701
+ const rawPageVirtualizationOverscan = Math.max(
29508
30702
  0,
29509
30703
  Math.round(
29510
30704
  Number.isFinite(pageVirtualization?.overscan) ? pageVirtualization?.overscan : DEFAULT_PAGE_VIRTUALIZATION_OVERSCAN
29511
30705
  )
29512
30706
  );
30707
+ const pageVirtualizationOverscan = hasLargeTableLayoutSurface && !Number.isFinite(pageVirtualization?.overscan) ? LARGE_TABLE_PAGE_VIRTUALIZATION_OVERSCAN : rawPageVirtualizationOverscan;
29513
30708
  const webdriverActive = typeof navigator !== "undefined" && navigator.webdriver === true;
29514
30709
  const internalPageVirtualizationRequested = pageVirtualization?.enabled !== false && !hasExternalVisiblePageRange && !hideDocumentUntilPaginationSettled && isInitialPaginationSettled && !deferInternalPageVirtualization && !webdriverActive && pageCount > 1;
29515
30710
  React.useEffect(() => {
29516
- setDeferInternalPageVirtualization(true);
29517
- }, [editor.documentLoadNonce]);
30711
+ setDeferInternalPageVirtualization(!hasLargeTableLayoutSurface);
30712
+ }, [editor.documentLoadNonce, hasLargeTableLayoutSurface]);
29518
30713
  React.useEffect(() => {
29519
30714
  if (typeof window === "undefined" || webdriverActive || pageCount <= 1) {
29520
30715
  setDeferInternalPageVirtualization(true);
29521
30716
  return;
29522
30717
  }
30718
+ if (hasLargeTableLayoutSurface) {
30719
+ setDeferInternalPageVirtualization(false);
30720
+ return;
30721
+ }
29523
30722
  const timeoutId = window.setTimeout(() => {
29524
30723
  setDeferInternalPageVirtualization(false);
29525
30724
  }, pageVirtualizationSettleDelayMs);
@@ -29528,6 +30727,7 @@ function DocxEditorViewer({
29528
30727
  };
29529
30728
  }, [
29530
30729
  editor.documentLoadNonce,
30730
+ hasLargeTableLayoutSurface,
29531
30731
  pageCount,
29532
30732
  pageVirtualizationSettleDelayMs,
29533
30733
  webdriverActive
@@ -29541,15 +30741,30 @@ function DocxEditorViewer({
29541
30741
  );
29542
30742
  }, [editor.documentLoadNonce, pageCount, trackedChangesEnabled]);
29543
30743
  const internalPageVirtualizationEnabled = internalPageVirtualizationRequested && internalVirtualScrollElement !== null;
29544
- const internalPageVirtualizer = (0, import_react_virtual.useVirtualizer)({
29545
- count: Math.max(1, pageCount),
29546
- getScrollElement: () => internalPageVirtualizationEnabled ? internalVirtualScrollElement : null,
29547
- estimateSize: (pageIndex) => {
30744
+ const internalPageVirtualizationPending = typeof window !== "undefined" && internalPageVirtualizationRequested && internalVirtualScrollElement === null;
30745
+ const internalVirtualScrollUsesWindow = typeof document !== "undefined" && internalVirtualScrollElement !== null && (internalVirtualScrollElement === document.scrollingElement || internalVirtualScrollElement === document.documentElement || internalVirtualScrollElement === document.body);
30746
+ const internalElementPageVirtualizationEnabled = internalPageVirtualizationEnabled && !internalVirtualScrollUsesWindow;
30747
+ const internalWindowPageVirtualizationEnabled = internalPageVirtualizationEnabled && internalVirtualScrollUsesWindow;
30748
+ const estimateVirtualPageSize = React.useCallback(
30749
+ (pageIndex) => {
29548
30750
  const pageLayout = pageSectionInfoByIndex[pageIndex]?.layout ?? documentLayout;
29549
30751
  return Math.max(1, pageLayout.pageHeightPx + DOC_PAGE_BREAK_GAP);
29550
30752
  },
30753
+ [documentLayout, pageSectionInfoByIndex]
30754
+ );
30755
+ const internalElementPageVirtualizer = (0, import_react_virtual.useVirtualizer)({
30756
+ count: Math.max(1, pageCount),
30757
+ getScrollElement: () => internalElementPageVirtualizationEnabled ? internalVirtualScrollElement : null,
30758
+ estimateSize: estimateVirtualPageSize,
30759
+ overscan: pageVirtualizationOverscan
30760
+ });
30761
+ const internalWindowPageVirtualizer = (0, import_react_virtual.useWindowVirtualizer)({
30762
+ count: Math.max(1, pageCount),
30763
+ getScrollElement: () => internalWindowPageVirtualizationEnabled && typeof window !== "undefined" ? window : null,
30764
+ estimateSize: estimateVirtualPageSize,
29551
30765
  overscan: pageVirtualizationOverscan
29552
30766
  });
30767
+ const internalPageVirtualizer = internalVirtualScrollUsesWindow ? internalWindowPageVirtualizer : internalElementPageVirtualizer;
29553
30768
  const internalVirtualItems = internalPageVirtualizer.getVirtualItems();
29554
30769
  const internalVisiblePageRange = React.useMemo(() => {
29555
30770
  if (!internalPageVirtualizationEnabled) {
@@ -29584,7 +30799,166 @@ function DocxEditorViewer({
29584
30799
  endPageIndex
29585
30800
  };
29586
30801
  }, [internalPageVirtualizationEnabled, internalVirtualItems, pageCount]);
29587
- const effectiveVisiblePageRange = visiblePageRange ?? internalVisiblePageRange;
30802
+ const internalRenderVisiblePageRange = React.useMemo(() => {
30803
+ if (!internalVisiblePageRange) {
30804
+ return void 0;
30805
+ }
30806
+ if (!hasLargeTableLayoutSurface || Number.isFinite(pageVirtualization?.overscan)) {
30807
+ return internalVisiblePageRange;
30808
+ }
30809
+ const scrollDirection = internalPageVirtualizer.scrollDirection;
30810
+ const renderPreviousPage = scrollDirection !== "backward";
30811
+ const renderNextPage = scrollDirection === "backward";
30812
+ const startPageIndex = clampNumber(
30813
+ internalVisiblePageRange.startPageIndex - (renderPreviousPage ? LARGE_TABLE_PAGE_ADJACENT_RENDER_COUNT : 0),
30814
+ 0,
30815
+ pageCount - 1
30816
+ );
30817
+ const endPageIndex = clampNumber(
30818
+ internalVisiblePageRange.endPageIndex + (renderNextPage ? LARGE_TABLE_PAGE_ADJACENT_RENDER_COUNT : 0),
30819
+ startPageIndex,
30820
+ pageCount - 1
30821
+ );
30822
+ return {
30823
+ startPageIndex,
30824
+ endPageIndex
30825
+ };
30826
+ }, [
30827
+ hasLargeTableLayoutSurface,
30828
+ internalPageVirtualizer.scrollDirection,
30829
+ internalVisiblePageRange,
30830
+ pageCount,
30831
+ pageVirtualization?.overscan
30832
+ ]);
30833
+ React.useLayoutEffect(() => {
30834
+ if (!internalPageVirtualizationEnabled || !internalVirtualScrollElement || internalVirtualItems.length > 0 || typeof window === "undefined") {
30835
+ setObservedVisiblePageRange(
30836
+ (current) => current === void 0 ? current : void 0
30837
+ );
30838
+ return;
30839
+ }
30840
+ const rootElement = viewerRootRef.current;
30841
+ if (!rootElement) {
30842
+ setObservedVisiblePageRange(
30843
+ (current) => current === void 0 ? current : void 0
30844
+ );
30845
+ return;
30846
+ }
30847
+ let frameId = null;
30848
+ const syncVisiblePageRange = () => {
30849
+ frameId = null;
30850
+ const viewportRect = internalVirtualScrollUsesWindow ? {
30851
+ top: 0,
30852
+ bottom: window.innerHeight
30853
+ } : internalVirtualScrollElement.getBoundingClientRect();
30854
+ const pageWrappers = rootElement.querySelectorAll(
30855
+ '[data-docx-page-wrapper="true"][data-index]'
30856
+ );
30857
+ let firstVisiblePageIndex;
30858
+ let lastVisiblePageIndex;
30859
+ for (const pageWrapper of pageWrappers) {
30860
+ const rawPageIndex = pageWrapper.getAttribute("data-index");
30861
+ const pageIndex = Number.parseInt(rawPageIndex ?? "", 10);
30862
+ if (!Number.isFinite(pageIndex)) {
30863
+ continue;
30864
+ }
30865
+ const pageRect = pageWrapper.getBoundingClientRect();
30866
+ if (pageRect.bottom <= viewportRect.top) {
30867
+ continue;
30868
+ }
30869
+ if (pageRect.top >= viewportRect.bottom) {
30870
+ if (firstVisiblePageIndex !== void 0) {
30871
+ break;
30872
+ }
30873
+ continue;
30874
+ }
30875
+ if (firstVisiblePageIndex === void 0) {
30876
+ firstVisiblePageIndex = pageIndex;
30877
+ }
30878
+ lastVisiblePageIndex = pageIndex;
30879
+ }
30880
+ if (firstVisiblePageIndex === void 0 || lastVisiblePageIndex === void 0) {
30881
+ setObservedVisiblePageRange(
30882
+ (current) => current === void 0 ? current : void 0
30883
+ );
30884
+ return;
30885
+ }
30886
+ const startPageIndex = clampNumber(
30887
+ firstVisiblePageIndex - pageVirtualizationOverscan,
30888
+ 0,
30889
+ pageCount - 1
30890
+ );
30891
+ const endPageIndex = clampNumber(
30892
+ lastVisiblePageIndex + pageVirtualizationOverscan,
30893
+ startPageIndex,
30894
+ pageCount - 1
30895
+ );
30896
+ setObservedVisiblePageRange((current) => {
30897
+ if (current?.startPageIndex === startPageIndex && current?.endPageIndex === endPageIndex) {
30898
+ return current;
30899
+ }
30900
+ return {
30901
+ startPageIndex,
30902
+ endPageIndex
30903
+ };
30904
+ });
30905
+ };
30906
+ const scheduleVisiblePageRangeSync = () => {
30907
+ if (frameId !== null) {
30908
+ return;
30909
+ }
30910
+ frameId = window.requestAnimationFrame(syncVisiblePageRange);
30911
+ };
30912
+ const resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(() => {
30913
+ scheduleVisiblePageRangeSync();
30914
+ }) : void 0;
30915
+ if (!internalVirtualScrollUsesWindow) {
30916
+ resizeObserver?.observe(internalVirtualScrollElement);
30917
+ }
30918
+ resizeObserver?.observe(rootElement);
30919
+ if (internalVirtualScrollUsesWindow) {
30920
+ window.addEventListener("scroll", scheduleVisiblePageRangeSync, {
30921
+ passive: true
30922
+ });
30923
+ } else {
30924
+ internalVirtualScrollElement.addEventListener(
30925
+ "scroll",
30926
+ scheduleVisiblePageRangeSync,
30927
+ { passive: true }
30928
+ );
30929
+ }
30930
+ window.addEventListener("resize", scheduleVisiblePageRangeSync);
30931
+ scheduleVisiblePageRangeSync();
30932
+ return () => {
30933
+ if (internalVirtualScrollUsesWindow) {
30934
+ window.removeEventListener("scroll", scheduleVisiblePageRangeSync);
30935
+ } else {
30936
+ internalVirtualScrollElement.removeEventListener(
30937
+ "scroll",
30938
+ scheduleVisiblePageRangeSync
30939
+ );
30940
+ }
30941
+ window.removeEventListener("resize", scheduleVisiblePageRangeSync);
30942
+ resizeObserver?.disconnect();
30943
+ if (frameId !== null) {
30944
+ window.cancelAnimationFrame(frameId);
30945
+ }
30946
+ };
30947
+ }, [
30948
+ internalPageVirtualizationEnabled,
30949
+ internalVirtualItems.length,
30950
+ internalVirtualScrollElement,
30951
+ internalVirtualScrollUsesWindow,
30952
+ pageCount,
30953
+ pageVirtualizationOverscan
30954
+ ]);
30955
+ const effectiveVisiblePageRange = visiblePageRange ?? internalRenderVisiblePageRange ?? observedVisiblePageRange ?? (internalPageVirtualizationPending ? {
30956
+ startPageIndex: 0,
30957
+ endPageIndex: Math.min(
30958
+ pageCount - 1,
30959
+ Math.max(0, pageVirtualizationOverscan)
30960
+ )
30961
+ } : void 0);
29588
30962
  const normalizedVisiblePageRange = React.useMemo(() => {
29589
30963
  if (pageCount <= 0) {
29590
30964
  return {
@@ -29612,7 +30986,8 @@ function DocxEditorViewer({
29612
30986
  pageCount
29613
30987
  ]);
29614
30988
  const initialPremeasureStartPageIndex = hasExternalVisiblePageRange ? normalizedVisiblePageRange.startPageIndex : 0;
29615
- const initialPremeasureEndPageIndex = hasExternalVisiblePageRange ? normalizedVisiblePageRange.endPageIndex : Math.min(pageCount - 1, INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT - 1);
30989
+ const initialPremeasurePageLimit = hasLargeTableLayoutSurface ? Math.min(2, INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT) : INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT;
30990
+ const initialPremeasureEndPageIndex = hasExternalVisiblePageRange ? normalizedVisiblePageRange.endPageIndex : Math.min(pageCount - 1, initialPremeasurePageLimit - 1);
29616
30991
  const measureAllPagesBeforeInitialReveal = hideDocumentUntilPaginationSettled && pageCount > 0 && initialPremeasureStartPageIndex === 0 && initialPremeasureEndPageIndex >= pageCount - 1;
29617
30992
  const visiblePageStartIndex = measureAllPagesBeforeInitialReveal ? 0 : hideDocumentUntilPaginationSettled ? initialPremeasureStartPageIndex : normalizedVisiblePageRange.startPageIndex;
29618
30993
  const visiblePageEndIndex = measureAllPagesBeforeInitialReveal ? pageCount - 1 : hideDocumentUntilPaginationSettled ? initialPremeasureEndPageIndex : normalizedVisiblePageRange.endPageIndex;
@@ -29626,20 +31001,64 @@ function DocxEditorViewer({
29626
31001
  }
29627
31002
  return indexes;
29628
31003
  }, [pageCount, visiblePageEndIndex, visiblePageStartIndex]);
31004
+ const visibleTableRowIndexesByNodeIndex = React.useMemo(() => {
31005
+ const rowsByNodeIndex = /* @__PURE__ */ new Map();
31006
+ const addRowIndex = (nodeIndex, rowIndex) => {
31007
+ const tableNode = editor.model.nodes[nodeIndex];
31008
+ if (!tableNode || tableNode.type !== "table" || rowIndex < 0 || rowIndex >= tableNode.rows.length) {
31009
+ return;
31010
+ }
31011
+ const existing = rowsByNodeIndex.get(nodeIndex);
31012
+ if (existing) {
31013
+ existing.add(rowIndex);
31014
+ } else {
31015
+ rowsByNodeIndex.set(nodeIndex, /* @__PURE__ */ new Set([rowIndex]));
31016
+ }
31017
+ };
31018
+ for (const pageIndex of visiblePageIndexes) {
31019
+ for (const segment of pageNodeSegmentsByPage[pageIndex] ?? []) {
31020
+ const tableNode = editor.model.nodes[segment.nodeIndex];
31021
+ if (!tableNode || tableNode.type !== "table") {
31022
+ continue;
31023
+ }
31024
+ if (segment.tableRowSlice) {
31025
+ addRowIndex(segment.nodeIndex, segment.tableRowSlice.rowIndex);
31026
+ continue;
31027
+ }
31028
+ if (segment.tableRowRange) {
31029
+ for (let rowIndex = segment.tableRowRange.startRowIndex; rowIndex < segment.tableRowRange.endRowIndex; rowIndex += 1) {
31030
+ addRowIndex(segment.nodeIndex, rowIndex);
31031
+ }
31032
+ continue;
31033
+ }
31034
+ for (let rowIndex = 0; rowIndex < tableNode.rows.length; rowIndex += 1) {
31035
+ addRowIndex(segment.nodeIndex, rowIndex);
31036
+ }
31037
+ }
31038
+ }
31039
+ return rowsByNodeIndex;
31040
+ }, [editor.model.nodes, pageNodeSegmentsByPage, visiblePageIndexes]);
29629
31041
  const paginationMeasurementEnabled = hideDocumentUntilPaginationSettled || postImportPaginationUnlocked;
29630
31042
  const visiblePagesHavePendingPaginationMeasurements = React.useMemo(() => {
29631
31043
  if (pageCount === 0) {
29632
31044
  return false;
29633
31045
  }
29634
31046
  for (const pageIndex of visiblePageIndexes) {
29635
- if (!Number.isFinite(measuredPageContentHeightByIndex[pageIndex])) {
31047
+ const pageSegments = pageNodeSegmentsByPage[pageIndex] ?? [];
31048
+ const pageContainsTableRowSlice = pageSegments.some(
31049
+ (segment) => Boolean(segment.tableRowSlice)
31050
+ );
31051
+ if (!Number.isFinite(measuredPageContentHeightByIndex[pageIndex]) && !(hasLargeTableLayoutSurface && pageContainsTableRowSlice)) {
29636
31052
  return true;
29637
31053
  }
29638
- for (const segment of pageNodeSegmentsByPage[pageIndex] ?? []) {
31054
+ for (const segment of pageSegments) {
29639
31055
  const tableNode = editor.model.nodes[segment.nodeIndex];
29640
31056
  if (!tableNode || tableNode.type !== "table") {
29641
31057
  continue;
29642
31058
  }
31059
+ if (segment.tableRowSlice) {
31060
+ continue;
31061
+ }
29643
31062
  const measuredHeights = tableMeasuredRowHeights[segment.nodeIndex];
29644
31063
  if (!measuredHeights || measuredHeights.length !== tableNode.rows.length) {
29645
31064
  return true;
@@ -29649,6 +31068,7 @@ function DocxEditorViewer({
29649
31068
  return false;
29650
31069
  }, [
29651
31070
  editor.model.nodes,
31071
+ hasLargeTableLayoutSurface,
29652
31072
  measuredPageContentHeightByIndex,
29653
31073
  pageCount,
29654
31074
  pageNodeSegmentsByPage,
@@ -29720,7 +31140,13 @@ function DocxEditorViewer({
29720
31140
  rootElement.querySelectorAll(
29721
31141
  '[data-docx-page-wrapper="true"][data-index]'
29722
31142
  )
29723
- );
31143
+ ).filter((element) => {
31144
+ const pageIndex = Number.parseInt(
31145
+ element.getAttribute("data-index") ?? "",
31146
+ 10
31147
+ );
31148
+ return Number.isFinite(pageIndex) && pageIndex >= visiblePageStartIndex && pageIndex <= visiblePageEndIndex;
31149
+ });
29724
31150
  const nextElements = new Set(pageWrappers);
29725
31151
  observedElements.forEach((element) => {
29726
31152
  if (!nextElements.has(element)) {
@@ -29756,7 +31182,9 @@ function DocxEditorViewer({
29756
31182
  internalPageVirtualizationEnabled,
29757
31183
  internalPageVirtualizer,
29758
31184
  internalVirtualScrollElement,
29759
- pageCount
31185
+ pageCount,
31186
+ visiblePageEndIndex,
31187
+ visiblePageStartIndex
29760
31188
  ]);
29761
31189
  React.useEffect(() => {
29762
31190
  if (!internalPageVirtualizationEnabled) {
@@ -30269,11 +31697,18 @@ function DocxEditorViewer({
30269
31697
  const nextMeasuredPageDiagnostics = pageNodeSegmentsByPage.map(
30270
31698
  (_, pageIndex) => {
30271
31699
  const pageLayout = pageSectionInfoByIndex[pageIndex]?.layout ?? documentLayout;
30272
- const pageElement = pageElementsRef.current.get(pageIndex);
30273
31700
  const fallbackHeightPx = Math.max(
30274
31701
  120,
30275
31702
  pageLayout.pageHeightPx - pageLayout.marginsPx.top - pageLayout.marginsPx.bottom
30276
31703
  );
31704
+ const pageIsVisible = pageIndex >= visiblePageStartIndex && pageIndex <= visiblePageEndIndex;
31705
+ if (!pageIsVisible) {
31706
+ return {
31707
+ heightPx: measuredPageContentHeightByIndex?.[pageIndex] ?? fallbackHeightPx,
31708
+ bodyOverrunsFooter: false
31709
+ };
31710
+ }
31711
+ const pageElement = pageElementsRef.current.get(pageIndex);
30277
31712
  if (!pageElement) {
30278
31713
  return {
30279
31714
  heightPx: fallbackHeightPx,
@@ -30285,7 +31720,9 @@ function DocxEditorViewer({
30285
31720
  const footerElement = pageFooterElementsRef.current.get(pageIndex);
30286
31721
  const headerHeightPx = headerElement ? Math.max(
30287
31722
  0,
30288
- Math.round(headerElement.getBoundingClientRect().height / zoomScale)
31723
+ Math.round(
31724
+ headerElement.getBoundingClientRect().height / zoomScale
31725
+ )
30289
31726
  ) : 0;
30290
31727
  const docxFooterTopPx = resolveFooterNodesFloatingBoundaryTopPx(
30291
31728
  pageHeaderAndFooterNodes[pageIndex]?.footerNodes ?? [],
@@ -30351,7 +31788,9 @@ function DocxEditorViewer({
30351
31788
  bottomPx: rect.bottom,
30352
31789
  widthPx: rect.width,
30353
31790
  heightPx: rect.height,
30354
- ignore: !element.isConnected || Boolean(element.closest("[data-docx-image-location]")) || Boolean(
31791
+ ignore: !element.isConnected || Boolean(
31792
+ element.closest("[data-docx-image-location]")
31793
+ ) || Boolean(
30355
31794
  element.closest(
30356
31795
  `[${PAGE_CONTENT_MEASUREMENT_IGNORE_ATTRIBUTE}="true"]`
30357
31796
  )
@@ -30381,7 +31820,31 @@ function DocxEditorViewer({
30381
31820
  const nextMeasuredHeights = nextMeasuredPageDiagnostics.map(
30382
31821
  (diagnostics) => diagnostics.heightPx
30383
31822
  );
31823
+ const overlappingPageIndexes = nextMeasuredPageDiagnostics.reduce(
31824
+ (indexes, diagnostics, pageIndex) => {
31825
+ if (diagnostics.bodyOverrunsFooter) {
31826
+ indexes.push(pageIndex);
31827
+ }
31828
+ return indexes;
31829
+ },
31830
+ []
31831
+ );
31832
+ const nextMeasuredBodyFooterOverlapLatchState = resolveMeasuredBodyFooterOverlapLatchState({
31833
+ pageCount,
31834
+ targetPageCount: editor.model.metadata.documentPageCount,
31835
+ overlappingPageIndexes,
31836
+ previousSignature: measuredBodyFooterOverlapCandidateRef.current.signature,
31837
+ previousConsecutivePasses: measuredBodyFooterOverlapCandidateRef.current.consecutivePasses,
31838
+ stabilityThreshold: MEASURED_BODY_FOOTER_OVERLAP_STABILITY_THRESHOLD
31839
+ });
31840
+ measuredBodyFooterOverlapCandidateRef.current = {
31841
+ signature: nextMeasuredBodyFooterOverlapLatchState.signature,
31842
+ consecutivePasses: nextMeasuredBodyFooterOverlapLatchState.consecutivePasses
31843
+ };
30384
31844
  const frameId = window.requestAnimationFrame(() => {
31845
+ if (nextMeasuredBodyFooterOverlapLatchState.shouldLatch) {
31846
+ setHasMeasuredBodyFooterOverlap(true);
31847
+ }
30385
31848
  setMeasuredPageContentHeightByIndex((current) => {
30386
31849
  const stabilizedHeights = stabilizeMeasuredPageContentHeights(
30387
31850
  current,
@@ -30434,10 +31897,13 @@ function DocxEditorViewer({
30434
31897
  paginationMeasurementEnabled,
30435
31898
  paginationMeasurementEpoch,
30436
31899
  pageCount,
31900
+ editor.model.metadata.documentPageCount,
30437
31901
  pageNodeSegmentsByPage,
30438
31902
  pageNodeSegmentIdentityKeysByPage,
30439
31903
  pageSectionInfoByIndex,
30440
- pageHeaderAndFooterNodes
31904
+ pageHeaderAndFooterNodes,
31905
+ visiblePageEndIndex,
31906
+ visiblePageStartIndex
30441
31907
  ]);
30442
31908
  React.useEffect(() => {
30443
31909
  if (!deferInitialPaginationPaint || isInitialPaginationSettled || disableMeasuredImportPagination) {
@@ -30466,6 +31932,27 @@ function DocxEditorViewer({
30466
31932
  isInitialPaginationSettled,
30467
31933
  pageCount
30468
31934
  ]);
31935
+ React.useEffect(() => {
31936
+ if (!deferInitialPaginationPaint || !isInitialPaginationSettled || initialPaginationBackgroundRefinementUnlocked) {
31937
+ return;
31938
+ }
31939
+ if (typeof window === "undefined") {
31940
+ setInitialPaginationBackgroundRefinementUnlocked(true);
31941
+ return;
31942
+ }
31943
+ const timeoutId = window.setTimeout(() => {
31944
+ React.startTransition(() => {
31945
+ setInitialPaginationBackgroundRefinementUnlocked(true);
31946
+ });
31947
+ }, INITIAL_PAGINATION_BACKGROUND_REFINEMENT_DELAY_MS);
31948
+ return () => {
31949
+ window.clearTimeout(timeoutId);
31950
+ };
31951
+ }, [
31952
+ deferInitialPaginationPaint,
31953
+ initialPaginationBackgroundRefinementUnlocked,
31954
+ isInitialPaginationSettled
31955
+ ]);
30469
31956
  React.useEffect(() => {
30470
31957
  if (!deferInitialPaginationPaint || isInitialPaginationSettled) {
30471
31958
  return;
@@ -34684,10 +36171,14 @@ function DocxEditorViewer({
34684
36171
  if (node.type !== "table") {
34685
36172
  return;
34686
36173
  }
36174
+ const visibleRowIndexes = visibleTableRowIndexesByNodeIndex.get(nodeIndex);
36175
+ if (!visibleRowIndexes || visibleRowIndexes.size === 0) {
36176
+ return;
36177
+ }
34687
36178
  const measuredByRowIndex = /* @__PURE__ */ new Map();
34688
36179
  const recordMeasuredRow = (rowIndex, rowHeightPx) => {
34689
36180
  const normalizedRowIndex = Math.max(0, Math.round(rowIndex));
34690
- if (normalizedRowIndex >= node.rows.length) {
36181
+ if (normalizedRowIndex >= node.rows.length || !visibleRowIndexes.has(normalizedRowIndex)) {
34691
36182
  return;
34692
36183
  }
34693
36184
  const normalizedHeight = normalizeMeasuredTableRowHeightPx(rowHeightPx);
@@ -34720,7 +36211,8 @@ function DocxEditorViewer({
34720
36211
  );
34721
36212
  });
34722
36213
  }
34723
- const rowCells = document.querySelectorAll(
36214
+ const measurementRoot = viewerRootRef.current ?? document;
36215
+ const rowCells = measurementRoot.querySelectorAll(
34724
36216
  `[data-docx-table-cell='true'][data-docx-table-index='${nodeIndex}'][data-docx-row-index]`
34725
36217
  );
34726
36218
  rowCells.forEach((cellElement) => {
@@ -34751,7 +36243,8 @@ function DocxEditorViewer({
34751
36243
  node,
34752
36244
  pageContentWidthPxByNodeIndex.get(nodeIndex),
34753
36245
  editor.model.metadata.numberingDefinitions,
34754
- docGridLinePitchPxByNodeIndex.get(nodeIndex)
36246
+ docGridLinePitchPxByNodeIndex.get(nodeIndex),
36247
+ pageContentHeightPxByNodeIndex.get(nodeIndex)
34755
36248
  );
34756
36249
  const previousMeasuredRowHeights = tableMeasuredRowHeights[nodeIndex];
34757
36250
  const measuredHeights = node.rows.map((_, rowIndex) => {
@@ -34817,8 +36310,7 @@ function DocxEditorViewer({
34817
36310
  tableColumnWidths,
34818
36311
  tableRowHeights,
34819
36312
  tableDraftLayoutEpoch,
34820
- visiblePageEndIndex,
34821
- visiblePageStartIndex
36313
+ visibleTableRowIndexesByNodeIndex
34822
36314
  ]);
34823
36315
  const normalizeResizableHeights = React.useCallback(
34824
36316
  (rowHeights) => {
@@ -36278,6 +37770,29 @@ function DocxEditorViewer({
36278
37770
  `${keyPrefix}-fragment-image-${lineIndex}-${run.key}-${overlapStart}`
36279
37771
  );
36280
37772
  }
37773
+ if (run.kind === "tab" && Number.isFinite(run.tabWidthPx)) {
37774
+ const overlapRatio = run.endOffset > run.startOffset ? (overlapEnd - overlapStart) / (run.endOffset - run.startOffset) : 1;
37775
+ const tabWidthPx = Math.max(
37776
+ 1,
37777
+ Math.round(run.tabWidthPx * overlapRatio)
37778
+ );
37779
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
37780
+ "span",
37781
+ {
37782
+ "data-docx-tab-char": "true",
37783
+ style: {
37784
+ ...runStyleToCss(run.style, documentContentTheme),
37785
+ display: "inline-block",
37786
+ width: tabWidthPx,
37787
+ minWidth: tabWidthPx,
37788
+ whiteSpace: "pre",
37789
+ lineHeight: "1em"
37790
+ },
37791
+ children: "\xA0"
37792
+ },
37793
+ `${keyPrefix}-fragment-tab-${lineIndex}-${run.key}-${overlapStart}`
37794
+ );
37795
+ }
36281
37796
  const slice = run.text.slice(
36282
37797
  overlapStart - run.startOffset,
36283
37798
  overlapEnd - run.startOffset
@@ -39113,6 +40628,488 @@ function DocxEditorViewer({
39113
40628
  boxSizing: "border-box",
39114
40629
  overflow: floatingMovePreview || dropCapMovePreview ? "visible" : "clip"
39115
40630
  };
40631
+ const tableCellParagraphSliceLayoutCacheRef = React.useRef(
40632
+ /* @__PURE__ */ new Map()
40633
+ );
40634
+ const tableCellParagraphFlowLayoutCacheRef = React.useRef(
40635
+ /* @__PURE__ */ new Map()
40636
+ );
40637
+ const tableCellParagraphSlicePlanCacheRef = React.useRef(
40638
+ /* @__PURE__ */ new Map()
40639
+ );
40640
+ const tableCellParagraphSliceSignatureCacheRef = React.useRef(
40641
+ /* @__PURE__ */ new WeakMap()
40642
+ );
40643
+ React.useEffect(() => {
40644
+ tableCellParagraphSliceLayoutCacheRef.current.clear();
40645
+ tableCellParagraphFlowLayoutCacheRef.current.clear();
40646
+ tableCellParagraphSlicePlanCacheRef.current.clear();
40647
+ tableCellParagraphSliceSignatureCacheRef.current = /* @__PURE__ */ new WeakMap();
40648
+ }, [paragraphStructureEpoch]);
40649
+ const resolveTableCellParagraphSliceSignature = (cell) => {
40650
+ const cellKey = cell;
40651
+ const cached = tableCellParagraphSliceSignatureCacheRef.current.get(cellKey);
40652
+ if (cached) {
40653
+ return cached;
40654
+ }
40655
+ const signature = [
40656
+ JSON.stringify(cell.style ?? null),
40657
+ ...cell.nodes.map(
40658
+ (paragraph, paragraphIndex) => isParagraphCellContentNode(paragraph) ? `${paragraphIndex}:${paragraph.sourceXml ?? paragraphText(paragraph)}` : `${paragraphIndex}:${paragraph.type}`
40659
+ )
40660
+ ].join("");
40661
+ tableCellParagraphSliceSignatureCacheRef.current.set(cellKey, signature);
40662
+ return signature;
40663
+ };
40664
+ const resolveTableCellParagraphSlicePlans = (params) => {
40665
+ const {
40666
+ cell,
40667
+ rowHeightPx,
40668
+ sliceStartPx,
40669
+ sliceHeightPx,
40670
+ cellContentWidthPx,
40671
+ tableCellMarginTwips,
40672
+ applyWordTableDefaults,
40673
+ docGridLinePitchPx
40674
+ } = params;
40675
+ if (!cell.nodes.every(isParagraphCellContentNode)) {
40676
+ return void 0;
40677
+ }
40678
+ const numberingDefinitions = editor.model.metadata.numberingDefinitions;
40679
+ const cellSignature = resolveTableCellParagraphSliceSignature(cell);
40680
+ const flowLayoutCacheKey = [
40681
+ cellContentWidthPx,
40682
+ JSON.stringify(tableCellMarginTwips ?? null),
40683
+ applyWordTableDefaults ? 1 : 0,
40684
+ docGridLinePitchPx ?? 0,
40685
+ cellSignature
40686
+ ].join(":");
40687
+ let flowLayout = tableCellParagraphFlowLayoutCacheRef.current.get(flowLayoutCacheKey);
40688
+ if (!flowLayout) {
40689
+ const contentHeightPx = estimateTableCellContentHeightPx(
40690
+ cell.nodes,
40691
+ cellContentWidthPx,
40692
+ numberingDefinitions,
40693
+ applyWordTableDefaults,
40694
+ docGridLinePitchPx
40695
+ );
40696
+ const paddingPx = resolveTableSpacingPaddingPx(
40697
+ mergeTableSpacing(tableCellMarginTwips, cell.style?.marginTwips)
40698
+ );
40699
+ let paragraphTopPx = paddingPx.top;
40700
+ const entries = [];
40701
+ for (let paragraphIndex = 0; paragraphIndex < cell.nodes.length; paragraphIndex += 1) {
40702
+ const paragraph = cell.nodes[paragraphIndex];
40703
+ if (!paragraph) {
40704
+ continue;
40705
+ }
40706
+ const disableDocGridSnap = paragraphDocGridSnapState(paragraph) === "disable";
40707
+ const layoutCacheKey2 = `${cellContentWidthPx}:${applyWordTableDefaults ? 1 : 0}:${docGridLinePitchPx ?? 0}:${paragraphIndex}:${paragraph.sourceXml ?? paragraphText(paragraph)}`;
40708
+ let layoutEntry = tableCellParagraphSliceLayoutCacheRef.current.get(layoutCacheKey2);
40709
+ if (!layoutEntry) {
40710
+ const paragraphForLayout = wordLikeTableCellParagraph(
40711
+ paragraph,
40712
+ applyWordTableDefaults
40713
+ );
40714
+ const paragraphHeightPx2 = estimateParagraphHeightPx(
40715
+ paragraphForLayout,
40716
+ cellContentWidthPx,
40717
+ numberingDefinitions,
40718
+ docGridLinePitchPx,
40719
+ disableDocGridSnap
40720
+ );
40721
+ const suppressTopSpacing = paragraphIndex === 0 && suppressFirstTableCellParagraphTopSpacing(paragraph);
40722
+ const beforeSpacingPx = suppressTopSpacing ? 0 : twipsToPixels(paragraphForLayout.style?.spacing?.beforeTwips) ?? 0;
40723
+ const topBorderInsetPx = paragraphBorderInsetPx(
40724
+ paragraphForLayout.style?.borders?.top
40725
+ );
40726
+ const lineHeightPx = Math.max(
40727
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
40728
+ estimateParagraphLineHeightPx(
40729
+ paragraphForLayout,
40730
+ docGridLinePitchPx,
40731
+ disableDocGridSnap
40732
+ )
40733
+ );
40734
+ const pretextSource = buildParagraphPretextLayoutSource(
40735
+ paragraphForLayout,
40736
+ {
40737
+ allowExplicitLineBreakText: true,
40738
+ expandTabsForLayout: true
40739
+ }
40740
+ );
40741
+ const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
40742
+ paragraphForLayout,
40743
+ cellContentWidthPx,
40744
+ numberingDefinitions
40745
+ );
40746
+ const pretextLayout = pretextSource ? layoutParagraphPretextSource(
40747
+ paragraphForLayout,
40748
+ pretextSource,
40749
+ paragraphTextWidthPx,
40750
+ lineHeightPx,
40751
+ []
40752
+ ) : void 0;
40753
+ const totalLineCount = Math.max(
40754
+ 1,
40755
+ pretextLayout?.lineCount ?? paragraphLineCountWithinWidth(
40756
+ paragraphForLayout,
40757
+ cellContentWidthPx,
40758
+ numberingDefinitions
40759
+ )
40760
+ );
40761
+ layoutEntry = {
40762
+ paragraphForLayout,
40763
+ paragraphHeightPx: paragraphHeightPx2,
40764
+ textTopOffsetPx: beforeSpacingPx + topBorderInsetPx,
40765
+ lineHeightPx,
40766
+ lineTopOffsetsPx: pretextLayout ? pretextLayout.lines.map(
40767
+ (line) => Math.max(0, Math.round(line.y))
40768
+ ) : Array.from(
40769
+ { length: totalLineCount },
40770
+ (_, lineIndex) => lineIndex * lineHeightPx
40771
+ ),
40772
+ pretextSource: pretextSource ?? void 0,
40773
+ pretextLayout: pretextLayout ?? void 0
40774
+ };
40775
+ tableCellParagraphSliceLayoutCacheRef.current.set(
40776
+ layoutCacheKey2,
40777
+ layoutEntry
40778
+ );
40779
+ }
40780
+ const paragraphHeightPx = layoutEntry.paragraphHeightPx;
40781
+ const textTopPx = paragraphTopPx + layoutEntry.textTopOffsetPx;
40782
+ const textBottomPx = textTopPx + (layoutEntry.pretextLayout ? wrappedPretextParagraphBlockHeightPx(layoutEntry.pretextLayout) : layoutEntry.lineHeightPx * layoutEntry.lineTopOffsetsPx.length);
40783
+ const paragraphBottomPx = resolveTableCellParagraphVisualBottomPx({
40784
+ paragraphTopPx,
40785
+ paragraphHeightPx,
40786
+ textBottomPx
40787
+ });
40788
+ entries.push({
40789
+ paragraph,
40790
+ paragraphIndex,
40791
+ paragraphTopPx,
40792
+ textTopPx,
40793
+ paragraphBottomPx,
40794
+ layoutEntry
40795
+ });
40796
+ paragraphTopPx = paragraphBottomPx;
40797
+ }
40798
+ flowLayout = {
40799
+ contentHeightPx,
40800
+ paddingPx,
40801
+ entries
40802
+ };
40803
+ tableCellParagraphFlowLayoutCacheRef.current.set(
40804
+ flowLayoutCacheKey,
40805
+ flowLayout
40806
+ );
40807
+ }
40808
+ const availableContentHeightPx = Math.max(
40809
+ 0,
40810
+ rowHeightPx - flowLayout.paddingPx.top - flowLayout.paddingPx.bottom
40811
+ );
40812
+ const extraVerticalSpacePx = Math.max(
40813
+ 0,
40814
+ availableContentHeightPx - flowLayout.contentHeightPx
40815
+ );
40816
+ const verticalOffsetPx = cell.style?.verticalAlign === "center" ? Math.round(extraVerticalSpacePx / 2) : cell.style?.verticalAlign === "bottom" ? extraVerticalSpacePx : 0;
40817
+ const sliceBottomPx = sliceStartPx + sliceHeightPx;
40818
+ const slicePlanCacheKey = [
40819
+ flowLayoutCacheKey,
40820
+ rowHeightPx,
40821
+ sliceStartPx,
40822
+ sliceHeightPx
40823
+ ].join(":");
40824
+ const cachedPlans = tableCellParagraphSlicePlanCacheRef.current.get(slicePlanCacheKey);
40825
+ if (cachedPlans) {
40826
+ return cachedPlans;
40827
+ }
40828
+ const plans = [];
40829
+ let firstCandidateIndex = 0;
40830
+ let low = 0;
40831
+ let high = flowLayout.entries.length;
40832
+ while (low < high) {
40833
+ const mid = Math.floor((low + high) / 2);
40834
+ const entryBottomPx = (flowLayout.entries[mid]?.paragraphBottomPx ?? 0) + verticalOffsetPx;
40835
+ if (entryBottomPx <= sliceStartPx + PAGE_OVERFLOW_TOLERANCE_PX) {
40836
+ low = mid + 1;
40837
+ } else {
40838
+ high = mid;
40839
+ }
40840
+ }
40841
+ firstCandidateIndex = low;
40842
+ for (let entryIndex = firstCandidateIndex; entryIndex < flowLayout.entries.length; entryIndex += 1) {
40843
+ const entry = flowLayout.entries[entryIndex];
40844
+ if (!entry) {
40845
+ continue;
40846
+ }
40847
+ const paragraphTopPx = entry.paragraphTopPx + verticalOffsetPx;
40848
+ const textTopPx = entry.textTopPx + verticalOffsetPx;
40849
+ const paragraphBottomPx = entry.paragraphBottomPx + verticalOffsetPx;
40850
+ if (paragraphTopPx >= sliceBottomPx - PAGE_OVERFLOW_TOLERANCE_PX) {
40851
+ break;
40852
+ }
40853
+ const intersectsParagraph = sliceBottomPx > paragraphTopPx + PAGE_OVERFLOW_TOLERANCE_PX && sliceStartPx < paragraphBottomPx - PAGE_OVERFLOW_TOLERANCE_PX;
40854
+ if (!intersectsParagraph) {
40855
+ continue;
40856
+ }
40857
+ const fullyVisible = tableCellParagraphFitsFullyWithinSlice({
40858
+ sliceStartPx,
40859
+ sliceBottomPx,
40860
+ paragraphTopPx,
40861
+ paragraphBottomPx
40862
+ });
40863
+ if (fullyVisible) {
40864
+ plans.push({
40865
+ paragraph: entry.paragraph,
40866
+ paragraphIndex: entry.paragraphIndex,
40867
+ topPx: Math.max(0, Math.round(paragraphTopPx - sliceStartPx)),
40868
+ layoutEntry: entry.layoutEntry
40869
+ });
40870
+ continue;
40871
+ }
40872
+ const paragraphLineRange = resolveLineRangeWithinVerticalSlice(
40873
+ entry.layoutEntry.lineTopOffsetsPx,
40874
+ entry.layoutEntry.lineHeightPx,
40875
+ sliceStartPx - textTopPx,
40876
+ sliceBottomPx - textTopPx
40877
+ );
40878
+ if (!paragraphLineRange) {
40879
+ continue;
40880
+ }
40881
+ const lineRangeTopPx = paragraphLineRange.startLineIndex > 0 ? textTopPx + entry.layoutEntry.lineTopOffsetsPx[paragraphLineRange.startLineIndex] : paragraphTopPx;
40882
+ plans.push({
40883
+ paragraph: entry.paragraph,
40884
+ paragraphIndex: entry.paragraphIndex,
40885
+ topPx: Math.max(0, Math.round(lineRangeTopPx - sliceStartPx)),
40886
+ layoutEntry: entry.layoutEntry,
40887
+ paragraphLineRange
40888
+ });
40889
+ }
40890
+ tableCellParagraphSlicePlanCacheRef.current.set(slicePlanCacheKey, plans);
40891
+ return plans;
40892
+ };
40893
+ const renderSlicedTableCellParagraph = (params) => {
40894
+ const {
40895
+ paragraph,
40896
+ paragraphIndex,
40897
+ tableIndex,
40898
+ rowIndex,
40899
+ cellIndex,
40900
+ contentIndex,
40901
+ cellContentWidthPx,
40902
+ applyWordTableDefaults,
40903
+ docGridLinePitchPx,
40904
+ layoutEntry,
40905
+ paragraphLineRange
40906
+ } = params;
40907
+ const numberingDefinitions = editor.model.metadata.numberingDefinitions;
40908
+ const paragraphForLayout = layoutEntry.paragraphForLayout;
40909
+ const hasPartialLineRange = paragraphSegmentHasPartialLineRange(paragraphLineRange);
40910
+ const paragraphSegmentLineHeightPx = Math.max(
40911
+ 1,
40912
+ paragraphLineRange?.lineHeightPx ?? layoutEntry.lineHeightPx
40913
+ );
40914
+ const paragraphSegmentStartLine = paragraphLineRange?.startLineIndex ?? 0;
40915
+ const paragraphSegmentEndLine = paragraphLineRange?.endLineIndex ?? paragraphLineRange?.totalLineCount ?? 1;
40916
+ const paragraphSegmentTotalLines = paragraphLineRange?.totalLineCount ?? Math.max(1, paragraphSegmentEndLine);
40917
+ const paragraphSegmentVisibleLineCount = Math.max(
40918
+ 1,
40919
+ paragraphSegmentEndLine - paragraphSegmentStartLine
40920
+ );
40921
+ const paragraphSegmentVisibleHeightPx = paragraphSegmentVisibleLineCount * paragraphSegmentLineHeightPx;
40922
+ const paragraphSegmentTranslateYPx = paragraphSegmentStartLine * paragraphSegmentLineHeightPx;
40923
+ const location = {
40924
+ kind: "table-cell",
40925
+ tableIndex,
40926
+ rowIndex,
40927
+ cellIndex,
40928
+ paragraphIndex
40929
+ };
40930
+ const numberingLabel = paragraphNumberingLabels.get(
40931
+ paragraphLocationKey(location)
40932
+ );
40933
+ const paragraphRenderTextWidthPx = paragraphAvailableTextWidthPx(
40934
+ paragraphForLayout,
40935
+ cellContentWidthPx,
40936
+ numberingDefinitions
40937
+ );
40938
+ const pretextParagraphLayout = hasPartialLineRange && layoutEntry.pretextSource ? layoutEntry.pretextLayout && Math.abs(paragraphSegmentLineHeightPx - layoutEntry.lineHeightPx) <= 1 ? layoutEntry.pretextLayout : layoutParagraphPretextSource(
40939
+ paragraphForLayout,
40940
+ layoutEntry.pretextSource,
40941
+ paragraphRenderTextWidthPx,
40942
+ paragraphSegmentLineHeightPx,
40943
+ []
40944
+ ) : void 0;
40945
+ const pretextParagraphTotalLines = Math.max(
40946
+ 0,
40947
+ pretextParagraphLayout?.lineCount ?? 0
40948
+ );
40949
+ const pretextParagraphSliceStartLine = hasPartialLineRange && paragraphLineRange && pretextParagraphTotalLines > 0 ? Math.max(
40950
+ 0,
40951
+ Math.min(
40952
+ paragraphLineRange.startLineIndex,
40953
+ pretextParagraphTotalLines
40954
+ )
40955
+ ) : void 0;
40956
+ const pretextParagraphSliceEndLine = hasPartialLineRange && paragraphLineRange && pretextParagraphTotalLines > 0 && pretextParagraphSliceStartLine !== void 0 ? Math.max(
40957
+ pretextParagraphSliceStartLine,
40958
+ Math.min(
40959
+ paragraphLineRange.endLineIndex,
40960
+ pretextParagraphTotalLines
40961
+ )
40962
+ ) : void 0;
40963
+ const pretextParagraphSliceLayout = hasPartialLineRange && pretextParagraphLayout && pretextParagraphSliceStartLine !== void 0 && pretextParagraphSliceEndLine !== void 0 && pretextParagraphLayout.lineCount > 0 ? sliceLayoutToLineRange(
40964
+ pretextParagraphLayout,
40965
+ pretextParagraphSliceStartLine,
40966
+ pretextParagraphSliceEndLine
40967
+ ) : void 0;
40968
+ const shouldRenderParagraphSegmentWithPretext = hasPartialLineRange && Boolean(layoutEntry.pretextSource) && Boolean(pretextParagraphLayout) && pretextParagraphTotalLines > 0;
40969
+ const paragraphSegmentClipBleed = shouldRenderParagraphSegmentWithPretext ? resolveParagraphSegmentClipBleedPx(paragraphLineRange) : resolveFallbackParagraphSegmentClipBleedPx(
40970
+ paragraphForLayout,
40971
+ paragraphLineRange
40972
+ );
40973
+ const paragraphSegmentClipBleedTopPx = paragraphSegmentClipBleed.topPx;
40974
+ const paragraphSegmentClipBleedBottomPx = paragraphSegmentClipBleed.bottomPx;
40975
+ const pretextSegmentNumberingMarkerBoxWidthPx = numberingLabel && paragraphSegmentStartLine === 0 ? resolveNumberingMarkerBoxWidthPx(
40976
+ paragraph,
40977
+ numberingDefinitions,
40978
+ numberingLabel
40979
+ ) ?? Math.max(
40980
+ 16,
40981
+ Math.ceil(
40982
+ measureTextWidthPx2(
40983
+ numberingLabel.imageSrc ? numberingLabel.trailingText ?? "" : numberingLabel.text ?? "",
40984
+ numberingLabel.style,
40985
+ paragraphBaseFontSizePx(paragraph)
40986
+ )
40987
+ ) + (numberingLabel.imageSrc ? Math.ceil(numberingLabel.imageWidthPx ?? 12) + 2 : 0) + 4
40988
+ ) : void 0;
40989
+ const pretextSegmentNumberingMarkerNode = shouldRenderParagraphSegmentWithPretext && numberingLabel && paragraphSegmentStartLine === 0 && Number.isFinite(pretextSegmentNumberingMarkerBoxWidthPx) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
40990
+ "span",
40991
+ {
40992
+ contentEditable: false,
40993
+ "data-docx-numbering-label": "true",
40994
+ style: {
40995
+ ...numberingMarkerStyle(
40996
+ paragraph,
40997
+ numberingDefinitions,
40998
+ numberingLabel,
40999
+ numberingLabel.style ? runStyleToCss(numberingLabel.style, documentContentTheme) : void 0,
41000
+ documentContentTheme
41001
+ ),
41002
+ position: "absolute",
41003
+ left: -Math.round(
41004
+ pretextSegmentNumberingMarkerBoxWidthPx
41005
+ ),
41006
+ top: 0,
41007
+ marginRight: 0,
41008
+ zIndex: 1,
41009
+ pointerEvents: "none"
41010
+ },
41011
+ children: numberingLabel.imageSrc ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
41012
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41013
+ "img",
41014
+ {
41015
+ src: numberingLabel.imageSrc,
41016
+ alt: "",
41017
+ "aria-hidden": "true",
41018
+ draggable: false,
41019
+ style: {
41020
+ display: "inline-block",
41021
+ verticalAlign: "text-bottom",
41022
+ width: numberingLabel.imageWidthPx ?? 12,
41023
+ height: numberingLabel.imageHeightPx ?? 12,
41024
+ marginRight: 2,
41025
+ filter: documentContentFilter
41026
+ }
41027
+ }
41028
+ ),
41029
+ numberingLabel.trailingText ?? ""
41030
+ ] }) : numberingLabel.text ?? ""
41031
+ },
41032
+ `table-cell-${tableIndex}-${rowIndex}-${cellIndex}-${paragraphIndex}-numbering-marker-${paragraphSegmentStartLine}`
41033
+ ) : void 0;
41034
+ const baseParagraphStyle = tableCellParagraphBlockStyle(
41035
+ paragraph,
41036
+ numberingDefinitions,
41037
+ headingStyles,
41038
+ paragraphIndex,
41039
+ applyWordTableDefaults,
41040
+ docGridLinePitchPx
41041
+ );
41042
+ const paragraphStyle = {
41043
+ ...baseParagraphStyle,
41044
+ ...hasPartialLineRange ? {
41045
+ marginTop: paragraphSegmentStartLine === 0 ? baseParagraphStyle.marginTop : 0,
41046
+ marginBottom: paragraphSegmentEndLine >= paragraphSegmentTotalLines ? baseParagraphStyle.marginBottom : 0
41047
+ } : void 0,
41048
+ outline: "none"
41049
+ };
41050
+ const fallbackParagraphRuns = renderInteractiveParagraphRuns(
41051
+ paragraph,
41052
+ `body-cell-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
41053
+ location
41054
+ );
41055
+ const renderedInteractiveParagraphContent = shouldRenderParagraphSegmentWithPretext ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41056
+ "div",
41057
+ {
41058
+ style: {
41059
+ minHeight: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
41060
+ marginTop: -paragraphSegmentClipBleedTopPx,
41061
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
41062
+ paddingTop: paragraphSegmentClipBleedTopPx,
41063
+ paddingBottom: paragraphSegmentClipBleedBottomPx,
41064
+ overflow: "visible"
41065
+ },
41066
+ children: layoutEntry.pretextSource && pretextParagraphSliceLayout && pretextParagraphSliceLayout.lineCount > 0 ? renderWrappedPretextParagraph({
41067
+ location,
41068
+ keyPrefix: `body-cell-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}-lines-${paragraphSegmentStartLine}-${paragraphSegmentEndLine}`,
41069
+ source: layoutEntry.pretextSource,
41070
+ layout: pretextParagraphSliceLayout,
41071
+ lineHeightPx: paragraphSegmentLineHeightPx,
41072
+ baseTextStyle: firstRunStyle(paragraph),
41073
+ blockHeightPx: pretextParagraphSliceLayout.height,
41074
+ obstacleNodes: pretextSegmentNumberingMarkerNode
41075
+ }) : null
41076
+ }
41077
+ ) : hasPartialLineRange ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41078
+ "div",
41079
+ {
41080
+ style: {
41081
+ height: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
41082
+ marginTop: -paragraphSegmentClipBleedTopPx,
41083
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
41084
+ overflow: "hidden"
41085
+ },
41086
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41087
+ "div",
41088
+ {
41089
+ style: {
41090
+ transform: `translateY(-${paragraphSegmentTranslateYPx - paragraphSegmentClipBleedTopPx}px)`
41091
+ },
41092
+ children: fallbackParagraphRuns
41093
+ }
41094
+ )
41095
+ }
41096
+ ) : fallbackParagraphRuns;
41097
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41098
+ "div",
41099
+ {
41100
+ "data-docx-paragraph-host": "true",
41101
+ "data-docx-paragraph-kind": "table-cell",
41102
+ "data-docx-table-index": tableIndex,
41103
+ "data-docx-row-index": rowIndex,
41104
+ "data-docx-cell-index": cellIndex,
41105
+ "data-docx-paragraph-index": paragraphIndex,
41106
+ "data-docx-table-paragraph-index": paragraphIndex,
41107
+ style: paragraphStyle,
41108
+ children: renderedInteractiveParagraphContent
41109
+ },
41110
+ `body-cell-slice-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}`
41111
+ );
41112
+ };
39116
41113
  const renderDocumentNode = (node, nodeIndex, tableRowRange, tableRowSlice, paragraphLineRange, options) => {
39117
41114
  const nodeDocGridLinePitchPx = docGridLinePitchPxByNodeIndex.get(nodeIndex);
39118
41115
  const nodeContentWidthPx = Math.max(
@@ -39150,7 +41147,7 @@ function DocxEditorViewer({
39150
41147
  paragraphLineRange
39151
41148
  );
39152
41149
  const paragraphHasActiveEditableSegment = activeEditableParagraphSegment?.nodeIndex === nodeIndex;
39153
- const shouldTrackParagraphElement = !hasPartialLineRange || paragraphSegmentIsActiveEditable || !paragraphHasActiveEditableSegment && paragraphSegmentStartLine === 0;
41150
+ const shouldTrackParagraphElement = options?.suppressParagraphElementTracking === true ? false : !hasPartialLineRange || paragraphSegmentIsActiveEditable || !paragraphHasActiveEditableSegment && paragraphSegmentStartLine === 0;
39154
41151
  const isManualPageBreakParagraph = paragraphIsOnlyExplicitPageBreak2(node);
39155
41152
  const paragraphContentWidthPx = nodeContentWidthPx;
39156
41153
  const paragraphRenderTextWidthPx = paragraphAvailableTextWidthPx(
@@ -39159,7 +41156,8 @@ function DocxEditorViewer({
39159
41156
  editor.model.metadata.numberingDefinitions
39160
41157
  );
39161
41158
  const pretextParagraphSource = hasPartialLineRange ? buildParagraphPretextLayoutSource(node, {
39162
- allowExplicitLineBreakText: true
41159
+ allowExplicitLineBreakText: true,
41160
+ expandTabsForLayout: true
39163
41161
  }) : void 0;
39164
41162
  const pretextParagraphLayout = hasPartialLineRange && pretextParagraphSource ? layoutParagraphPretextSource(
39165
41163
  node,
@@ -39254,7 +41252,13 @@ function DocxEditorViewer({
39254
41252
  },
39255
41253
  `node-${nodeIndex}-numbering-marker-${paragraphSegmentStartLine}`
39256
41254
  ) : void 0;
39257
- const editable = !hasImage && !isReadOnly && (!hasPartialLineRange || paragraphSegmentIsActiveEditable) && !isManualPageBreakParagraph;
41255
+ const resolvedBeforeSpacingPx = Number.isFinite(
41256
+ options?.overrideBeforeSpacingPx
41257
+ ) ? Math.max(0, Math.round(options?.overrideBeforeSpacingPx)) : void 0;
41258
+ const resolvedAfterSpacingPx = Number.isFinite(
41259
+ options?.overrideAfterSpacingPx
41260
+ ) ? Math.max(0, Math.round(options?.overrideAfterSpacingPx)) : void 0;
41261
+ const editable = !hasImage && !isReadOnly && options?.forceReadOnly !== true && (!hasPartialLineRange || paragraphSegmentIsActiveEditable) && !isManualPageBreakParagraph;
39258
41262
  const resolvedPageLayout = options?.pageLayout ?? documentLayout;
39259
41263
  const paragraphContainsLikelyFullPageCoverImage = node.children.some(
39260
41264
  (child) => child.type === "image" && shouldRenderAbsoluteFloatingImage(child) && likelyFullPageCoverImageRelativeToContentBox(
@@ -39324,8 +41328,11 @@ function DocxEditorViewer({
39324
41328
  const paragraphStyle = {
39325
41329
  ...baseParagraphStyle,
39326
41330
  ...hasPartialLineRange ? {
39327
- marginTop: paragraphSegmentStartLine === 0 ? beforeSpacingPx : 0,
39328
- marginBottom: paragraphSegmentEndLine >= paragraphSegmentTotalLines ? afterSpacingPx : 0
41331
+ marginTop: paragraphSegmentStartLine === 0 ? resolvedBeforeSpacingPx ?? beforeSpacingPx : 0,
41332
+ marginBottom: paragraphSegmentEndLine >= paragraphSegmentTotalLines ? resolvedAfterSpacingPx ?? afterSpacingPx : 0
41333
+ } : resolvedBeforeSpacingPx !== void 0 || resolvedAfterSpacingPx !== void 0 ? {
41334
+ ...resolvedBeforeSpacingPx !== void 0 ? { marginTop: resolvedBeforeSpacingPx } : void 0,
41335
+ ...resolvedAfterSpacingPx !== void 0 ? { marginBottom: resolvedAfterSpacingPx } : void 0
39329
41336
  } : void 0,
39330
41337
  ...letterheadStyleAdjustments ?? void 0,
39331
41338
  ...options?.suppressLetterheadColumnLayout && options?.isFirstInLetterheadColumn ? { marginTop: 0 } : void 0,
@@ -39364,7 +41371,8 @@ function DocxEditorViewer({
39364
41371
  {
39365
41372
  style: {
39366
41373
  minHeight: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
39367
- marginBottom: -(paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx),
41374
+ marginTop: -paragraphSegmentClipBleedTopPx,
41375
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
39368
41376
  paddingTop: paragraphSegmentClipBleedTopPx,
39369
41377
  paddingBottom: paragraphSegmentClipBleedBottomPx,
39370
41378
  overflow: "visible"
@@ -39388,7 +41396,8 @@ function DocxEditorViewer({
39388
41396
  {
39389
41397
  style: {
39390
41398
  height: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
39391
- marginBottom: -(paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx),
41399
+ marginTop: -paragraphSegmentClipBleedTopPx,
41400
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
39392
41401
  overflow: "hidden"
39393
41402
  },
39394
41403
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -39974,7 +41983,7 @@ ${currentText.slice(end)}`;
39974
41983
  },
39975
41984
  children: !editable ? renderedInteractiveParagraphContent : null
39976
41985
  },
39977
- paragraphLineRange ? `epoch-${paragraphStructureEpoch}-node-${nodeIndex}-lines-${paragraphSegmentStartLine}-${paragraphSegmentEndLine}` : `epoch-${paragraphStructureEpoch}-node-${nodeIndex}`
41986
+ paragraphLineRange ? `epoch-${paragraphStructureEpoch}-node-${nodeIndex}-lines-${paragraphSegmentStartLine}-${paragraphSegmentEndLine}${options?.syntheticKeySuffix ? `-${options.syntheticKeySuffix}` : ""}` : `epoch-${paragraphStructureEpoch}-node-${nodeIndex}${options?.syntheticKeySuffix ? `-${options.syntheticKeySuffix}` : ""}`
39978
41987
  );
39979
41988
  }
39980
41989
  const tableRowSliceOffsetPxForWrapper = tableRowSlice ? Math.max(0, Math.round(tableRowSlice.startOffsetPx)) : 0;
@@ -40007,7 +42016,7 @@ ${currentText.slice(end)}`;
40007
42016
  paddingTop: tableRowSliceTopBleedPxForWrapper,
40008
42017
  paddingBottom: tableRowSliceBottomBleedPxForWrapper,
40009
42018
  boxSizing: "border-box",
40010
- overflow: "clip"
42019
+ overflow: "visible"
40011
42020
  } : void 0
40012
42021
  },
40013
42022
  onPointerEnter: () => {
@@ -40040,11 +42049,12 @@ ${currentText.slice(end)}`;
40040
42049
  },
40041
42050
  children: (() => {
40042
42051
  const tableIndentPx = twipsToSignedPixels(node.style?.indentTwips) ?? 0;
42052
+ const columnCount = tableColumnCount(node);
42053
+ const collapsedHorizontalBorderBleedPx = resolveCollapsedTableHorizontalOuterBleedPx(node, columnCount);
40043
42054
  const maxTableWidthPx = Math.max(
40044
42055
  120,
40045
- nodeContentWidthPx - tableIndentPx
42056
+ nodeContentWidthPx - tableIndentPx - collapsedHorizontalBorderBleedPx
40046
42057
  );
40047
- const columnCount = tableColumnCount(node);
40048
42058
  const tableWidthPx = twipsToPixels(node.style?.widthTwips);
40049
42059
  const hasStoredColumnWidths = (tableColumnWidths[nodeIndex]?.length ?? 0) === columnCount;
40050
42060
  const rawColumnWidthsPx = resolveTableColumnWidths(
@@ -40137,6 +42147,7 @@ ${currentText.slice(end)}`;
40137
42147
  "span",
40138
42148
  {
40139
42149
  contentEditable: false,
42150
+ "data-docx-pagination-ignore": "true",
40140
42151
  style: {
40141
42152
  position: "absolute",
40142
42153
  top: -TABLE_HANDLE_SAFEZONE_TOP_PX,
@@ -40154,6 +42165,7 @@ ${currentText.slice(end)}`;
40154
42165
  "span",
40155
42166
  {
40156
42167
  contentEditable: false,
42168
+ "data-docx-pagination-ignore": "true",
40157
42169
  style: {
40158
42170
  position: "absolute",
40159
42171
  right: -TABLE_HANDLE_SAFEZONE_RIGHT_PX,
@@ -40243,10 +42255,7 @@ ${currentText.slice(end)}`;
40243
42255
  style: {
40244
42256
  width: resolvedTableWidthPx > 0 ? `${resolvedTableWidthPx}px` : "100%",
40245
42257
  ...tableElementBorderStyle(node, tableBorderSpacingPx),
40246
- tableLayout: node.style?.layout === "autofit" ? "auto" : "fixed",
40247
- ...hasTableRowSlice && tableRowSliceOffsetPx > 0 ? {
40248
- transform: `translateY(-${tableRowSliceOffsetPx - tableRowSliceTopBleedPx}px)`
40249
- } : void 0
42258
+ tableLayout: node.style?.layout === "autofit" ? "auto" : "fixed"
40250
42259
  },
40251
42260
  children: [
40252
42261
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("colgroup", { children: columnWidthsPx.map((widthPx, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -40294,7 +42303,7 @@ ${currentText.slice(end)}`;
40294
42303
  );
40295
42304
  const recursiveCellParagraphs = tableCellParagraphsRecursively(cell.nodes);
40296
42305
  const cellHasImage = tableCellHasImage(cell.nodes);
40297
- const editableCell = selectedByAnchor && !isMultiCellSelectionActive && !cellHasImage && !isReadOnly && cellParagraphs.length > 0;
42306
+ const editableCell = selectedByAnchor && !isSlicedRow && !isMultiCellSelectionActive && !cellHasImage && !isReadOnly && cellParagraphs.length > 0;
40298
42307
  const nestedParagraphIndexesByNode = /* @__PURE__ */ new Map();
40299
42308
  recursiveCellParagraphs.forEach(
40300
42309
  (paragraph, paragraphIndex) => {
@@ -40304,7 +42313,7 @@ ${currentText.slice(end)}`;
40304
42313
  );
40305
42314
  }
40306
42315
  );
40307
- const tableCellEditScope = recursiveCellParagraphs.length > 0 && !isReadOnly && !isMultiCellSelectionActive && !cellHasImage ? {
42316
+ const tableCellEditScope = recursiveCellParagraphs.length > 0 && !isReadOnly && !isSlicedRow && !isMultiCellSelectionActive && !cellHasImage ? {
40308
42317
  isEditable: true,
40309
42318
  draftKeyPrefix: `${nodeIndex}:${rowIndex}:${cellIndex}`,
40310
42319
  paragraphIndexesByNode: nestedParagraphIndexesByNode,
@@ -40345,6 +42354,38 @@ ${currentText.slice(end)}`;
40345
42354
  ).reduce((sum, widthPx) => sum + widthPx, 0);
40346
42355
  const cellBackgroundColor = cell.style?.backgroundColor ?? row.style?.backgroundColor;
40347
42356
  const hasCustomCellRowHeight = hasCustomRowHeight || hasResolvedRowHeight;
42357
+ const mergedCellMarginTwips = mergeTableSpacing(
42358
+ tableCellMarginTwips,
42359
+ cell.style?.marginTwips
42360
+ );
42361
+ const cellPaddingPx = resolveTableSpacingPaddingPx(
42362
+ mergedCellMarginTwips
42363
+ );
42364
+ const cellRenderedWidthPx = cellWidthPx ?? spannedWidthPx;
42365
+ const cellContentWidthPx = Math.max(
42366
+ 1,
42367
+ cellRenderedWidthPx - cellPaddingPx.left - cellPaddingPx.right
42368
+ );
42369
+ const slicedRowHeightPx = Math.max(
42370
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
42371
+ Math.round(
42372
+ rowBoundarySourceHeightsPx[rowIndex] ?? rowHeightPx ?? MIN_PARAGRAPH_LINE_HEIGHT_PX
42373
+ )
42374
+ );
42375
+ const slicedCellViewportHeightPx = isSlicedRow && tableRowSlice ? Math.max(
42376
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
42377
+ Math.round(tableRowSlice.sliceHeightPx)
42378
+ ) : void 0;
42379
+ const slicedParagraphPlans = isSlicedRow && tableRowSlice && !editableCell && slicedCellViewportHeightPx ? resolveTableCellParagraphSlicePlans({
42380
+ cell,
42381
+ rowHeightPx: slicedRowHeightPx,
42382
+ sliceStartPx: tableRowSliceOffsetPx,
42383
+ sliceHeightPx: slicedCellViewportHeightPx,
42384
+ cellContentWidthPx,
42385
+ tableCellMarginTwips,
42386
+ applyWordTableDefaults,
42387
+ docGridLinePitchPx: nodeDocGridLinePitchPx
42388
+ }) : void 0;
40348
42389
  const renderedEditableCellContent = editableCell ? (() => {
40349
42390
  let paragraphCursor = 0;
40350
42391
  return cell.nodes.map(
@@ -40442,10 +42483,7 @@ ${currentText.slice(end)}`;
40442
42483
  cell.style?.borders
40443
42484
  ),
40444
42485
  ...tableSpacingPaddingStyle(
40445
- mergeTableSpacing(
40446
- tableCellMarginTwips,
40447
- cell.style?.marginTwips
40448
- )
42486
+ mergedCellMarginTwips
40449
42487
  ),
40450
42488
  backgroundColor: cellBackgroundColor,
40451
42489
  verticalAlign: cell.style?.verticalAlign ?? "top",
@@ -41266,6 +43304,45 @@ ${currentText.slice(end)}`;
41266
43304
  );
41267
43305
  }
41268
43306
  }
43307
+ ) : slicedParagraphPlans && slicedCellViewportHeightPx ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43308
+ "div",
43309
+ {
43310
+ style: {
43311
+ position: "relative",
43312
+ height: slicedCellViewportHeightPx,
43313
+ overflow: "visible"
43314
+ },
43315
+ children: slicedParagraphPlans.map((plan) => {
43316
+ const contentIndex = cell.nodes.indexOf(
43317
+ plan.paragraph
43318
+ );
43319
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43320
+ "div",
43321
+ {
43322
+ style: {
43323
+ position: "absolute",
43324
+ left: 0,
43325
+ right: 0,
43326
+ top: plan.topPx
43327
+ },
43328
+ children: renderSlicedTableCellParagraph({
43329
+ paragraph: plan.paragraph,
43330
+ paragraphIndex: plan.paragraphIndex,
43331
+ tableIndex: nodeIndex,
43332
+ rowIndex,
43333
+ cellIndex,
43334
+ contentIndex,
43335
+ cellContentWidthPx,
43336
+ applyWordTableDefaults,
43337
+ docGridLinePitchPx: nodeDocGridLinePitchPx,
43338
+ layoutEntry: plan.layoutEntry,
43339
+ paragraphLineRange: plan.paragraphLineRange
43340
+ })
43341
+ },
43342
+ `body-cell-slice-host-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`
43343
+ );
43344
+ })
43345
+ }
41269
43346
  ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "grid", gap: 4 }, children: (() => {
41270
43347
  let paragraphCursor = 0;
41271
43348
  return cell.nodes.map(
@@ -42757,10 +44834,11 @@ ${currentText.slice(end)}`;
42757
44834
  pageLayout.pageHeightPx - pageLayout.marginsPx.top - pageLayout.marginsPx.bottom
42758
44835
  ),
42759
44836
  metricsBySection: paginationSectionMetrics,
42760
- measuredPageContentHeightsPxByPageIndex: measuredPageContentHeightByIndex,
44837
+ measuredPageContentHeightsPxByPageIndex: renderMeasuredPageContentHeightsPxByPageIndex,
42761
44838
  measuredPageContentIdentityKeysByPageIndex: measuredPageContentIdentityKeysByIndex,
42762
44839
  pageIdentityKey: pageNodeSegmentIdentityKeysByPage[pageIndex],
42763
- useMeasuredPageContentHeights: useMeasuredPageContentHeightsForRender
44840
+ useMeasuredPageContentHeights: useMeasuredPageContentHeightsForRender,
44841
+ pageContentHeightScale: renderPageContentHeightScale
42764
44842
  });
42765
44843
  const headerFooterBodyDimmed = pageHeaderFooterEditActive;
42766
44844
  const documentPageBackgroundColor = editor.model.metadata.documentBackgroundColor;
@@ -43054,6 +45132,7 @@ ${currentText.slice(end)}`;
43054
45132
  display: "flex",
43055
45133
  flexDirection: "column",
43056
45134
  minHeight: pageBodyAvailableHeightPx,
45135
+ overflow: "visible",
43057
45136
  ...documentContentFilter ? { filter: documentContentFilter } : void 0
43058
45137
  },
43059
45138
  children: [
@@ -43121,6 +45200,44 @@ ${currentText.slice(end)}`;
43121
45200
  if (!columnNode) {
43122
45201
  return null;
43123
45202
  }
45203
+ const explicitColumnBreakParagraphSegments = columnNode.type === "paragraph" && !columnSegment.tableRowRange && !columnSegment.tableRowSlice && !columnSegment.paragraphLineRange && !explicitColumnWidthsPx && (sectionColumns?.count ?? 0) > 1 ? splitParagraphAtExplicitColumnBreaks(columnNode) : void 0;
45204
+ if (explicitColumnBreakParagraphSegments && explicitColumnBreakParagraphSegments.length > 1) {
45205
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
45206
+ React.Fragment,
45207
+ {
45208
+ children: explicitColumnBreakParagraphSegments.map(
45209
+ (segmentParagraph, segmentIndex) => {
45210
+ const isLastSegment = segmentIndex >= explicitColumnBreakParagraphSegments.length - 1;
45211
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
45212
+ "div",
45213
+ {
45214
+ style: segmentIndex > 0 ? { breakBefore: "column" } : void 0,
45215
+ children: renderDocumentNode(
45216
+ segmentParagraph,
45217
+ columnSegment.nodeIndex,
45218
+ void 0,
45219
+ void 0,
45220
+ void 0,
45221
+ {
45222
+ pageLayout,
45223
+ contentWidthPxOverride: columnContentWidthPx,
45224
+ suppressLikelyFullPageCoverImageKeys: suppressedLikelyFullPageCoverImageKeys,
45225
+ forceReadOnly: true,
45226
+ suppressParagraphElementTracking: segmentIndex > 0,
45227
+ syntheticKeySuffix: `column-break-${segmentIndex}`,
45228
+ overrideBeforeSpacingPx: segmentIndex === 0 ? void 0 : 0,
45229
+ overrideAfterSpacingPx: isLastSegment ? void 0 : 0
45230
+ }
45231
+ )
45232
+ },
45233
+ `column-layout-node-${pageIndex}-${columnSegment.nodeIndex}-column-break-${segmentIndex}`
45234
+ );
45235
+ }
45236
+ )
45237
+ },
45238
+ `column-layout-node-${pageIndex}-${columnSegment.nodeIndex}-column-break-group`
45239
+ );
45240
+ }
43124
45241
  const renderedNode = renderDocumentNode(
43125
45242
  columnNode,
43126
45243
  columnSegment.nodeIndex,
@@ -44792,6 +46909,9 @@ var DEFAULT_MIN_PARAGRAPH_LINE_HEIGHT_PX = 14;
44792
46909
  var PARAGRAPH_SEGMENT_TOP_BLEED_PX2 = 22;
44793
46910
  var PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX2 = 6;
44794
46911
  var PARAGRAPH_SEGMENT_VISUAL_SAFETY_PX2 = 24;
46912
+ var LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_RATIO2 = 0.18;
46913
+ var LAST_RENDERED_PAGE_BREAK_HINT_MIN_REMAINING_SPACE_PX2 = DEFAULT_MIN_PARAGRAPH_LINE_HEIGHT_PX * 3;
46914
+ var LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_PX2 = 120;
44795
46915
  function paragraphSegmentHasPartialLineRange2(paragraphLineRange) {
44796
46916
  if (!paragraphLineRange) {
44797
46917
  return false;
@@ -44860,6 +46980,48 @@ function normalizedPositivePixelValue(value, fallback) {
44860
46980
  }
44861
46981
  return Math.max(1, Math.round(value));
44862
46982
  }
46983
+ function shouldHonorParagraphStartLastRenderedPageBreak2(params) {
46984
+ const pageConsumedHeightPx = Math.max(
46985
+ 0,
46986
+ Math.round(params.pageConsumedHeightPx)
46987
+ );
46988
+ const pageContentHeightPx = Math.max(
46989
+ 0,
46990
+ Math.round(params.pageContentHeightPx)
46991
+ );
46992
+ if (pageConsumedHeightPx <= 0 || pageContentHeightPx <= 0) {
46993
+ return false;
46994
+ }
46995
+ const remainingHeightPx = Math.max(
46996
+ 0,
46997
+ pageContentHeightPx - pageConsumedHeightPx
46998
+ );
46999
+ const maxAllowedRemainingHeightPx = Math.max(
47000
+ LAST_RENDERED_PAGE_BREAK_HINT_MIN_REMAINING_SPACE_PX2,
47001
+ Math.min(
47002
+ LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_PX2,
47003
+ Math.round(
47004
+ pageContentHeightPx * LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_RATIO2
47005
+ )
47006
+ )
47007
+ );
47008
+ return remainingHeightPx <= maxAllowedRemainingHeightPx;
47009
+ }
47010
+ function keepNextParagraphReservePx(paragraph, nextParagraph, callbacks, docGridLinePitchPx) {
47011
+ if (paragraph.style?.keepNext !== true || !nextParagraph || !Number.isFinite(paragraph.style?.headingLevel)) {
47012
+ return 0;
47013
+ }
47014
+ const nextParagraphText = nextParagraph.children.filter((child) => child.type === "text").map((child) => child.text).join(" ").replace(/\s+/g, " ").trim();
47015
+ if (nextParagraph.style?.numbering === void 0 && nextParagraphText.length < 80) {
47016
+ return 0;
47017
+ }
47018
+ return Math.max(
47019
+ nextParagraph.style?.numbering ? 10 : 6,
47020
+ Math.round(
47021
+ callbacks.estimateParagraphLineHeightPx(nextParagraph, docGridLinePitchPx) * (nextParagraph.style?.numbering ? 1 : 0.5)
47022
+ )
47023
+ );
47024
+ }
44863
47025
  function normalizedMeasuredTableRowHeights(measuredRowHeightsPx, expectedRowCount, minParagraphLineHeightPx) {
44864
47026
  if (!measuredRowHeightsPx || measuredRowHeightsPx.length !== expectedRowCount) {
44865
47027
  return void 0;
@@ -45052,6 +47214,12 @@ function collectDocxEstimatedOverflowBreakStartNodeIndexes(model, hardBreakStart
45052
47214
  paragraphBeforeSpacingPx2(nextChainNode)
45053
47215
  );
45054
47216
  requiredHeightPx += Math.max(1, nextRawHeightPx - collapsedChainMarginPx);
47217
+ requiredHeightPx += keepNextParagraphReservePx(
47218
+ currentChainNode,
47219
+ nextChainNode,
47220
+ callbacks,
47221
+ chainMetrics.docGridLinePitchPx
47222
+ );
45055
47223
  chainPreviousParagraphAfterPx = paragraphAfterSpacingPx2(nextChainNode);
45056
47224
  }
45057
47225
  }
@@ -45148,7 +47316,10 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
45148
47316
  nodeMetrics.pageContentHeightPx
45149
47317
  );
45150
47318
  }
45151
- if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak2(node) && currentPageSegments.length > 0) {
47319
+ if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak2(node) && shouldHonorParagraphStartLastRenderedPageBreak2({
47320
+ pageConsumedHeightPx,
47321
+ pageContentHeightPx: currentPageContentHeightPx
47322
+ }) && currentPageSegments.length > 0) {
45152
47323
  startNextPage();
45153
47324
  pageConsumedHeightPx = 0;
45154
47325
  previousParagraphAfterPx = 0;
@@ -45373,6 +47544,12 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
45373
47544
  paragraphBeforeSpacingPx2(nextChainNode)
45374
47545
  );
45375
47546
  requiredHeightPx += Math.max(1, nextRawHeightPx - collapsedChainMarginPx);
47547
+ requiredHeightPx += keepNextParagraphReservePx(
47548
+ currentChainNode,
47549
+ nextChainNode,
47550
+ callbacks,
47551
+ chainMetrics.docGridLinePitchPx
47552
+ );
45376
47553
  chainPreviousParagraphAfterPx = paragraphAfterSpacingPx2(nextChainNode);
45377
47554
  }
45378
47555
  }