@extend-ai/react-docx 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  }
@@ -7797,6 +7799,107 @@ function parseParagraphsFromClipboard(input) {
7797
7799
  }
7798
7800
  }
7799
7801
 
7802
+ // src/docx-import-worker-client.ts
7803
+ var import_meta = {};
7804
+ var cachedWorker;
7805
+ var cachedWorkerUnavailable = false;
7806
+ var nextRequestId = 1;
7807
+ function resolveWorker() {
7808
+ if (cachedWorkerUnavailable) {
7809
+ return void 0;
7810
+ }
7811
+ if (cachedWorker) {
7812
+ return cachedWorker;
7813
+ }
7814
+ if (typeof window === "undefined" || typeof Worker === "undefined" || typeof URL === "undefined") {
7815
+ cachedWorkerUnavailable = true;
7816
+ return void 0;
7817
+ }
7818
+ try {
7819
+ const workerUrl = new URL(
7820
+ "./docx-import-worker.ts",
7821
+ import_meta.url
7822
+ );
7823
+ cachedWorker = new Worker(workerUrl, {
7824
+ type: "module",
7825
+ name: "docx-import"
7826
+ });
7827
+ return cachedWorker;
7828
+ } catch {
7829
+ cachedWorkerUnavailable = true;
7830
+ cachedWorker = void 0;
7831
+ return void 0;
7832
+ }
7833
+ }
7834
+ async function importDocxOnMainThread(buffer) {
7835
+ const pkg = await parseDocx(buffer);
7836
+ const model = buildDocModel(pkg);
7837
+ return { pkg, model };
7838
+ }
7839
+ async function importDocxViaWorker(buffer) {
7840
+ const worker = resolveWorker();
7841
+ if (!worker) {
7842
+ return importDocxOnMainThread(buffer);
7843
+ }
7844
+ const requestId = nextRequestId;
7845
+ nextRequestId += 1;
7846
+ return new Promise((resolve, reject) => {
7847
+ const handleMessage = (event) => {
7848
+ const data = event.data;
7849
+ if (!data || data.requestId !== requestId) {
7850
+ return;
7851
+ }
7852
+ worker.removeEventListener("message", handleMessage);
7853
+ worker.removeEventListener("error", handleError);
7854
+ worker.removeEventListener("messageerror", handleMessageError);
7855
+ if (data.type === "imported") {
7856
+ resolve({ pkg: data.pkg, model: data.model });
7857
+ } else {
7858
+ reject(new Error(data.message));
7859
+ }
7860
+ };
7861
+ const handleError = (event) => {
7862
+ worker.removeEventListener("message", handleMessage);
7863
+ worker.removeEventListener("error", handleError);
7864
+ worker.removeEventListener("messageerror", handleMessageError);
7865
+ const message = event instanceof ErrorEvent && event.message ? event.message : "DOCX import worker crashed";
7866
+ try {
7867
+ worker.terminate();
7868
+ } catch {
7869
+ }
7870
+ if (cachedWorker === worker) {
7871
+ cachedWorker = void 0;
7872
+ }
7873
+ reject(new Error(message));
7874
+ };
7875
+ const handleMessageError = () => {
7876
+ handleError(new Event("messageerror"));
7877
+ };
7878
+ worker.addEventListener("message", handleMessage);
7879
+ worker.addEventListener("error", handleError);
7880
+ worker.addEventListener("messageerror", handleMessageError);
7881
+ const request = {
7882
+ type: "import",
7883
+ requestId,
7884
+ buffer
7885
+ };
7886
+ try {
7887
+ worker.postMessage(request, [buffer]);
7888
+ } catch (error) {
7889
+ worker.removeEventListener("message", handleMessage);
7890
+ worker.removeEventListener("error", handleError);
7891
+ worker.removeEventListener("messageerror", handleMessageError);
7892
+ if (typeof console !== "undefined") {
7893
+ console.warn(
7894
+ "DOCX import worker postMessage failed; falling back to main thread.",
7895
+ error
7896
+ );
7897
+ }
7898
+ importDocxOnMainThread(buffer).then(resolve, reject);
7899
+ }
7900
+ });
7901
+ }
7902
+
7800
7903
  // ../serializer/src/index.ts
7801
7904
  var REL_TYPE_IMAGE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
7802
7905
  var REL_TYPE_HYPERLINK = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
@@ -9122,18 +9225,63 @@ function collectTopLevelExplicitPageBreakStartNodeIndexes(nodes) {
9122
9225
  }
9123
9226
 
9124
9227
  // src/page-count-reconciliation.ts
9228
+ var PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS = 10;
9125
9229
  function shouldAllowStoredPageCountReduction(options) {
9126
- const estimatedPageCount = Math.max(1, Math.round(options.estimatedPageCount));
9230
+ const estimatedPageCount = Math.max(
9231
+ 1,
9232
+ Math.round(options.estimatedPageCount)
9233
+ );
9127
9234
  const targetPageCount = Math.max(1, Math.round(options.targetPageCount));
9128
9235
  if (targetPageCount >= estimatedPageCount) {
9129
9236
  return true;
9130
9237
  }
9238
+ if (options.hasMeasuredBodyFooterOverlap === true) {
9239
+ return false;
9240
+ }
9131
9241
  if (options.hasLastRenderedPageBreakHints !== true) {
9132
9242
  return true;
9133
9243
  }
9134
- const renderedBreakHintPageCount = Number.isFinite(options.renderedBreakHintPageCount) ? Math.max(1, Math.round(options.renderedBreakHintPageCount)) : void 0;
9244
+ const renderedBreakHintPageCount = Number.isFinite(
9245
+ options.renderedBreakHintPageCount
9246
+ ) ? Math.max(1, Math.round(options.renderedBreakHintPageCount)) : void 0;
9135
9247
  return renderedBreakHintPageCount !== void 0 && targetPageCount >= renderedBreakHintPageCount;
9136
9248
  }
9249
+ function shouldLatchMeasuredBodyFooterOverlap(options) {
9250
+ if (options.measuredBodyFooterOverlap !== true) {
9251
+ return false;
9252
+ }
9253
+ const targetPageCount = Number.isFinite(options.targetPageCount) ? Math.max(1, Math.round(options.targetPageCount)) : void 0;
9254
+ if (targetPageCount === void 0) {
9255
+ return false;
9256
+ }
9257
+ const pageCount = Math.max(1, Math.round(options.pageCount));
9258
+ return pageCount <= targetPageCount;
9259
+ }
9260
+ function resolveMeasuredBodyFooterOverlapLatchState(options) {
9261
+ const shouldConsiderMeasuredBodyFooterOverlap = shouldLatchMeasuredBodyFooterOverlap({
9262
+ pageCount: options.pageCount,
9263
+ targetPageCount: options.targetPageCount,
9264
+ measuredBodyFooterOverlap: options.overlappingPageIndexes.length > 0
9265
+ });
9266
+ if (!shouldConsiderMeasuredBodyFooterOverlap) {
9267
+ return {
9268
+ signature: void 0,
9269
+ consecutivePasses: 0,
9270
+ shouldLatch: false
9271
+ };
9272
+ }
9273
+ const signature = options.overlappingPageIndexes.map((pageIndex) => `${pageIndex}`).join("|");
9274
+ const consecutivePasses = signature === options.previousSignature ? Math.max(0, Math.round(options.previousConsecutivePasses ?? 0)) + 1 : 1;
9275
+ const stabilityThreshold = Math.max(
9276
+ 1,
9277
+ Math.round(options.stabilityThreshold ?? 1)
9278
+ );
9279
+ return {
9280
+ signature,
9281
+ consecutivePasses,
9282
+ shouldLatch: consecutivePasses >= stabilityThreshold
9283
+ };
9284
+ }
9137
9285
  function isBetterCandidate(candidate, incumbent, targetPageCount) {
9138
9286
  const candidateDifference = Math.abs(candidate.pageCount - targetPageCount);
9139
9287
  const incumbentDifference = Math.abs(incumbent.pageCount - targetPageCount);
@@ -9147,7 +9295,7 @@ function isBetterCandidate(candidate, incumbent, targetPageCount) {
9147
9295
  }
9148
9296
  return candidate.pageCount === targetPageCount && incumbent.pageCount !== targetPageCount;
9149
9297
  }
9150
- function reconcilePagesToTargetCountByScalingHeight(options) {
9298
+ function reconcilePageCountCandidateToTargetCountByScalingHeight(options) {
9151
9299
  const {
9152
9300
  initialPages,
9153
9301
  targetPageCount,
@@ -9159,7 +9307,11 @@ function reconcilePagesToTargetCountByScalingHeight(options) {
9159
9307
  const initialPageCount = initialPages.length;
9160
9308
  const initialDifference = Math.abs(initialPageCount - safeTargetPageCount);
9161
9309
  if (initialDifference === 0 || initialDifference > maxDifference) {
9162
- return initialPages;
9310
+ return {
9311
+ pageCount: initialPageCount,
9312
+ pages: initialPages,
9313
+ scale: 1
9314
+ };
9163
9315
  }
9164
9316
  const bestCandidate = {
9165
9317
  pageCount: initialPageCount,
@@ -9209,22 +9361,71 @@ function reconcilePagesToTargetCountByScalingHeight(options) {
9209
9361
  0.24,
9210
9362
  0.22,
9211
9363
  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) {
9364
+ ] : [
9365
+ 1.02,
9366
+ 1.04,
9367
+ 1.06,
9368
+ 1.08,
9369
+ 1.1,
9370
+ 1.12,
9371
+ 1.14,
9372
+ 1.16,
9373
+ 1.18,
9374
+ 1.2,
9375
+ 1.22,
9376
+ 1.24,
9377
+ 1.26,
9378
+ 1.28,
9379
+ 1.3
9380
+ ];
9381
+ const buildCandidateAtScale = (scale) => {
9214
9382
  const pages = buildPagesAtScale(scale);
9215
- const candidate = {
9383
+ return {
9216
9384
  pageCount: pages.length,
9217
9385
  pages,
9218
9386
  scale
9219
9387
  };
9388
+ };
9389
+ const refineExactTargetCandidate = (lowerScale, upperScale) => {
9390
+ let bestExactCandidate;
9391
+ const interval = upperScale - lowerScale;
9392
+ if (!Number.isFinite(interval) || Math.abs(interval) < 1e-4) {
9393
+ return selectedCandidate;
9394
+ }
9395
+ for (let step = 1; step <= PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS; step += 1) {
9396
+ const scale = lowerScale + interval * step / PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS;
9397
+ const candidate = buildCandidateAtScale(scale);
9398
+ if (isBetterCandidate(candidate, selectedCandidate, safeTargetPageCount)) {
9399
+ selectedCandidate = candidate;
9400
+ }
9401
+ if (candidate.pageCount === safeTargetPageCount && (bestExactCandidate === void 0 || isBetterCandidate(
9402
+ candidate,
9403
+ bestExactCandidate,
9404
+ safeTargetPageCount
9405
+ ))) {
9406
+ bestExactCandidate = candidate;
9407
+ }
9408
+ }
9409
+ return bestExactCandidate ?? selectedCandidate;
9410
+ };
9411
+ let previousScale = 1;
9412
+ let previousPageCount = initialPageCount;
9413
+ for (const scale of scales) {
9414
+ const candidate = buildCandidateAtScale(scale);
9220
9415
  if (isBetterCandidate(candidate, selectedCandidate, safeTargetPageCount)) {
9221
9416
  selectedCandidate = candidate;
9222
9417
  }
9223
9418
  if (candidate.pageCount === safeTargetPageCount) {
9224
- return candidate.pages;
9419
+ const crossedIntoExactTarget = needMorePages ? previousPageCount < safeTargetPageCount : previousPageCount > safeTargetPageCount;
9420
+ if (crossedIntoExactTarget) {
9421
+ return refineExactTargetCandidate(previousScale, scale);
9422
+ }
9423
+ return candidate;
9225
9424
  }
9425
+ previousScale = scale;
9426
+ previousPageCount = candidate.pageCount;
9226
9427
  }
9227
- return selectedCandidate.pages;
9428
+ return selectedCandidate;
9228
9429
  }
9229
9430
 
9230
9431
  // src/pretext-layout.ts
@@ -9449,6 +9650,22 @@ function prepareCached(text, font, wordBreak = "normal") {
9449
9650
  return void 0;
9450
9651
  }
9451
9652
  }
9653
+ function measurePretextPlainTextLineCount(text, font, containerWidthPx, options) {
9654
+ if (!text) {
9655
+ return 0;
9656
+ }
9657
+ const wordBreak = options?.wordBreak ?? "normal";
9658
+ const prepared = prepareCached(text, font, wordBreak);
9659
+ if (!prepared) {
9660
+ return void 0;
9661
+ }
9662
+ try {
9663
+ const safeWidth = Math.max(1, Math.round(containerWidthPx));
9664
+ return (0, import_pretext.measureLineStats)(prepared, safeWidth).lineCount;
9665
+ } catch {
9666
+ return void 0;
9667
+ }
9668
+ }
9452
9669
  function cloneItemCursor(cursor) {
9453
9670
  return {
9454
9671
  itemIndex: cursor.itemIndex,
@@ -10190,7 +10407,7 @@ var SCRIPT_FONT_SCALE = 0.65;
10190
10407
  var DEFAULT_PARAGRAPH_LINE_MULTIPLE = 1;
10191
10408
  var WORD_SINGLE_LINE_AUTO_SCALE = 0.88;
10192
10409
  var WORD_SINGLE_LINE_AUTO_SCALE_SANS = 0.9;
10193
- var WORD_SINGLE_LINE_AUTO_SCALE_SERIF = 1.12;
10410
+ var WORD_SINGLE_LINE_AUTO_SCALE_SERIF = 1.08;
10194
10411
  var WORD_AUTO_LINE_SCALE_BLEND_END_MULTIPLE = 1.08;
10195
10412
  var MIN_AUTO_LINE_MULTIPLE = 0.1;
10196
10413
  var MIN_PARAGRAPH_LINE_HEIGHT_PX = 14;
@@ -10200,10 +10417,12 @@ var MEASURED_PAGE_FOOTER_CLEARANCE_BUFFER_PX = 24;
10200
10417
  var UNOVERLAPPED_FOOTER_MIN_CLEARANCE_PX = 16;
10201
10418
  var FLOATING_FOOTER_BASELINE_CLEARANCE_RESERVE_PX = 16;
10202
10419
  var PAGINATION_MEASUREMENT_INTERACTION_DEBOUNCE_MS = 180;
10420
+ var MEASURED_BODY_FOOTER_OVERLAP_STABILITY_THRESHOLD = 3;
10203
10421
  var WORD_TABLE_CELL_PARAGRAPH_AUTO_LINE_TWIPS = 240;
10204
10422
  var WORD_TABLE_CELL_PARAGRAPH_BEFORE_TWIPS = 0;
10205
10423
  var WORD_TABLE_CELL_PARAGRAPH_AFTER_TWIPS = 0;
10206
10424
  var TABLE_ROW_SLICE_VISUAL_BLEED_PX = 1;
10425
+ var TABLE_CELL_SLICE_FULLY_VISIBLE_BOTTOM_BUFFER_PX = 4;
10207
10426
  var DEFAULT_SPLIT_PARAGRAPH_LINE_TWIPS = 259;
10208
10427
  var DEFAULT_SPLIT_PARAGRAPH_AFTER_TWIPS = 160;
10209
10428
  var PAGE_CONTENT_MEASUREMENT_IGNORE_ATTRIBUTE = "data-docx-pagination-ignore";
@@ -10236,15 +10455,19 @@ var LEADING_COVER_SPACER_EXTRA_HEIGHT_PX = 2;
10236
10455
  var PARAGRAPH_SEGMENT_TOP_BLEED_PX = 22;
10237
10456
  var PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX = 6;
10238
10457
  var PARAGRAPH_SEGMENT_VISUAL_SAFETY_PX = 24;
10458
+ var LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_RATIO = 0.18;
10459
+ var LAST_RENDERED_PAGE_BREAK_HINT_MIN_REMAINING_SPACE_PX = MIN_PARAGRAPH_LINE_HEIGHT_PX * 3;
10460
+ var LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_PX = 120;
10239
10461
  var PARAGRAPH_SEGMENT_FALLBACK_TOP_BLEED_MAX_PX = 4;
10240
10462
  var PARAGRAPH_SEGMENT_FALLBACK_BOTTOM_BLEED_MAX_PX = 0;
10241
10463
  var PARAGRAPH_SEGMENT_FALLBACK_VISUAL_SAFETY_PX = 4;
10242
10464
  var INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT = 8;
10243
10465
  var INITIAL_PAGINATION_PAGE_COUNT_OSCILLATION_DISTINCT_THRESHOLD = 2;
10244
10466
  var INITIAL_PAGINATION_PAGE_COUNT_OSCILLATION_CHANGE_THRESHOLD = 4;
10467
+ var INITIAL_PAGINATION_BACKGROUND_REFINEMENT_DELAY_MS = 96;
10245
10468
  var DEFAULT_PAGE_VIRTUALIZATION_OVERSCAN = 2;
10246
10469
  var DEFAULT_PAGE_VIRTUALIZATION_SETTLE_DELAY_MS = 350;
10247
- var ENABLE_TABLE_ROW_SLICING = false;
10470
+ var ENABLE_TABLE_ROW_SLICING = true;
10248
10471
  var TOP_AND_BOTTOM_VERTICAL_DRAG_SNAP_PX = 10;
10249
10472
  var HEADER_FOOTER_INACTIVE_OPACITY = 0.5;
10250
10473
  var LETTERHEAD_INDENT_MIN_TWIPS = 900;
@@ -10549,7 +10772,11 @@ function nearestScrollableAncestor(element) {
10549
10772
  }
10550
10773
  current = current.parentElement;
10551
10774
  }
10552
- return null;
10775
+ const scrollingElement = typeof document !== "undefined" ? document.scrollingElement : null;
10776
+ if (scrollingElement instanceof HTMLElement) {
10777
+ return scrollingElement;
10778
+ }
10779
+ return typeof document !== "undefined" ? document.documentElement : null;
10553
10780
  }
10554
10781
  function resolveEffectiveZoomScale(element) {
10555
10782
  let current = element;
@@ -10651,7 +10878,7 @@ function normalizeMeasuredTableRowHeightPx(heightPx) {
10651
10878
  }
10652
10879
  return Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, Math.round(heightPx));
10653
10880
  }
10654
- function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowHeights, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx) {
10881
+ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowHeights, maxAvailableWidthPx, pageContentHeightPx, numberingDefinitions, docGridLinePitchPx) {
10655
10882
  if (measuredRowHeights.length !== table.rows.length) {
10656
10883
  return void 0;
10657
10884
  }
@@ -10659,7 +10886,8 @@ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowH
10659
10886
  table,
10660
10887
  maxAvailableWidthPx,
10661
10888
  numberingDefinitions,
10662
- docGridLinePitchPx
10889
+ docGridLinePitchPx,
10890
+ pageContentHeightPx
10663
10891
  );
10664
10892
  if (estimatedRowHeights.length !== table.rows.length) {
10665
10893
  return void 0;
@@ -10667,6 +10895,7 @@ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowH
10667
10895
  return measuredRowHeights.map((heightPx, rowIndex) => {
10668
10896
  const row = table.rows[rowIndex];
10669
10897
  const normalizedMeasuredHeightPx = normalizeMeasuredTableRowHeightPx(heightPx);
10898
+ const normalizedPageContentHeightPx = Number.isFinite(pageContentHeightPx) && pageContentHeightPx > 0 ? Math.max(120, Math.round(pageContentHeightPx)) : void 0;
10670
10899
  const estimatedHeightPx = Math.max(
10671
10900
  MIN_PARAGRAPH_LINE_HEIGHT_PX,
10672
10901
  Math.round(estimatedRowHeights[rowIndex] ?? MIN_PARAGRAPH_LINE_HEIGHT_PX)
@@ -10684,6 +10913,9 @@ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowH
10684
10913
  if (rowAllowsPageSplit(row) && row.style?.heightRule !== "exact") {
10685
10914
  return Math.max(explicitMinimumHeightPx, normalizedMeasuredHeightPx);
10686
10915
  }
10916
+ if (Number.isFinite(normalizedPageContentHeightPx) && normalizedMeasuredHeightPx > normalizedPageContentHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
10917
+ return Math.max(explicitMinimumHeightPx, normalizedMeasuredHeightPx);
10918
+ }
10687
10919
  const minimumHeightPx = Math.max(
10688
10920
  estimatedHeightPx,
10689
10921
  explicitMinimumHeightPx
@@ -10729,6 +10961,7 @@ function resolveTableMeasuredRowHeightsForPagination(nodes, tableMeasuredRowHeig
10729
10961
  tableNode,
10730
10962
  measuredRowHeights,
10731
10963
  options?.pageContentWidthPxByNodeIndex?.get(tableIndex),
10964
+ options?.pageContentHeightPxByNodeIndex?.get(tableIndex),
10732
10965
  options?.numberingDefinitions,
10733
10966
  options?.docGridLinePitchPxByNodeIndex?.get(tableIndex)
10734
10967
  ) ?? measuredRowHeights.map(
@@ -11493,9 +11726,9 @@ function resolveFooterPaginationReservePx(footerSections, layout) {
11493
11726
  )
11494
11727
  );
11495
11728
  const footerBodyOverlapPx = estimatedFooterHeightPx + layout.footerDistancePx - layout.marginsPx.bottom;
11496
- const explicitFooterOverlapReservePx = Math.max(
11729
+ const explicitFooterBoundaryReservePx = Math.max(
11497
11730
  0,
11498
- Math.round(footerBodyOverlapPx)
11731
+ Math.round(footerBodyOverlapPx + UNOVERLAPPED_FOOTER_MIN_CLEARANCE_PX)
11499
11732
  );
11500
11733
  const floatingFooterBoundaryReservePx = Number.isFinite(
11501
11734
  floatingFooterBoundaryTopPx
@@ -11507,13 +11740,13 @@ function resolveFooterPaginationReservePx(footerSections, layout) {
11507
11740
  ) : 0;
11508
11741
  if (hasFloatingFooterBodyIntrusionRisk) {
11509
11742
  return Math.max(
11510
- explicitFooterOverlapReservePx,
11743
+ explicitFooterBoundaryReservePx,
11511
11744
  floatingFooterBoundaryReservePx,
11512
11745
  FLOATING_FOOTER_BASELINE_CLEARANCE_RESERVE_PX
11513
11746
  );
11514
11747
  }
11515
11748
  return Math.max(
11516
- explicitFooterOverlapReservePx,
11749
+ explicitFooterBoundaryReservePx,
11517
11750
  floatingFooterBoundaryReservePx
11518
11751
  );
11519
11752
  }
@@ -11733,7 +11966,7 @@ function resolvePageContentHeightPxForPageSegments(pageSegments, pageIndex, defa
11733
11966
  );
11734
11967
  }
11735
11968
  function resolveRenderPageContentHeightPxForPageSegments(params) {
11736
- return resolvePageContentHeightPxForPageSegments(
11969
+ const resolvedHeightPx = resolvePageContentHeightPxForPageSegments(
11737
11970
  params.pageSegments,
11738
11971
  params.pageIndex,
11739
11972
  params.defaultPageContentHeightPx,
@@ -11742,6 +11975,13 @@ function resolveRenderPageContentHeightPxForPageSegments(params) {
11742
11975
  params.useMeasuredPageContentHeights === false ? void 0 : params.measuredPageContentIdentityKeysByPageIndex,
11743
11976
  params.pageIdentityKey
11744
11977
  );
11978
+ if (params.useMeasuredPageContentHeights === false && Number.isFinite(params.pageContentHeightScale) && Math.abs(params.pageContentHeightScale - 1) >= 1e-3) {
11979
+ return Math.max(
11980
+ 120,
11981
+ Math.round(resolvedHeightPx * params.pageContentHeightScale)
11982
+ );
11983
+ }
11984
+ return resolvedHeightPx;
11745
11985
  }
11746
11986
  function documentPageContainsOnlySplitParagraphSegments(pageSegments) {
11747
11987
  return pageSegments.length > 0 && pageSegments.every(
@@ -12278,28 +12518,74 @@ function nodeTreeContainsExplicitFontFamily(nodes) {
12278
12518
  return false;
12279
12519
  });
12280
12520
  }
12521
+ function firstExplicitFontFamilyInNodeTree(nodes) {
12522
+ for (const node of nodes) {
12523
+ if (node.type === "paragraph") {
12524
+ for (const child of node.children) {
12525
+ if (child.type !== "text" && child.type !== "form-field") {
12526
+ continue;
12527
+ }
12528
+ const fontFamily = child.style?.fontFamily?.trim();
12529
+ if (fontFamily) {
12530
+ return fontFamily;
12531
+ }
12532
+ }
12533
+ continue;
12534
+ }
12535
+ if (node.type === "table") {
12536
+ for (const row of node.rows) {
12537
+ for (const cell of row.cells) {
12538
+ const nestedFontFamily = firstExplicitFontFamilyInNodeTree(cell.nodes);
12539
+ if (nestedFontFamily) {
12540
+ return nestedFontFamily;
12541
+ }
12542
+ }
12543
+ }
12544
+ }
12545
+ }
12546
+ return void 0;
12547
+ }
12281
12548
  function resolveDocumentInheritedFontFamily(model) {
12282
12549
  const paragraphStyles = model.metadata.paragraphStyles ?? [];
12283
- const styleDefinesFontFamily = paragraphStyles.some(
12550
+ const normalizedDefaultStyleId = model.metadata.defaultParagraphStyleId?.trim().toLowerCase() ?? "";
12551
+ const defaultParagraphStyle = paragraphStyles.find(
12552
+ (style) => style.id.trim().toLowerCase() === normalizedDefaultStyleId
12553
+ ) ?? paragraphStyles.find((style) => style.isDefault) ?? paragraphStyles.find((style) => style.id.trim().toLowerCase() === "normal");
12554
+ const defaultStyleFontFamily = defaultParagraphStyle?.runStyle?.fontFamily?.trim();
12555
+ if (defaultStyleFontFamily) {
12556
+ return cssFontFamily(defaultStyleFontFamily);
12557
+ }
12558
+ const paragraphStyleFontFamily = paragraphStyles.find(
12284
12559
  (style) => Boolean(style.runStyle?.fontFamily?.trim())
12285
- );
12286
- if (styleDefinesFontFamily) {
12287
- return void 0;
12560
+ )?.runStyle?.fontFamily;
12561
+ if (paragraphStyleFontFamily) {
12562
+ return cssFontFamily(paragraphStyleFontFamily);
12288
12563
  }
12289
- if (nodeTreeContainsExplicitFontFamily(model.nodes)) {
12290
- return void 0;
12564
+ const explicitBodyFontFamily = firstExplicitFontFamilyInNodeTree(model.nodes);
12565
+ if (explicitBodyFontFamily) {
12566
+ return cssFontFamily(explicitBodyFontFamily);
12291
12567
  }
12292
- if ((model.metadata.headerSections ?? []).some(
12293
- (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12294
- )) {
12295
- return void 0;
12568
+ for (const section of model.metadata.headerSections ?? []) {
12569
+ const explicitHeaderFontFamily = firstExplicitFontFamilyInNodeTree(
12570
+ section.nodes
12571
+ );
12572
+ if (explicitHeaderFontFamily) {
12573
+ return cssFontFamily(explicitHeaderFontFamily);
12574
+ }
12296
12575
  }
12297
- if ((model.metadata.footerSections ?? []).some(
12298
- (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12299
- )) {
12300
- return void 0;
12576
+ for (const section of model.metadata.footerSections ?? []) {
12577
+ const explicitFooterFontFamily = firstExplicitFontFamilyInNodeTree(
12578
+ section.nodes
12579
+ );
12580
+ if (explicitFooterFontFamily) {
12581
+ return cssFontFamily(explicitFooterFontFamily);
12582
+ }
12301
12583
  }
12302
- return cssFontFamily(DEFAULT_UNSPECIFIED_DOCX_FONT_FAMILY);
12584
+ return nodeTreeContainsExplicitFontFamily(model.nodes) || (model.metadata.headerSections ?? []).some(
12585
+ (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12586
+ ) || (model.metadata.footerSections ?? []).some(
12587
+ (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12588
+ ) ? void 0 : cssFontFamily(DEFAULT_UNSPECIFIED_DOCX_FONT_FAMILY);
12303
12589
  }
12304
12590
  function replaceTabLayoutMarkersWithTabText(root) {
12305
12591
  const centerLayouts = Array.from(
@@ -12667,6 +12953,11 @@ function sectionNodesNeedFullPageFooterOverlay(nodes) {
12667
12953
  function paragraphHasFormField2(paragraph) {
12668
12954
  return paragraph.children.some((child) => child.type === "form-field");
12669
12955
  }
12956
+ function paragraphHasCheckboxFormField(paragraph) {
12957
+ return paragraph.children.some(
12958
+ (child) => child.type === "form-field" && child.fieldType === "checkbox"
12959
+ );
12960
+ }
12670
12961
  function paragraphHasVisibleText2(paragraph) {
12671
12962
  return paragraph.children.some(
12672
12963
  (child) => child.type === "text" && child.text.trim().length > 0 || child.type === "form-field" && formFieldDisplayValue2(child).trim().length > 0
@@ -12985,6 +13276,9 @@ function paragraphLooksLikeCheckboxChoiceRow(paragraph) {
12985
13276
  }
12986
13277
  var KEEP_ALL_SCRIPT_RE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u;
12987
13278
  var MIN_DUAL_WRAPPED_INTERIOR_BAND_PX = 72;
13279
+ var paragraphPretextLayoutSourceCache = /* @__PURE__ */ new WeakMap();
13280
+ var paragraphPretextLayoutItemsBySource = /* @__PURE__ */ new WeakMap();
13281
+ var paragraphPretextUniformFontBySource = /* @__PURE__ */ new WeakMap();
12988
13282
  function imageWrapModeFromFloating(floating) {
12989
13283
  if (!floating) {
12990
13284
  return "inline";
@@ -13130,16 +13424,67 @@ function resolveFloatingForImageWrapMode(mode, currentFloating, seedFloating) {
13130
13424
  };
13131
13425
  }
13132
13426
  }
13427
+ function buildParagraphPretextTabSpacerText(widthPx, style, paragraphBaseFontPx) {
13428
+ const safeWidthPx = Math.max(8, Math.round(widthPx));
13429
+ const spacerCharacter = "\xA0";
13430
+ const spacerAdvancePx = Math.max(
13431
+ 1,
13432
+ measureTextWidthPx2(spacerCharacter, style, paragraphBaseFontPx)
13433
+ );
13434
+ let spacerCount = Math.max(1, Math.round(safeWidthPx / spacerAdvancePx));
13435
+ let spacerText = spacerCharacter.repeat(spacerCount);
13436
+ let measuredWidthPx = measureTextWidthPx2(
13437
+ spacerText,
13438
+ style,
13439
+ paragraphBaseFontPx
13440
+ );
13441
+ while (measuredWidthPx + spacerAdvancePx * 0.5 < safeWidthPx && spacerCount < 64) {
13442
+ spacerCount += 1;
13443
+ spacerText = spacerCharacter.repeat(spacerCount);
13444
+ measuredWidthPx = measureTextWidthPx2(spacerText, style, paragraphBaseFontPx);
13445
+ }
13446
+ while (spacerCount > 1) {
13447
+ const nextText = spacerCharacter.repeat(spacerCount - 1);
13448
+ const nextWidthPx = measureTextWidthPx2(nextText, style, paragraphBaseFontPx);
13449
+ if (Math.abs(nextWidthPx - safeWidthPx) >= Math.abs(measuredWidthPx - safeWidthPx)) {
13450
+ break;
13451
+ }
13452
+ spacerCount -= 1;
13453
+ spacerText = nextText;
13454
+ measuredWidthPx = nextWidthPx;
13455
+ }
13456
+ return spacerText;
13457
+ }
13133
13458
  function buildParagraphPretextLayoutSource(paragraph, options) {
13459
+ const cacheKey = (options?.allowExplicitLineBreakText ? 1 : 0) | (options?.expandTabsForLayout ? 2 : 0);
13460
+ const cachedVariants = paragraphPretextLayoutSourceCache.get(paragraph);
13461
+ const cachedSource = cachedVariants?.get(cacheKey);
13462
+ if (cachedSource !== void 0) {
13463
+ return cachedSource ?? void 0;
13464
+ }
13465
+ const storeCachedSource = (source) => {
13466
+ if (!cachedVariants) {
13467
+ paragraphPretextLayoutSourceCache.set(
13468
+ paragraph,
13469
+ /* @__PURE__ */ new Map([[cacheKey, source ?? null]])
13470
+ );
13471
+ } else {
13472
+ cachedVariants.set(cacheKey, source ?? null);
13473
+ }
13474
+ return source;
13475
+ };
13134
13476
  if (paragraphHasFormField2(paragraph)) {
13135
- return void 0;
13477
+ return storeCachedSource(void 0);
13136
13478
  }
13137
13479
  if (!options?.allowExplicitLineBreakText && paragraphContainsExplicitLineBreakText(paragraph)) {
13138
- return void 0;
13480
+ return storeCachedSource(void 0);
13139
13481
  }
13140
13482
  const runs = [];
13141
13483
  let combinedText = "";
13142
13484
  const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
13485
+ const tabStopPositionsPx = options?.expandTabsForLayout ? resolveParagraphTabStopsPx(paragraph) : [];
13486
+ const fallbackTabWidthPx = paragraphLooksLikeCheckboxChoiceRow(paragraph) ? checkboxChoiceRowTabWidthPx(paragraph) : DEFAULT_TAB_STOP_PX;
13487
+ let approximateLineWidthPx = 0;
13143
13488
  let lastTextStyle = firstRunStyle(paragraph);
13144
13489
  for (let childIndex = 0; childIndex < paragraph.children.length; childIndex += 1) {
13145
13490
  const child = paragraph.children[childIndex];
@@ -13169,10 +13514,63 @@ function buildParagraphPretextLayoutSource(paragraph, options) {
13169
13514
  continue;
13170
13515
  }
13171
13516
  if (child.type !== "text") {
13172
- return void 0;
13173
- }
13174
- if (child.noteReference || child.text.includes(" ")) {
13175
- return void 0;
13517
+ return storeCachedSource(void 0);
13518
+ }
13519
+ if (child.noteReference) {
13520
+ return storeCachedSource(void 0);
13521
+ }
13522
+ if (child.text.includes(" ")) {
13523
+ if (!options?.expandTabsForLayout) {
13524
+ return storeCachedSource(void 0);
13525
+ }
13526
+ const tabSegments = child.text.split(" ");
13527
+ tabSegments.forEach((segmentText, segmentIndex) => {
13528
+ if (segmentText.length > 0) {
13529
+ const startOffset3 = combinedText.length;
13530
+ combinedText += segmentText;
13531
+ runs.push({
13532
+ kind: "text",
13533
+ key: `run-${childIndex}-${segmentIndex}`,
13534
+ text: segmentText,
13535
+ startOffset: startOffset3,
13536
+ endOffset: combinedText.length,
13537
+ style: child.style,
13538
+ link: child.link
13539
+ });
13540
+ approximateLineWidthPx = updateEstimatedLineWidthPxForText(
13541
+ approximateLineWidthPx,
13542
+ segmentText,
13543
+ child.style
13544
+ );
13545
+ }
13546
+ if (segmentIndex >= tabSegments.length - 1) {
13547
+ return;
13548
+ }
13549
+ const tabWidthPx = resolveTabSpacerWidthPx(
13550
+ tabStopPositionsPx,
13551
+ approximateLineWidthPx,
13552
+ fallbackTabWidthPx
13553
+ );
13554
+ const spacerText = buildParagraphPretextTabSpacerText(
13555
+ tabWidthPx,
13556
+ child.style,
13557
+ paragraphBaseFontPx
13558
+ );
13559
+ const startOffset2 = combinedText.length;
13560
+ combinedText += spacerText;
13561
+ runs.push({
13562
+ kind: "tab",
13563
+ key: `run-${childIndex}-${segmentIndex}-tab`,
13564
+ text: spacerText,
13565
+ startOffset: startOffset2,
13566
+ endOffset: combinedText.length,
13567
+ style: child.style,
13568
+ tabWidthPx
13569
+ });
13570
+ approximateLineWidthPx += tabWidthPx;
13571
+ });
13572
+ lastTextStyle = child.style ?? lastTextStyle;
13573
+ continue;
13176
13574
  }
13177
13575
  const startOffset = combinedText.length;
13178
13576
  combinedText += child.text;
@@ -13185,15 +13583,142 @@ function buildParagraphPretextLayoutSource(paragraph, options) {
13185
13583
  style: child.style,
13186
13584
  link: child.link
13187
13585
  });
13586
+ approximateLineWidthPx = updateEstimatedLineWidthPxForText(
13587
+ approximateLineWidthPx,
13588
+ child.text,
13589
+ child.style
13590
+ );
13188
13591
  lastTextStyle = child.style ?? lastTextStyle;
13189
13592
  }
13190
13593
  if (combinedText.length === 0) {
13191
- return void 0;
13594
+ return storeCachedSource(void 0);
13192
13595
  }
13193
- return {
13596
+ return storeCachedSource({
13194
13597
  text: combinedText,
13195
13598
  runs
13599
+ });
13600
+ }
13601
+ function splitParagraphAtExplicitColumnBreaks(paragraph) {
13602
+ if (!paragraphHasExplicitColumnBreak(paragraph)) {
13603
+ return void 0;
13604
+ }
13605
+ const paragraphChildren = [];
13606
+ let currentChildren = [];
13607
+ let sawExplicitColumnBreak = false;
13608
+ const appendCurrentSegment = () => {
13609
+ paragraphChildren.push(currentChildren);
13610
+ currentChildren = [];
13196
13611
  };
13612
+ for (let childIndex = 0; childIndex < paragraph.children.length; childIndex += 1) {
13613
+ const child = paragraph.children[childIndex];
13614
+ if (!child) {
13615
+ continue;
13616
+ }
13617
+ if (child.type === "text") {
13618
+ if (/^[\r\n]+$/.test(child.text)) {
13619
+ const explicitBreakCount = child.text.replace(/[^\n]/g, "").length;
13620
+ if (explicitBreakCount > 0) {
13621
+ for (let breakIndex = 0; breakIndex < explicitBreakCount; breakIndex += 1) {
13622
+ sawExplicitColumnBreak = true;
13623
+ appendCurrentSegment();
13624
+ }
13625
+ continue;
13626
+ }
13627
+ }
13628
+ currentChildren.push(cloneTextRunWithMetadata(child));
13629
+ continue;
13630
+ }
13631
+ if (child.type === "form-field") {
13632
+ currentChildren.push(cloneFormFieldRun2(child));
13633
+ continue;
13634
+ }
13635
+ return void 0;
13636
+ }
13637
+ if (!sawExplicitColumnBreak) {
13638
+ return void 0;
13639
+ }
13640
+ appendCurrentSegment();
13641
+ return paragraphChildren.map((children, segmentIndex) => {
13642
+ const nextStyle = cloneParagraphStyle2(paragraph.style);
13643
+ if (segmentIndex > 0 && nextStyle?.numbering) {
13644
+ nextStyle.numbering = void 0;
13645
+ }
13646
+ return {
13647
+ ...paragraph,
13648
+ style: nextStyle,
13649
+ sourceXml: void 0,
13650
+ children: children.length > 0 ? children : [
13651
+ {
13652
+ type: "text",
13653
+ text: ""
13654
+ }
13655
+ ]
13656
+ };
13657
+ });
13658
+ }
13659
+ function estimateParagraphContentHeightPx(paragraph, availableWidthPx, numberingDefinitions, docGridLinePitchPx) {
13660
+ if (!paragraphHasImage2(paragraph) && !paragraphHasFormField2(paragraph)) {
13661
+ const lineHeightPx = estimateParagraphLineHeightPx(
13662
+ paragraph,
13663
+ docGridLinePitchPx
13664
+ );
13665
+ const lineCount = paragraphLineCountWithinWidth(
13666
+ paragraph,
13667
+ availableWidthPx,
13668
+ numberingDefinitions
13669
+ );
13670
+ return Math.max(1, lineHeightPx * Math.max(1, lineCount));
13671
+ }
13672
+ return Math.max(
13673
+ 1,
13674
+ estimateParagraphHeightPx(
13675
+ paragraph,
13676
+ availableWidthPx,
13677
+ numberingDefinitions,
13678
+ docGridLinePitchPx
13679
+ ) - paragraphBeforeSpacingPx(paragraph) - paragraphAfterSpacingPx(paragraph)
13680
+ );
13681
+ }
13682
+ function projectParagraphConsumedHeightWithExplicitColumnBreaks(paragraphSegments, pageConsumedHeightPx, pageContentHeightPx, sectionFlowOriginPx, columnCount, availableWidthPx, beforeSpacingPx, afterSpacingPx, collapsedMarginPx, numberingDefinitions, docGridLinePitchPx) {
13683
+ if (paragraphSegments.length <= 1 || columnCount <= 1) {
13684
+ return void 0;
13685
+ }
13686
+ const normalizedParagraphStartPx = Math.max(
13687
+ 0,
13688
+ Math.max(pageConsumedHeightPx, sectionFlowOriginPx)
13689
+ );
13690
+ const firstSegmentTopSpacingPx = pageConsumedHeightPx > 0 ? Math.max(0, beforeSpacingPx - collapsedMarginPx) : beforeSpacingPx;
13691
+ const tallestSegmentHeightPx = paragraphSegments.reduce(
13692
+ (tallest, segment) => {
13693
+ return Math.max(
13694
+ tallest,
13695
+ estimateParagraphContentHeightPx(
13696
+ segment,
13697
+ availableWidthPx,
13698
+ numberingDefinitions,
13699
+ docGridLinePitchPx
13700
+ )
13701
+ );
13702
+ },
13703
+ 0
13704
+ );
13705
+ const projectedConsumedHeightPx = normalizedParagraphStartPx + firstSegmentTopSpacingPx + tallestSegmentHeightPx + afterSpacingPx;
13706
+ const sectionFlowCapacityPx = Math.max(
13707
+ 0,
13708
+ pageContentHeightPx - sectionFlowOriginPx
13709
+ );
13710
+ const sectionConsumedPx = Math.max(
13711
+ 0,
13712
+ pageConsumedHeightPx - sectionFlowOriginPx
13713
+ );
13714
+ const remainingColumnHeightPx = Math.max(
13715
+ 0,
13716
+ sectionFlowCapacityPx / columnCount - sectionConsumedPx
13717
+ );
13718
+ if (projectedConsumedHeightPx - pageConsumedHeightPx > remainingColumnHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
13719
+ return void 0;
13720
+ }
13721
+ return projectedConsumedHeightPx;
13197
13722
  }
13198
13723
  function buildSyntheticPretextLayoutSource(text, style) {
13199
13724
  return {
@@ -13217,16 +13742,50 @@ function sanitizeRenderedPretextFragmentText(text) {
13217
13742
  return text.replace(/\r\n?|\n/g, "");
13218
13743
  }
13219
13744
  function buildParagraphPretextLayoutItems(paragraph, source) {
13745
+ const cachedItems = paragraphPretextLayoutItemsBySource.get(source);
13746
+ if (cachedItems) {
13747
+ return cachedItems;
13748
+ }
13220
13749
  const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
13221
13750
  const wordBreak = pretextWordBreakModeForText(source.text);
13222
- return source.runs.filter((run) => run.endOffset > run.startOffset).map((run) => ({
13751
+ const items = source.runs.filter((run) => run.endOffset > run.startOffset).map((run) => ({
13223
13752
  text: run.text,
13224
13753
  font: resolveMeasureFont(run.style, paragraphBaseFontPx),
13225
13754
  startOffset: run.startOffset,
13226
13755
  endOffset: run.endOffset,
13227
- break: run.kind === "image" ? "never" : "normal",
13756
+ break: run.kind === "image" || run.kind === "tab" ? "never" : "normal",
13228
13757
  wordBreak
13229
13758
  }));
13759
+ paragraphPretextLayoutItemsBySource.set(source, items);
13760
+ return items;
13761
+ }
13762
+ function resolveUniformPretextSourceFont(paragraph, source) {
13763
+ const cachedUniformFont = paragraphPretextUniformFontBySource.get(source);
13764
+ if (cachedUniformFont !== void 0) {
13765
+ return cachedUniformFont ?? void 0;
13766
+ }
13767
+ const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
13768
+ let uniformFont;
13769
+ for (const run of source.runs) {
13770
+ if (run.endOffset <= run.startOffset) {
13771
+ continue;
13772
+ }
13773
+ if (run.kind !== "text") {
13774
+ paragraphPretextUniformFontBySource.set(source, null);
13775
+ return void 0;
13776
+ }
13777
+ const runFont = resolveMeasureFont(run.style, paragraphBaseFontPx);
13778
+ if (uniformFont === void 0) {
13779
+ uniformFont = runFont;
13780
+ continue;
13781
+ }
13782
+ if (runFont !== uniformFont) {
13783
+ paragraphPretextUniformFontBySource.set(source, null);
13784
+ return void 0;
13785
+ }
13786
+ }
13787
+ paragraphPretextUniformFontBySource.set(source, uniformFont ?? null);
13788
+ return uniformFont;
13230
13789
  }
13231
13790
  function buildMeasureSegmentsPretextLayoutItems(segments, paragraphBaseFontPx, text) {
13232
13791
  const wordBreak = pretextWordBreakModeForText(text);
@@ -14013,6 +14572,31 @@ function paragraphStartsWithLastRenderedPageBreak(paragraph) {
14013
14572
  ).replace(/<\/?w:(?:ins|smartTag)\b[^>]*>/gi, "").replace(/\s+/g, "");
14014
14573
  return leadingXml.length === 0;
14015
14574
  }
14575
+ function shouldHonorParagraphStartLastRenderedPageBreak(params) {
14576
+ const pageConsumedHeightPx = Math.max(
14577
+ 0,
14578
+ Math.round(params.pageConsumedHeightPx)
14579
+ );
14580
+ const pageContentHeightPx = Math.max(
14581
+ 0,
14582
+ Math.round(params.pageContentHeightPx)
14583
+ );
14584
+ if (pageConsumedHeightPx <= 0 || pageContentHeightPx <= 0) {
14585
+ return false;
14586
+ }
14587
+ const remainingHeightPx = Math.max(
14588
+ 0,
14589
+ pageContentHeightPx - pageConsumedHeightPx
14590
+ );
14591
+ const maxAllowedRemainingHeightPx = clampNumber(
14592
+ Math.round(
14593
+ pageContentHeightPx * LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_RATIO
14594
+ ),
14595
+ LAST_RENDERED_PAGE_BREAK_HINT_MIN_REMAINING_SPACE_PX,
14596
+ LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_PX
14597
+ );
14598
+ return remainingHeightPx <= maxAllowedRemainingHeightPx;
14599
+ }
14016
14600
  function isOnOffTagEnabled2(tagXml) {
14017
14601
  if (!tagXml) {
14018
14602
  return false;
@@ -14156,7 +14740,8 @@ function sectionBreakAfterParagraphStartsNewPage(paragraph) {
14156
14740
  if (cached) {
14157
14741
  return cached.sectionBreakStartsNewPage;
14158
14742
  }
14159
- return paragraphHasExplicitPageBreak2(paragraph) ? paragraphBreakFlagsBySourceXml.get(xml)?.sectionBreakStartsNewPage ?? false : false;
14743
+ paragraphHasExplicitPageBreak2(paragraph);
14744
+ return paragraphBreakFlagsBySourceXml.get(xml)?.sectionBreakStartsNewPage ?? false;
14160
14745
  }
14161
14746
  function nodeAlreadyEndsAtExplicitPageBoundary(node) {
14162
14747
  if (!node || node.type !== "paragraph") {
@@ -14396,6 +14981,10 @@ function singleLineAutoScaleForFontFamily(fontFamily) {
14396
14981
  }
14397
14982
  return WORD_SINGLE_LINE_AUTO_SCALE;
14398
14983
  }
14984
+ function resolveParagraphSingleLineAutoScale(paragraph, fontFamily) {
14985
+ const baseScale = singleLineAutoScaleForFontFamily(fontFamily);
14986
+ return paragraphHasCheckboxFormField(paragraph) ? Math.max(1.08, baseScale) : baseScale;
14987
+ }
14399
14988
  function paragraphContainsExplicitLineBreakText(paragraph) {
14400
14989
  return paragraph.children.some(
14401
14990
  (child) => child.type === "text" && /[\r\n]/.test(child.text)
@@ -14484,6 +15073,23 @@ function resolveParagraphTabStopsPx(paragraph) {
14484
15073
  ).map((value) => Math.round(value)).sort((left, right) => left - right);
14485
15074
  return stopsPx;
14486
15075
  }
15076
+ function resolveParagraphFirstLineOriginPx(paragraph) {
15077
+ const leftIndentPx = twipsToSignedPixels(paragraph.style?.indent?.leftTwips);
15078
+ const firstLineIndentPx = twipsToSignedPixels(
15079
+ paragraph.style?.indent?.firstLineTwips
15080
+ );
15081
+ const hangingIndentPx = twipsToSignedPixels(
15082
+ paragraph.style?.indent?.hangingTwips
15083
+ );
15084
+ const textIndentPx = firstLineIndentPx ?? (Number.isFinite(hangingIndentPx) ? -hangingIndentPx : 0);
15085
+ return (Number.isFinite(leftIndentPx) ? leftIndentPx : 0) + (Number.isFinite(textIndentPx) ? textIndentPx : 0);
15086
+ }
15087
+ function resolveParagraphFirstLineLeftTabStopsPx(paragraph) {
15088
+ const firstLineOriginPx = resolveParagraphFirstLineOriginPx(paragraph);
15089
+ return (paragraph.style?.tabStops ?? []).filter((tabStop) => tabStop.alignment !== "right").map((tabStop) => twipsToPixels(tabStop.positionTwips)).filter(
15090
+ (value) => Number.isFinite(value) && value > firstLineOriginPx + 0.5
15091
+ ).map((value) => Math.round(value - firstLineOriginPx)).sort((left, right) => left - right);
15092
+ }
14487
15093
  function resolveNextTabStopPx(currentLineWidthPx, tabStopsPx) {
14488
15094
  const nextExplicit = tabStopsPx.find(
14489
15095
  (stopPx) => stopPx > currentLineWidthPx + 0.5
@@ -14717,6 +15323,21 @@ function estimateWrappedLineCountForParagraph(paragraph, availableWidthPx) {
14717
15323
  if (!pretextSource) {
14718
15324
  return void 0;
14719
15325
  }
15326
+ const uniformFont = resolveUniformPretextSourceFont(
15327
+ paragraph,
15328
+ pretextSource
15329
+ );
15330
+ if (uniformFont !== void 0) {
15331
+ const fastLineCount = measurePretextPlainTextLineCount(
15332
+ pretextSource.text,
15333
+ uniformFont,
15334
+ maxLineWidthPx,
15335
+ { wordBreak: pretextWordBreakModeForText(pretextSource.text) }
15336
+ );
15337
+ if (fastLineCount !== void 0) {
15338
+ return fastLineCount;
15339
+ }
15340
+ }
14720
15341
  const lineHeightPx = estimateParagraphLineHeightPx(paragraph);
14721
15342
  const layout = layoutParagraphPretextSource(
14722
15343
  paragraph,
@@ -14971,6 +15592,58 @@ function wrappedPretextParagraphBlockHeightPx(layout) {
14971
15592
  }
14972
15593
  return Math.max(1, Math.round(layout.height));
14973
15594
  }
15595
+ function resolvePretextLineRangeContentHeightPx(layout, startLineIndex, endLineIndex) {
15596
+ if (layout.lines.length === 0) {
15597
+ return 0;
15598
+ }
15599
+ const lineHeightPx = Math.max(1, Math.round(layout.lineHeightPx ?? 1));
15600
+ const safeStart = Math.max(
15601
+ 0,
15602
+ Math.min(Math.round(startLineIndex), layout.lines.length)
15603
+ );
15604
+ const safeEnd = Math.max(
15605
+ safeStart,
15606
+ Math.min(Math.round(endLineIndex), layout.lines.length)
15607
+ );
15608
+ if (safeEnd <= safeStart) {
15609
+ return 0;
15610
+ }
15611
+ const firstLineTopPx = layout.lines[safeStart]?.y ?? safeStart * lineHeightPx;
15612
+ const lastLineTopPx = layout.lines[safeEnd - 1]?.y ?? (safeEnd - 1) * lineHeightPx;
15613
+ return Math.max(1, Math.round(lastLineTopPx - firstLineTopPx + lineHeightPx));
15614
+ }
15615
+ function resolveMaxPretextLineRangeEndIndexThatFits(layout, startLineIndex, maxEndLineIndex, availableHeightPx) {
15616
+ const safeStart = Math.max(
15617
+ 0,
15618
+ Math.min(Math.round(startLineIndex), layout.lines.length)
15619
+ );
15620
+ const safeMaxEnd = Math.max(
15621
+ safeStart,
15622
+ Math.min(Math.round(maxEndLineIndex), layout.lines.length)
15623
+ );
15624
+ const safeAvailableHeightPx = Math.max(0, Math.round(availableHeightPx));
15625
+ if (safeAvailableHeightPx <= 0 || safeMaxEnd <= safeStart) {
15626
+ return safeStart;
15627
+ }
15628
+ let low = safeStart;
15629
+ let high = safeMaxEnd;
15630
+ let bestEnd = safeStart;
15631
+ while (low <= high) {
15632
+ const mid = Math.floor((low + high) / 2);
15633
+ const candidateHeightPx = resolvePretextLineRangeContentHeightPx(
15634
+ layout,
15635
+ safeStart,
15636
+ mid
15637
+ );
15638
+ if (candidateHeightPx <= safeAvailableHeightPx) {
15639
+ bestEnd = mid;
15640
+ low = mid + 1;
15641
+ continue;
15642
+ }
15643
+ high = mid - 1;
15644
+ }
15645
+ return bestEnd;
15646
+ }
14974
15647
  function estimateAbsoluteFloatingImageFootprintPx(paragraph, image) {
14975
15648
  if (!shouldRenderAbsoluteFloatingImage(image)) {
14976
15649
  return 0;
@@ -15010,10 +15683,7 @@ function resolveAutoLineSpacingMultiple(lineTwips, fallbackMultiple) {
15010
15683
  function autoLineHeightScaleForMultiple(multiple, singleLineScale) {
15011
15684
  const safeSingleLineScale = Math.max(
15012
15685
  MIN_AUTO_LINE_MULTIPLE,
15013
- Math.min(
15014
- 1,
15015
- Number.isFinite(singleLineScale) ? singleLineScale : WORD_SINGLE_LINE_AUTO_SCALE
15016
- )
15686
+ Number.isFinite(singleLineScale) ? singleLineScale : WORD_SINGLE_LINE_AUTO_SCALE
15017
15687
  );
15018
15688
  if (!Number.isFinite(multiple)) {
15019
15689
  return safeSingleLineScale;
@@ -15029,9 +15699,9 @@ function autoLineHeightScaleForMultiple(multiple, singleLineScale) {
15029
15699
  (safeSingleLineScale + (1 - safeSingleLineScale) * blendProgress).toFixed(4)
15030
15700
  );
15031
15701
  }
15032
- function calibrateAutoLineSpacingMultiple(multiple, fontFamily) {
15702
+ function calibrateAutoLineSpacingMultiple(multiple, fontFamily, singleLineScaleOverride) {
15033
15703
  const normalizedMultiple = Math.max(MIN_AUTO_LINE_MULTIPLE, multiple);
15034
- const singleLineScale = singleLineAutoScaleForFontFamily(fontFamily);
15704
+ const singleLineScale = singleLineScaleOverride ?? singleLineAutoScaleForFontFamily(fontFamily);
15035
15705
  return Math.max(
15036
15706
  MIN_AUTO_LINE_MULTIPLE,
15037
15707
  Number(
@@ -15075,13 +15745,18 @@ function estimateParagraphLineHeightPx(paragraph, docGridLinePitchPx, disableDoc
15075
15745
  );
15076
15746
  const baseFontPx = paragraphBaseFontSizePx(paragraph);
15077
15747
  const baseFontFamily = paragraphDominantFontFamily(paragraph);
15748
+ const singleLineScale = resolveParagraphSingleLineAutoScale(
15749
+ paragraph,
15750
+ baseFontFamily
15751
+ );
15078
15752
  const defaultLineMultiple = isTableOfContentsParagraph(paragraph) ? 1.05 : DEFAULT_PARAGRAPH_LINE_MULTIPLE;
15079
15753
  const normalLineHeightPx = Math.max(
15080
15754
  1,
15081
15755
  Math.round(
15082
15756
  baseFontPx * calibrateAutoLineSpacingMultiple(
15083
15757
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
15084
- baseFontFamily
15758
+ baseFontFamily,
15759
+ singleLineScale
15085
15760
  )
15086
15761
  )
15087
15762
  );
@@ -15098,7 +15773,8 @@ function estimateParagraphLineHeightPx(paragraph, docGridLinePitchPx, disableDoc
15098
15773
  }
15099
15774
  const multiple = calibrateAutoLineSpacingMultiple(
15100
15775
  resolveAutoLineSpacingMultiple(lineTwips, defaultLineMultiple),
15101
- baseFontFamily
15776
+ baseFontFamily,
15777
+ singleLineScale
15102
15778
  );
15103
15779
  const autoLineHeightPx = Math.max(1, Math.round(baseFontPx * multiple));
15104
15780
  const minimumReadableAutoLineHeightPx = paragraph.style?.numbering ? Math.ceil(baseFontPx) : 0;
@@ -15264,14 +15940,17 @@ function suppressFirstTableCellParagraphTopSpacing(paragraph) {
15264
15940
  }
15265
15941
  function estimateTableCellContentHeightPx(nodeContent, availableWidthPx, numberingDefinitions, applyWordTableDefaults = false, docGridLinePitchPx) {
15266
15942
  let paragraphIndex = 0;
15267
- return nodeContent.reduce((sum, contentNode) => {
15943
+ let expandedWithPretextLayout = false;
15944
+ let totalHeightPx = 0;
15945
+ for (const contentNode of nodeContent) {
15268
15946
  if (!isParagraphCellContentNode(contentNode)) {
15269
- return sum + estimateTableHeightPx(
15947
+ totalHeightPx += estimateTableHeightPx(
15270
15948
  contentNode,
15271
15949
  availableWidthPx,
15272
15950
  numberingDefinitions,
15273
15951
  docGridLinePitchPx
15274
15952
  );
15953
+ continue;
15275
15954
  }
15276
15955
  const disableDocGridSnap = paragraphDocGridSnapState(contentNode) === "disable";
15277
15956
  const paragraphForLayout = wordLikeTableCellParagraph(
@@ -15285,14 +15964,55 @@ function estimateTableCellContentHeightPx(nodeContent, availableWidthPx, numberi
15285
15964
  docGridLinePitchPx,
15286
15965
  disableDocGridSnap
15287
15966
  );
15967
+ const lineHeightPx = Math.max(
15968
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
15969
+ estimateParagraphLineHeightPx(
15970
+ paragraphForLayout,
15971
+ docGridLinePitchPx,
15972
+ disableDocGridSnap
15973
+ )
15974
+ );
15975
+ const pretextSource = buildParagraphPretextLayoutSource(
15976
+ paragraphForLayout,
15977
+ {
15978
+ allowExplicitLineBreakText: true,
15979
+ expandTabsForLayout: true
15980
+ }
15981
+ );
15982
+ const paragraphTextWidthPx = typeof availableWidthPx === "number" && availableWidthPx > 0 ? paragraphAvailableTextWidthPx(
15983
+ paragraphForLayout,
15984
+ availableWidthPx,
15985
+ numberingDefinitions
15986
+ ) : void 0;
15987
+ const pretextLayout = pretextSource && typeof paragraphTextWidthPx === "number" && paragraphTextWidthPx > 0 ? layoutParagraphPretextSource(
15988
+ paragraphForLayout,
15989
+ pretextSource,
15990
+ paragraphTextWidthPx,
15991
+ lineHeightPx,
15992
+ []
15993
+ ) : void 0;
15288
15994
  const suppressTopSpacing = paragraphIndex === 0 && suppressFirstTableCellParagraphTopSpacing(contentNode);
15289
15995
  paragraphIndex += 1;
15996
+ const beforeSpacing = suppressTopSpacing ? 0 : twipsToPixels(paragraphForLayout.style?.spacing?.beforeTwips) ?? 0;
15997
+ const afterSpacing = twipsToPixels(paragraphForLayout.style?.spacing?.afterTwips) ?? 0;
15998
+ const topBorderInsetPx = paragraphBorderInsetPx(
15999
+ paragraphForLayout.style?.borders?.top
16000
+ );
16001
+ const bottomBorderInsetPx = paragraphBorderInsetPx(
16002
+ paragraphForLayout.style?.borders?.bottom
16003
+ );
16004
+ const pretextHeightPx = pretextLayout ? beforeSpacing + afterSpacing + topBorderInsetPx + bottomBorderInsetPx + wrappedPretextParagraphBlockHeightPx(pretextLayout) : 0;
16005
+ const resolvedBaseHeight = pretextHeightPx > 0 ? Math.max(baseHeight, pretextHeightPx) : baseHeight;
16006
+ if (pretextHeightPx > baseHeight) {
16007
+ expandedWithPretextLayout = true;
16008
+ }
15290
16009
  if (!suppressTopSpacing) {
15291
- return sum + baseHeight;
16010
+ totalHeightPx += resolvedBaseHeight;
16011
+ continue;
15292
16012
  }
15293
- const beforeSpacing = twipsToPixels(paragraphForLayout.style?.spacing?.beforeTwips) ?? 0;
15294
- return sum + Math.max(1, baseHeight - beforeSpacing);
15295
- }, 0);
16013
+ totalHeightPx += Math.max(1, resolvedBaseHeight - beforeSpacing);
16014
+ }
16015
+ return totalHeightPx + (expandedWithPretextLayout ? Math.max(1, MIN_PARAGRAPH_LINE_HEIGHT_PX) : 0);
15296
16016
  }
15297
16017
  function rowAllowsPageSplit(row) {
15298
16018
  return row.style?.cantSplit !== true && row.style?.heightRule !== "exact";
@@ -15310,7 +16030,7 @@ function rowHasDeepFlowContent(row) {
15310
16030
  }
15311
16031
  return nestedTableCount > 0 || blockNodeCount >= SPLITTABLE_TABLE_ROW_DEEP_CONTENT_NODE_THRESHOLD;
15312
16032
  }
15313
- function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitHeightPx) {
16033
+ function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitHeightPx, pageContentHeightPx) {
15314
16034
  if (!rowAllowsPageSplit(row)) {
15315
16035
  return estimatedRowHeightPx;
15316
16036
  }
@@ -15324,6 +16044,13 @@ function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitH
15324
16044
  MIN_PARAGRAPH_LINE_HEIGHT_PX * 2,
15325
16045
  Math.round(explicitHeightPx)
15326
16046
  );
16047
+ const safePageContentHeightPx = Number.isFinite(pageContentHeightPx) && pageContentHeightPx > 0 ? Math.max(
16048
+ MIN_PARAGRAPH_LINE_HEIGHT_PX * 4,
16049
+ Math.round(pageContentHeightPx)
16050
+ ) : void 0;
16051
+ if (safePageContentHeightPx !== void 0 && estimatedRowHeightPx > safePageContentHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
16052
+ return estimatedRowHeightPx;
16053
+ }
15327
16054
  const cappedHeightPx = safeExplicitHeightPx + MIN_PARAGRAPH_LINE_HEIGHT_PX * SPLITTABLE_TABLE_ROW_ESTIMATE_EXTRA_LINE_COUNT;
15328
16055
  return Math.min(estimatedRowHeightPx, cappedHeightPx);
15329
16056
  }
@@ -15361,7 +16088,7 @@ function tableUsesWordLikeParagraphDefaults(table) {
15361
16088
  }
15362
16089
  return table.style?.layout === "fixed" && tableHasVisibleBorders(table) && tableContainsParagraphsWithoutExplicitSpacing(table);
15363
16090
  }
15364
- function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx) {
16091
+ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx, pageContentHeightPx) {
15365
16092
  const defaultCellMargin = table.style?.cellMarginTwips;
15366
16093
  const columnCount = tableColumnCount(table);
15367
16094
  const tableWidthPx = twipsToPixels(table.style?.widthTwips);
@@ -15379,7 +16106,11 @@ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefiniti
15379
16106
  return normalizeColumnWidthsPx(widthsPx, columnCount, tableWidthPx, 1);
15380
16107
  })();
15381
16108
  const rawResolvedTableWidthPx = tableWidthPx ?? rawTableColumnWidthsPx.reduce((sum, widthPx) => sum + widthPx, 0);
15382
- const maxTableWidthPx = Number.isFinite(maxAvailableWidthPx) && maxAvailableWidthPx > 0 ? Math.max(120, maxAvailableWidthPx) : void 0;
16109
+ const collapsedHorizontalBorderBleedPx = resolveCollapsedTableHorizontalOuterBleedPx(table, columnCount);
16110
+ const maxTableWidthPx = Number.isFinite(maxAvailableWidthPx) && maxAvailableWidthPx > 0 ? Math.max(
16111
+ 120,
16112
+ maxAvailableWidthPx - collapsedHorizontalBorderBleedPx
16113
+ ) : void 0;
15383
16114
  const resolvedTableWidthPx = clampTableWidthPx(
15384
16115
  rawResolvedTableWidthPx,
15385
16116
  maxTableWidthPx
@@ -15426,7 +16157,8 @@ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefiniti
15426
16157
  rowHeightPx = capSplitFriendlyTableRowEstimatePx(
15427
16158
  row,
15428
16159
  rowHeightPx,
15429
- explicitHeightPx
16160
+ explicitHeightPx,
16161
+ pageContentHeightPx
15430
16162
  );
15431
16163
  return Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, rowHeightPx);
15432
16164
  });
@@ -15527,6 +16259,45 @@ function paragraphSegmentHasPartialLineRange(paragraphLineRange) {
15527
16259
  }
15528
16260
  return paragraphLineRange.startLineIndex > 0 || paragraphLineRange.endLineIndex < paragraphLineRange.totalLineCount;
15529
16261
  }
16262
+ function resolveLineRangeWithinVerticalSlice(lineTopOffsetsPx, lineHeightPx, sliceTopPx, sliceBottomPx) {
16263
+ if (lineTopOffsetsPx.length === 0 || !Number.isFinite(lineHeightPx) || lineHeightPx <= 0) {
16264
+ return void 0;
16265
+ }
16266
+ const safeSliceTopPx = Math.max(0, sliceTopPx);
16267
+ const safeSliceBottomPx = Math.max(safeSliceTopPx, sliceBottomPx);
16268
+ const sliceHasHeight = safeSliceBottomPx > safeSliceTopPx;
16269
+ let startLineIndex;
16270
+ let endLineIndex;
16271
+ for (let lineIndex = 0; lineIndex < lineTopOffsetsPx.length; lineIndex += 1) {
16272
+ const lineTopPx = lineTopOffsetsPx[lineIndex] ?? lineIndex * lineHeightPx;
16273
+ const lineBottomPx = lineTopPx + lineHeightPx;
16274
+ const lineBelongsToSlice = sliceHasHeight && lineBottomPx > safeSliceTopPx + PAGE_OVERFLOW_TOLERANCE_PX && lineBottomPx <= safeSliceBottomPx + PAGE_OVERFLOW_TOLERANCE_PX;
16275
+ if (lineBelongsToSlice) {
16276
+ if (startLineIndex === void 0) {
16277
+ startLineIndex = lineIndex;
16278
+ }
16279
+ endLineIndex = lineIndex + 1;
16280
+ }
16281
+ }
16282
+ if (startLineIndex === void 0 || endLineIndex === void 0 || endLineIndex <= startLineIndex) {
16283
+ return void 0;
16284
+ }
16285
+ return {
16286
+ startLineIndex,
16287
+ endLineIndex,
16288
+ totalLineCount: lineTopOffsetsPx.length,
16289
+ lineHeightPx
16290
+ };
16291
+ }
16292
+ function resolveTableCellParagraphVisualBottomPx(params) {
16293
+ return Math.max(
16294
+ Math.round(params.paragraphTopPx + params.paragraphHeightPx),
16295
+ Math.round(params.textBottomPx)
16296
+ );
16297
+ }
16298
+ function tableCellParagraphFitsFullyWithinSlice(params) {
16299
+ 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;
16300
+ }
15530
16301
  function resolveParagraphSegmentClipBleedPx(paragraphLineRange) {
15531
16302
  if (!paragraphSegmentHasPartialLineRange(paragraphLineRange)) {
15532
16303
  return {
@@ -15536,7 +16307,7 @@ function resolveParagraphSegmentClipBleedPx(paragraphLineRange) {
15536
16307
  }
15537
16308
  return {
15538
16309
  topPx: paragraphLineRange && paragraphLineRange.startLineIndex > 0 ? Math.max(0, PARAGRAPH_SEGMENT_TOP_BLEED_PX) : 0,
15539
- bottomPx: Math.max(0, PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX)
16310
+ bottomPx: paragraphLineRange && paragraphLineRange.endLineIndex < paragraphLineRange.totalLineCount ? Math.max(0, PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX) : 0
15540
16311
  };
15541
16312
  }
15542
16313
  function resolveFallbackParagraphSegmentClipBleedPx(paragraph, paragraphLineRange) {
@@ -15610,12 +16381,32 @@ function estimateRenderedPageSegmentHeightPx(node, segment, model, availableWidt
15610
16381
  false
15611
16382
  ) : 0;
15612
16383
  const afterSpacingPx = paragraphLineRange.endLineIndex >= paragraphLineRange.totalLineCount ? effectiveParagraphAfterSpacingPx(model, segment.nodeIndex, node) : 0;
16384
+ const paragraphPretextSource = buildParagraphPretextLayoutSource(node, {
16385
+ allowExplicitLineBreakText: true,
16386
+ expandTabsForLayout: true
16387
+ });
16388
+ const paragraphPretextLayout = paragraphPretextSource ? layoutParagraphPretextSource(
16389
+ node,
16390
+ paragraphPretextSource,
16391
+ paragraphAvailableTextWidthPx(
16392
+ node,
16393
+ availableWidthPx,
16394
+ numberingDefinitions
16395
+ ),
16396
+ Math.max(1, paragraphLineRange.lineHeightPx),
16397
+ []
16398
+ ) : void 0;
16399
+ const segmentContentHeightPx = paragraphPretextLayout && paragraphPretextLayout.lineCount > 0 ? resolvePretextLineRangeContentHeightPx(
16400
+ paragraphPretextLayout,
16401
+ paragraphLineRange.startLineIndex,
16402
+ paragraphLineRange.endLineIndex
16403
+ ) : Math.max(
16404
+ 1,
16405
+ paragraphLineRange.endLineIndex - paragraphLineRange.startLineIndex
16406
+ ) * Math.max(1, paragraphLineRange.lineHeightPx);
15613
16407
  return Math.max(
15614
16408
  1,
15615
- beforeSpacingPx + Math.max(
15616
- 1,
15617
- paragraphLineRange.endLineIndex - paragraphLineRange.startLineIndex
15618
- ) * Math.max(1, paragraphLineRange.lineHeightPx) + afterSpacingPx
16409
+ beforeSpacingPx + segmentContentHeightPx + afterSpacingPx
15619
16410
  );
15620
16411
  }
15621
16412
  return Math.max(
@@ -15756,6 +16547,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15756
16547
  let pageConsumedHeightPx = 0;
15757
16548
  let previousParagraphAfterPx = 0;
15758
16549
  let currentMetricsIndex = 0;
16550
+ let currentSectionPageFlowOriginPx = 0;
15759
16551
  let currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15760
16552
  0,
15761
16553
  metricsBySection[0]
@@ -15797,11 +16589,13 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15797
16589
  currentPageIndex,
15798
16590
  nodeMetrics
15799
16591
  );
16592
+ currentSectionPageFlowOriginPx = pageConsumedHeightPx;
15800
16593
  }
15801
16594
  if (hardBreakStartNodeIndexes.has(nodeIndex) && currentPageSegments.length > 0) {
15802
16595
  startNextPage();
15803
16596
  pageConsumedHeightPx = 0;
15804
16597
  previousParagraphAfterPx = 0;
16598
+ currentSectionPageFlowOriginPx = 0;
15805
16599
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15806
16600
  currentPageIndex,
15807
16601
  nodeMetrics
@@ -15856,6 +16650,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15856
16650
  startNextPage();
15857
16651
  pageConsumedHeightPx = 0;
15858
16652
  previousParagraphAfterPx = 0;
16653
+ currentSectionPageFlowOriginPx = 0;
15859
16654
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15860
16655
  currentPageIndex,
15861
16656
  nodeMetrics
@@ -15865,15 +16660,20 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15865
16660
  startNextPage();
15866
16661
  pageConsumedHeightPx = 0;
15867
16662
  previousParagraphAfterPx = 0;
16663
+ currentSectionPageFlowOriginPx = 0;
15868
16664
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15869
16665
  currentPageIndex,
15870
16666
  nodeMetrics
15871
16667
  );
15872
16668
  }
15873
- if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak(node) && !nodeAlreadyEndsAtExplicitPageBoundary(model.nodes[nodeIndex - 1]) && currentPageSegments.length > 0) {
16669
+ if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak(node) && shouldHonorParagraphStartLastRenderedPageBreak({
16670
+ pageConsumedHeightPx,
16671
+ pageContentHeightPx: currentPageContentHeightPx
16672
+ }) && !nodeAlreadyEndsAtExplicitPageBoundary(model.nodes[nodeIndex - 1]) && currentPageSegments.length > 0) {
15874
16673
  startNextPage();
15875
16674
  pageConsumedHeightPx = 0;
15876
16675
  previousParagraphAfterPx = 0;
16676
+ currentSectionPageFlowOriginPx = 0;
15877
16677
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15878
16678
  currentPageIndex,
15879
16679
  nodeMetrics
@@ -15893,7 +16693,36 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15893
16693
  nodeIndex,
15894
16694
  node
15895
16695
  );
15896
- const rawNodeHeightPx = Math.max(
16696
+ const paragraphLineHeightPx = estimateParagraphLineHeightPx(
16697
+ node,
16698
+ nodeMetrics.docGridLinePitchPx
16699
+ );
16700
+ const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
16701
+ node,
16702
+ nodeMetrics.pageContentWidthPx,
16703
+ numberingDefinitions
16704
+ );
16705
+ const paragraphPretextSourceForSegmentRendering = buildParagraphPretextLayoutSource(node, {
16706
+ allowExplicitLineBreakText: true,
16707
+ expandTabsForLayout: true
16708
+ });
16709
+ let paragraphPretextLayoutForSegmentRendering;
16710
+ let paragraphPretextLayoutForSegmentRenderingResolved = false;
16711
+ const resolveParagraphPretextLayoutForSegmentRendering = () => {
16712
+ if (paragraphPretextLayoutForSegmentRenderingResolved) {
16713
+ return paragraphPretextLayoutForSegmentRendering;
16714
+ }
16715
+ paragraphPretextLayoutForSegmentRenderingResolved = true;
16716
+ paragraphPretextLayoutForSegmentRendering = paragraphPretextSourceForSegmentRendering ? layoutParagraphPretextSource(
16717
+ node,
16718
+ paragraphPretextSourceForSegmentRendering,
16719
+ paragraphTextWidthPx,
16720
+ paragraphLineHeightPx,
16721
+ []
16722
+ ) : void 0;
16723
+ return paragraphPretextLayoutForSegmentRendering;
16724
+ };
16725
+ let rawNodeHeightPx = Math.max(
15897
16726
  1,
15898
16727
  estimateParagraphHeightPx(
15899
16728
  node,
@@ -15917,6 +16746,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15917
16746
  startNextPage();
15918
16747
  pageConsumedHeightPx = 0;
15919
16748
  previousParagraphAfterPx = 0;
16749
+ currentSectionPageFlowOriginPx = 0;
15920
16750
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15921
16751
  currentPageIndex,
15922
16752
  nodeMetrics
@@ -15927,38 +16757,33 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15927
16757
  1,
15928
16758
  Math.max(rawNodeHeightPx, coverFootprintPx) - collapsedMarginPx
15929
16759
  );
15930
- const paragraphLineHeightPx = estimateParagraphLineHeightPx(
15931
- node,
15932
- nodeMetrics.docGridLinePitchPx
15933
- );
15934
- const paragraphPretextSourceForSegmentRendering = buildParagraphPretextLayoutSource(node, {
15935
- allowExplicitLineBreakText: true
15936
- });
15937
16760
  const paragraphSupportsPretextSegmentRendering = Boolean(
15938
16761
  paragraphPretextSourceForSegmentRendering
15939
16762
  );
15940
- const paragraphPretextLineCount = (() => {
15941
- if (!paragraphContainsExplicitLineBreakText(node)) {
15942
- return void 0;
15943
- }
15944
- const pretextSource = paragraphPretextSourceForSegmentRendering;
15945
- if (!pretextSource) {
15946
- return void 0;
16763
+ const remainingHeightBeforeParagraphPx = Math.max(
16764
+ 0,
16765
+ currentPageContentHeightPx - pageConsumedHeightPx
16766
+ );
16767
+ if (paragraphSupportsPretextSegmentRendering && remainingHeightBeforeParagraphPx <= collapsedNodeHeightPx + paragraphLineHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
16768
+ const pretextLayout = resolveParagraphPretextLayoutForSegmentRendering();
16769
+ const pretextContentHeightPx = pretextLayout ? wrappedPretextParagraphBlockHeightPx(pretextLayout) : void 0;
16770
+ if (Number.isFinite(pretextContentHeightPx)) {
16771
+ rawNodeHeightPx = Math.max(
16772
+ rawNodeHeightPx,
16773
+ Math.max(
16774
+ 1,
16775
+ Math.round(
16776
+ beforeSpacingPx + pretextContentHeightPx + afterSpacingPx
16777
+ )
16778
+ )
16779
+ );
15947
16780
  }
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
- })();
16781
+ }
16782
+ const collapsedNodeHeightPxAdjusted = Math.max(
16783
+ 1,
16784
+ Math.max(rawNodeHeightPx, coverFootprintPx) - collapsedMarginPx
16785
+ );
16786
+ const paragraphPretextLineCount = paragraphContainsExplicitLineBreakText(node) || paragraphContainsTabCharacter(node) ? resolveParagraphPretextLayoutForSegmentRendering()?.lineCount : void 0;
15962
16787
  const supportsImageParagraphLineSplit = paragraphHasImage2(node) && paragraphSupportsPretextSegmentRendering;
15963
16788
  const paragraphLineCount = paragraphLineCountWithinWidth(
15964
16789
  node,
@@ -15966,6 +16791,54 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15966
16791
  numberingDefinitions
15967
16792
  );
15968
16793
  const resolvedParagraphLineCount = Number.isFinite(paragraphPretextLineCount) && paragraphPretextLineCount > 0 ? Math.max(1, Math.round(paragraphPretextLineCount)) : paragraphLineCount;
16794
+ const explicitColumnBreakParagraphSegments = (nodeMetrics.pageContentHeightMultiplier ?? 1) > 1 ? splitParagraphAtExplicitColumnBreaks(node) : void 0;
16795
+ const tryConsumeExplicitColumnBreakParagraph = () => {
16796
+ if (!explicitColumnBreakParagraphSegments || explicitColumnBreakParagraphSegments.length <= 1) {
16797
+ return false;
16798
+ }
16799
+ const projectedConsumedHeightPx = projectParagraphConsumedHeightWithExplicitColumnBreaks(
16800
+ explicitColumnBreakParagraphSegments,
16801
+ pageConsumedHeightPx,
16802
+ currentPageContentHeightPx,
16803
+ currentSectionPageFlowOriginPx,
16804
+ Math.max(
16805
+ 1,
16806
+ Math.round(nodeMetrics.pageContentHeightMultiplier ?? 1)
16807
+ ),
16808
+ nodeMetrics.pageContentWidthPx,
16809
+ beforeSpacingPx,
16810
+ afterSpacingPx,
16811
+ collapsedMarginPx,
16812
+ numberingDefinitions,
16813
+ nodeMetrics.docGridLinePitchPx
16814
+ );
16815
+ if (!Number.isFinite(projectedConsumedHeightPx)) {
16816
+ return false;
16817
+ }
16818
+ currentPageSegments.push({ nodeIndex });
16819
+ pageConsumedHeightPx = Math.max(
16820
+ pageConsumedHeightPx,
16821
+ Math.round(projectedConsumedHeightPx)
16822
+ );
16823
+ previousParagraphAfterPx = afterSpacingPx;
16824
+ return true;
16825
+ };
16826
+ if (tryConsumeExplicitColumnBreakParagraph()) {
16827
+ continue;
16828
+ }
16829
+ if (explicitColumnBreakParagraphSegments && explicitColumnBreakParagraphSegments.length > 1 && pageConsumedHeightPx > 0 && currentPageSegments.length > 0) {
16830
+ startNextPage();
16831
+ pageConsumedHeightPx = 0;
16832
+ previousParagraphAfterPx = 0;
16833
+ currentSectionPageFlowOriginPx = 0;
16834
+ currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16835
+ currentPageIndex,
16836
+ nodeMetrics
16837
+ );
16838
+ if (tryConsumeExplicitColumnBreakParagraph()) {
16839
+ continue;
16840
+ }
16841
+ }
15969
16842
  const widowControlEnabled = paragraphWidowControlEnabled(node);
15970
16843
  const minLinesPerSegment = widowControlEnabled ? 2 : 1;
15971
16844
  const canSplitParagraphAcrossPages = paragraphCanSplitAcrossPages(node, resolvedParagraphLineCount, {
@@ -15974,6 +16847,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15974
16847
  allowImageParagraphSplit: supportsImageParagraphLineSplit
15975
16848
  }) && (!widowControlEnabled || resolvedParagraphLineCount > 3);
15976
16849
  if (canSplitParagraphAcrossPages && allowParagraphLineSplitting) {
16850
+ const pretextLayoutForSegmentSplitting = resolveParagraphPretextLayoutForSegmentRendering();
15977
16851
  const resolveSegmentReservePx = (startLineIndex, endLineIndex) => {
15978
16852
  const paragraphSegmentRange = {
15979
16853
  startLineIndex,
@@ -15986,6 +16860,16 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15986
16860
  paragraphSegmentRange
15987
16861
  );
15988
16862
  };
16863
+ const resolveSegmentContentHeightPx = (startLineIndex, endLineIndex) => {
16864
+ if (pretextLayoutForSegmentSplitting && pretextLayoutForSegmentSplitting.lineCount > 0) {
16865
+ return resolvePretextLineRangeContentHeightPx(
16866
+ pretextLayoutForSegmentSplitting,
16867
+ startLineIndex,
16868
+ endLineIndex
16869
+ );
16870
+ }
16871
+ return Math.max(1, endLineIndex - startLineIndex) * paragraphLineHeightPx;
16872
+ };
15989
16873
  let lineCursor = 0;
15990
16874
  let isFirstSegment = true;
15991
16875
  while (lineCursor < resolvedParagraphLineCount) {
@@ -16001,7 +16885,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16001
16885
  lineCursor,
16002
16886
  resolvedParagraphLineCount
16003
16887
  );
16004
- const allRemainingHeightPx = topSpacingPx + linesRemaining * paragraphLineHeightPx + bottomSpacingPx;
16888
+ const allRemainingHeightPx = topSpacingPx + resolveSegmentContentHeightPx(
16889
+ lineCursor,
16890
+ resolvedParagraphLineCount
16891
+ ) + bottomSpacingPx;
16005
16892
  if (allRemainingHeightPx + allRemainingSegmentReservePx <= remainingHeightPx2) {
16006
16893
  currentPageSegments.push({
16007
16894
  nodeIndex,
@@ -16033,11 +16920,27 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16033
16920
  availableForLinesPx / paragraphLineHeightPx
16034
16921
  );
16035
16922
  linesThatFit = Math.min(linesThatFit, maxLinesThisPage);
16923
+ if (pretextLayoutForSegmentSplitting && pretextLayoutForSegmentSplitting.lineCount > 0 && linesThatFit > 0) {
16924
+ const exactSegmentEndLineIndex = resolveMaxPretextLineRangeEndIndexThatFits(
16925
+ pretextLayoutForSegmentSplitting,
16926
+ lineCursor,
16927
+ Math.min(
16928
+ resolvedParagraphLineCount,
16929
+ lineCursor + linesThatFit
16930
+ ),
16931
+ availableForLinesPx
16932
+ );
16933
+ linesThatFit = Math.max(
16934
+ 0,
16935
+ exactSegmentEndLineIndex - lineCursor
16936
+ );
16937
+ }
16036
16938
  if (linesThatFit < minLinesPerSegment) {
16037
16939
  if (currentPageSegments.length > 0) {
16038
16940
  startNextPage();
16039
16941
  pageConsumedHeightPx = 0;
16040
16942
  previousParagraphAfterPx = 0;
16943
+ currentSectionPageFlowOriginPx = 0;
16041
16944
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16042
16945
  currentPageIndex,
16043
16946
  nodeMetrics
@@ -16067,7 +16970,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16067
16970
  lineCursor,
16068
16971
  segmentEndLineIndex
16069
16972
  );
16070
- if (topSpacingPx + (segmentEndLineIndex - lineCursor) * paragraphLineHeightPx + segmentReservePx <= remainingHeightPx2) {
16973
+ if (topSpacingPx + resolveSegmentContentHeightPx(
16974
+ lineCursor,
16975
+ segmentEndLineIndex
16976
+ ) + segmentReservePx <= remainingHeightPx2) {
16071
16977
  break;
16072
16978
  }
16073
16979
  linesThatFit -= 1;
@@ -16089,7 +16995,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16089
16995
  lineHeightPx: paragraphLineHeightPx
16090
16996
  }
16091
16997
  });
16092
- pageConsumedHeightPx += topSpacingPx + (safeSegmentEndLineIndex - lineCursor) * paragraphLineHeightPx;
16998
+ pageConsumedHeightPx += topSpacingPx + resolveSegmentContentHeightPx(lineCursor, safeSegmentEndLineIndex);
16093
16999
  previousParagraphAfterPx = 0;
16094
17000
  lineCursor = safeSegmentEndLineIndex;
16095
17001
  isFirstSegment = false;
@@ -16097,6 +17003,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16097
17003
  startNextPage();
16098
17004
  pageConsumedHeightPx = 0;
16099
17005
  previousParagraphAfterPx = 0;
17006
+ currentSectionPageFlowOriginPx = 0;
16100
17007
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16101
17008
  currentPageIndex,
16102
17009
  nodeMetrics
@@ -16105,7 +17012,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16105
17012
  }
16106
17013
  continue;
16107
17014
  }
16108
- let requiredHeightPx = collapsedNodeHeightPx;
17015
+ let requiredHeightPx = collapsedNodeHeightPxAdjusted;
16109
17016
  if (node.style?.keepNext === true && paragraphHasVisibleText2(node)) {
16110
17017
  let chainCursor = nodeIndex;
16111
17018
  let chainPreviousParagraphAfterPx = afterSpacingPx;
@@ -16159,6 +17066,11 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16159
17066
  1,
16160
17067
  nextRawHeightPx - collapsedChainMarginPx
16161
17068
  );
17069
+ requiredHeightPx += keepNextPaginationReservePx(
17070
+ currentChainNode,
17071
+ nextChainNode,
17072
+ chainMetrics.docGridLinePitchPx
17073
+ );
16162
17074
  chainPreviousParagraphAfterPx = nextAfterSpacingPx;
16163
17075
  }
16164
17076
  }
@@ -16196,6 +17108,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16196
17108
  startNextPage();
16197
17109
  pageConsumedHeightPx = 0;
16198
17110
  previousParagraphAfterPx = 0;
17111
+ currentSectionPageFlowOriginPx = 0;
16199
17112
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16200
17113
  currentPageIndex,
16201
17114
  nodeMetrics
@@ -16221,7 +17134,8 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16221
17134
  node,
16222
17135
  nodeMetrics.pageContentWidthPx,
16223
17136
  numberingDefinitions,
16224
- nodeMetrics.docGridLinePitchPx
17137
+ nodeMetrics.docGridLinePitchPx,
17138
+ nodeMetrics.pageContentHeightPx
16225
17139
  );
16226
17140
  if (!measuredRowHeightsPx && !estimatedRowHeightsByTableNodeIndex.has(nodeIndex)) {
16227
17141
  estimatedRowHeightsByTableNodeIndex.set(nodeIndex, estimatedRowHeightsPx);
@@ -16237,14 +17151,45 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16237
17151
  startNextPage();
16238
17152
  pageConsumedHeightPx = 0;
16239
17153
  previousParagraphAfterPx = 0;
17154
+ currentSectionPageFlowOriginPx = 0;
16240
17155
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16241
17156
  currentPageIndex,
16242
17157
  nodeMetrics
16243
17158
  );
16244
17159
  }
17160
+ let headerRunLength = 0;
17161
+ for (const row of node.rows) {
17162
+ if (row.style?.isHeader === true) {
17163
+ headerRunLength += 1;
17164
+ } else {
17165
+ break;
17166
+ }
17167
+ }
17168
+ const headerRunHeightPx = headerRunLength > 0 ? sumEstimatedTableRowHeightsPx(
17169
+ estimatedRowHeightsPx,
17170
+ 0,
17171
+ headerRunLength
17172
+ ) : 0;
17173
+ const canRepeatHeader = headerRunLength > 0 && headerRunHeightPx > 0 && headerRunHeightPx + MIN_PARAGRAPH_LINE_HEIGHT_PX * 2 < currentPageContentHeightPx;
16245
17174
  let rowStartIndex = 0;
16246
17175
  let rowSliceOffsetPx = 0;
17176
+ let repeatedHeaderHeightPxOnThisPage = 0;
16247
17177
  while (rowStartIndex < estimatedRowHeightsPx.length) {
17178
+ if (currentPageSegments.length === 0) {
17179
+ repeatedHeaderHeightPxOnThisPage = 0;
17180
+ }
17181
+ if (canRepeatHeader && rowStartIndex >= headerRunLength && currentPageSegments.length === 0) {
17182
+ currentPageSegments.push({
17183
+ nodeIndex,
17184
+ tableRowRange: {
17185
+ startRowIndex: 0,
17186
+ endRowIndex: headerRunLength
17187
+ }
17188
+ });
17189
+ pageConsumedHeightPx += headerRunHeightPx;
17190
+ previousParagraphAfterPx = 0;
17191
+ repeatedHeaderHeightPxOnThisPage = headerRunHeightPx;
17192
+ }
16248
17193
  const remainingHeightPx = Math.max(
16249
17194
  0,
16250
17195
  currentPageContentHeightPx - pageConsumedHeightPx
@@ -16258,7 +17203,11 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16258
17203
  0,
16259
17204
  currentRowTotalHeightPx - rowSliceOffsetPx
16260
17205
  );
16261
- const rowExceedsFreshPageHeightPx = currentRowTotalHeightPx > currentPageContentHeightPx + PAGE_OVERFLOW_TOLERANCE_PX;
17206
+ const freshPageAvailableHeightPx = Math.max(
17207
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
17208
+ currentPageContentHeightPx - repeatedHeaderHeightPxOnThisPage
17209
+ );
17210
+ const rowExceedsFreshPageHeightPx = currentRowTotalHeightPx > freshPageAvailableHeightPx + PAGE_OVERFLOW_TOLERANCE_PX;
16262
17211
  const canSplitCurrentRow = rowSliceOffsetPx > 0 || rowAllowsPageSplit(currentRow) || rowExceedsFreshPageHeightPx;
16263
17212
  const shouldContinueExistingRowSlice = rowSliceOffsetPx > 0;
16264
17213
  const rowNeedsSliceOnThisPage = ENABLE_TABLE_ROW_SLICING && canSplitCurrentRow && currentRowRemainingHeightPx > remainingHeightPx + PAGE_OVERFLOW_TOLERANCE_PX && (shouldContinueExistingRowSlice || rowExceedsFreshPageHeightPx);
@@ -16266,6 +17215,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16266
17215
  startNextPage();
16267
17216
  pageConsumedHeightPx = 0;
16268
17217
  previousParagraphAfterPx = 0;
17218
+ currentSectionPageFlowOriginPx = 0;
16269
17219
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16270
17220
  currentPageIndex,
16271
17221
  nodeMetrics
@@ -16277,6 +17227,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16277
17227
  startNextPage();
16278
17228
  pageConsumedHeightPx = 0;
16279
17229
  previousParagraphAfterPx = 0;
17230
+ currentSectionPageFlowOriginPx = 0;
16280
17231
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16281
17232
  currentPageIndex,
16282
17233
  nodeMetrics
@@ -16318,6 +17269,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16318
17269
  startNextPage();
16319
17270
  pageConsumedHeightPx = 0;
16320
17271
  previousParagraphAfterPx = 0;
17272
+ currentSectionPageFlowOriginPx = 0;
16321
17273
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16322
17274
  currentPageIndex,
16323
17275
  nodeMetrics
@@ -16326,6 +17278,24 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16326
17278
  continue;
16327
17279
  }
16328
17280
  if (rowSliceOffsetPx > 0) {
17281
+ currentPageSegments.push({
17282
+ nodeIndex,
17283
+ tableRowRange: {
17284
+ startRowIndex: rowStartIndex,
17285
+ endRowIndex: Math.min(
17286
+ estimatedRowHeightsPx.length,
17287
+ rowStartIndex + 1
17288
+ )
17289
+ },
17290
+ tableRowSlice: {
17291
+ rowIndex: rowStartIndex,
17292
+ startOffsetPx: rowSliceOffsetPx,
17293
+ sliceHeightPx: currentRowRemainingHeightPx,
17294
+ totalRowHeightPx: currentRowTotalHeightPx
17295
+ }
17296
+ });
17297
+ pageConsumedHeightPx += currentRowRemainingHeightPx;
17298
+ previousParagraphAfterPx = 0;
16329
17299
  rowStartIndex += 1;
16330
17300
  rowSliceOffsetPx = 0;
16331
17301
  continue;
@@ -16348,6 +17318,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16348
17318
  startNextPage();
16349
17319
  pageConsumedHeightPx = 0;
16350
17320
  previousParagraphAfterPx = 0;
17321
+ currentSectionPageFlowOriginPx = 0;
16351
17322
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16352
17323
  currentPageIndex,
16353
17324
  nodeMetrics
@@ -16378,6 +17349,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16378
17349
  startNextPage();
16379
17350
  pageConsumedHeightPx = 0;
16380
17351
  previousParagraphAfterPx = 0;
17352
+ currentSectionPageFlowOriginPx = 0;
16381
17353
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16382
17354
  currentPageIndex,
16383
17355
  nodeMetrics
@@ -16406,6 +17378,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16406
17378
  startNextPage();
16407
17379
  pageConsumedHeightPx = 0;
16408
17380
  previousParagraphAfterPx = 0;
17381
+ currentSectionPageFlowOriginPx = 0;
16409
17382
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16410
17383
  currentPageIndex,
16411
17384
  nodeMetrics
@@ -16877,6 +17850,10 @@ function resolveHighlightColor(value) {
16877
17850
  }
16878
17851
  function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap = false) {
16879
17852
  const baseFontFamily = paragraphDominantFontFamily(paragraph);
17853
+ const singleLineScale = resolveParagraphSingleLineAutoScale(
17854
+ paragraph,
17855
+ baseFontFamily
17856
+ );
16880
17857
  const lineTwips = paragraph.style?.spacing?.lineTwips;
16881
17858
  const docGridMinimumLineHeightPx = resolveParagraphDocGridLinePitchPx(
16882
17859
  paragraph,
@@ -16893,7 +17870,8 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16893
17870
  }
16894
17871
  return calibrateAutoLineSpacingMultiple(
16895
17872
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16896
- baseFontFamily
17873
+ baseFontFamily,
17874
+ singleLineScale
16897
17875
  );
16898
17876
  }
16899
17877
  const lineRule = paragraph.style?.spacing?.lineRule ?? "auto";
@@ -16910,7 +17888,8 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16910
17888
  lineTwips,
16911
17889
  DEFAULT_PARAGRAPH_LINE_MULTIPLE
16912
17890
  ),
16913
- baseFontFamily
17891
+ baseFontFamily,
17892
+ singleLineScale
16914
17893
  );
16915
17894
  return Number(lineMultiple.toFixed(3));
16916
17895
  }
@@ -16921,7 +17900,8 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16921
17900
  Math.round(
16922
17901
  paragraphBaseFontSizePx(paragraph) * calibrateAutoLineSpacingMultiple(
16923
17902
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16924
- baseFontFamily
17903
+ baseFontFamily,
17904
+ singleLineScale
16925
17905
  )
16926
17906
  )
16927
17907
  );
@@ -16937,12 +17917,29 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16937
17917
  if (lineRule === "exact") {
16938
17918
  return calibrateAutoLineSpacingMultiple(
16939
17919
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16940
- baseFontFamily
17920
+ baseFontFamily,
17921
+ singleLineScale
16941
17922
  );
16942
17923
  }
16943
17924
  return calibrateAutoLineSpacingMultiple(
16944
17925
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16945
- baseFontFamily
17926
+ baseFontFamily,
17927
+ singleLineScale
17928
+ );
17929
+ }
17930
+ function keepNextPaginationReservePx(paragraph, nextParagraph, docGridLinePitchPx) {
17931
+ if (paragraph.style?.keepNext !== true || !nextParagraph || !Number.isFinite(paragraph.style?.headingLevel)) {
17932
+ return 0;
17933
+ }
17934
+ const nextParagraphText = paragraphText(nextParagraph).replace(/\s+/g, " ").trim();
17935
+ if (nextParagraph.style?.numbering === void 0 && nextParagraphText.length < 80) {
17936
+ return 0;
17937
+ }
17938
+ return Math.max(
17939
+ nextParagraph.style?.numbering ? 10 : 6,
17940
+ Math.round(
17941
+ estimateParagraphLineHeightPx(nextParagraph, docGridLinePitchPx) * (nextParagraph.style?.numbering ? 1 : 0.5)
17942
+ )
16946
17943
  );
16947
17944
  }
16948
17945
  function paragraphBorderToCss(border) {
@@ -17516,6 +18513,17 @@ function tableOfContentsLeadingLeftTabStopPx(paragraph) {
17516
18513
  ).sort((left, right) => left - right);
17517
18514
  return leftTabStopPositionsPx[0];
17518
18515
  }
18516
+ function paragraphContainsTabCharacter(paragraph) {
18517
+ return paragraph.children.some((child) => {
18518
+ if (child.type === "text") {
18519
+ return child.text.includes(" ");
18520
+ }
18521
+ if (child.type === "form-field") {
18522
+ return formFieldDisplayValue2(child).includes(" ");
18523
+ }
18524
+ return false;
18525
+ });
18526
+ }
17519
18527
  function paragraphTabCharacterCount(paragraph) {
17520
18528
  return paragraph.children.reduce((count, child) => {
17521
18529
  const text = child.type === "text" ? child.text : child.type === "form-field" ? formFieldDisplayValue2(child) : "";
@@ -18910,6 +19918,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
18910
19918
  ) ? Math.round(options?.floatingAnchorOriginCorrectionXPx) : 0;
18911
19919
  const checkboxChoiceRow = paragraphLooksLikeCheckboxChoiceRow(paragraph);
18912
19920
  const fallbackTabWidthPx = checkboxChoiceRow ? checkboxChoiceRowTabWidthPx(paragraph) : DEFAULT_TAB_STOP_PX;
19921
+ const tabLeaderLeftTabStopPositionsPx = useTabLeaderLayout ? resolveParagraphFirstLineLeftTabStopsPx(paragraph) : [];
18913
19922
  const shouldTrackTabLineWidth = !useTabLeaderLayout && !useAnchoredTabLayout;
18914
19923
  let approximateLineWidthPx = 0;
18915
19924
  let trackedVisibleChildCursor = 0;
@@ -19028,6 +20037,32 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19028
20037
  lineHeight: "1em"
19029
20038
  };
19030
20039
  };
20040
+ const renderTabLeaderLeftSpacer = (target, key, style, trackedInlineChange, widthPx) => {
20041
+ const textStyle = trackedInlineStyle(
20042
+ runStyleToCss(style, documentTheme),
20043
+ trackedInlineChange
20044
+ );
20045
+ const hasUnderline = Boolean(style?.underline);
20046
+ target.push(
20047
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
20048
+ "span",
20049
+ {
20050
+ style: {
20051
+ ...textStyle,
20052
+ display: "inline-block",
20053
+ width: widthPx,
20054
+ minWidth: widthPx,
20055
+ whiteSpace: "pre",
20056
+ textDecoration: hasUnderline ? "none" : textStyle.textDecoration,
20057
+ borderBottom: hasUnderline ? "1px solid currentColor" : void 0,
20058
+ lineHeight: "1em"
20059
+ },
20060
+ children: "\xA0"
20061
+ },
20062
+ key
20063
+ )
20064
+ );
20065
+ };
19031
20066
  const resolvePageFieldText = (value, preferredZone) => {
19032
20067
  if (!hasPageField || value.trim().length === 0) {
19033
20068
  return value;
@@ -19317,7 +20352,10 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19317
20352
  (() => {
19318
20353
  const cropLayout = imageCropLayout(child, widthPx, heightPx);
19319
20354
  const imageVisualStyle = {
19320
- filter: appendCssFilters(child.cssFilter, options?.imageFilterSuffix),
20355
+ filter: appendCssFilters(
20356
+ child.cssFilter,
20357
+ options?.imageFilterSuffix
20358
+ ),
19321
20359
  opacity: child.cssOpacity
19322
20360
  };
19323
20361
  const imageTransformStyle = resolveImageRenderTransformStyle(child, {
@@ -19638,14 +20676,42 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19638
20676
  return;
19639
20677
  }
19640
20678
  if (leftText.length > 0) {
19641
- renderRun(
19642
- runsLeft,
19643
- child,
19644
- `${keyPrefix}-run-${childIndex}-left`,
19645
- resolveFieldText(leftText, 0),
19646
- trackedInlineChange,
19647
- childIndex
19648
- );
20679
+ let tabLeaderLeftLineWidthPx = 0;
20680
+ const leftTextParts = leftText.split(" ");
20681
+ leftTextParts.forEach((part, partIndex) => {
20682
+ if (part.length > 0) {
20683
+ const resolvedPart = resolveFieldText(part, 0);
20684
+ renderRun(
20685
+ runsLeft,
20686
+ child,
20687
+ `${keyPrefix}-run-${childIndex}-left-${partIndex}`,
20688
+ resolvedPart,
20689
+ trackedInlineChange,
20690
+ childIndex
20691
+ );
20692
+ tabLeaderLeftLineWidthPx = updateEstimatedLineWidthPxForText(
20693
+ tabLeaderLeftLineWidthPx,
20694
+ resolvedPart,
20695
+ child.style
20696
+ );
20697
+ }
20698
+ if (partIndex >= leftTextParts.length - 1) {
20699
+ return;
20700
+ }
20701
+ const tabWidthPx = resolveTabSpacerWidthPx(
20702
+ tabLeaderLeftTabStopPositionsPx,
20703
+ tabLeaderLeftLineWidthPx,
20704
+ fallbackTabWidthPx
20705
+ );
20706
+ renderTabLeaderLeftSpacer(
20707
+ runsLeft,
20708
+ `${keyPrefix}-run-${childIndex}-left-tab-${partIndex}`,
20709
+ child.style,
20710
+ trackedInlineChange,
20711
+ tabWidthPx
20712
+ );
20713
+ tabLeaderLeftLineWidthPx += tabWidthPx;
20714
+ });
19649
20715
  }
19650
20716
  renderRun(
19651
20717
  runsRight,
@@ -19871,10 +20937,10 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19871
20937
  {
19872
20938
  "data-docx-tab-zone": "left",
19873
20939
  style: {
19874
- display: "inline-flex",
20940
+ display: "block",
20941
+ flex: "0 1 auto",
19875
20942
  minWidth: 0,
19876
- whiteSpace: "pre-wrap",
19877
- alignItems: "baseline"
20943
+ whiteSpace: "pre-wrap"
19878
20944
  },
19879
20945
  children: runsLeft
19880
20946
  }
@@ -19902,12 +20968,13 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19902
20968
  {
19903
20969
  "data-docx-tab-zone": "right",
19904
20970
  style: {
19905
- display: "inline-flex",
19906
- minWidth: 0,
19907
- justifyContent: "flex-end",
20971
+ display: "block",
20972
+ flex: "0 0 max-content",
20973
+ minWidth: "max-content",
20974
+ width: "max-content",
19908
20975
  textAlign: "right",
19909
- whiteSpace: "pre-wrap",
19910
- alignItems: "baseline"
20976
+ whiteSpace: "nowrap",
20977
+ textIndent: 0
19911
20978
  },
19912
20979
  children: runsRight
19913
20980
  }
@@ -20157,20 +21224,7 @@ function buildParagraphNumberingLabels(model) {
20157
21224
  ])
20158
21225
  );
20159
21226
  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
- };
21227
+ const abstractCountersByAbstractNumId = /* @__PURE__ */ new Map();
20174
21228
  const registerParagraph = (paragraph, key) => {
20175
21229
  const paragraphNumbering = paragraph.style?.numbering;
20176
21230
  if (!paragraphNumbering || paragraphNumbering.numId <= 0) {
@@ -20181,13 +21235,12 @@ function buildParagraphNumberingLabels(model) {
20181
21235
  const level = findNumberingLevelDefinition(numbering, numId, ilvl);
20182
21236
  const numberingInstance = numberingInstanceByNumId.get(numId);
20183
21237
  const abstractNumId = numberingInstance?.abstractNumId;
20184
- const isSharedCounterParagraph = isHeadingLikeParagraph(paragraph);
20185
21238
  const template = level?.text ?? `%${ilvl + 1}.`;
20186
21239
  if (!template || template.trim().length === 0) {
20187
21240
  return;
20188
21241
  }
20189
21242
  const counters = countersByNumId.get(numId) ?? [];
20190
- const sharedAbstractCounters = isSharedCounterParagraph && Number.isFinite(abstractNumId) ? headingCountersByAbstractNumId.get(abstractNumId) ?? [] : void 0;
21243
+ const sharedAbstractCounters = Number.isFinite(abstractNumId) ? abstractCountersByAbstractNumId.get(abstractNumId) ?? [] : void 0;
20191
21244
  let parentCountersChanged = false;
20192
21245
  for (let index = 0; index < ilvl; index += 1) {
20193
21246
  const abstractCounterValue = sharedAbstractCounters && Number.isFinite(sharedAbstractCounters[index]) ? Math.max(1, Math.round(sharedAbstractCounters[index])) : void 0;
@@ -20216,7 +21269,7 @@ function buildParagraphNumberingLabels(model) {
20216
21269
  for (let index = ilvl + 1; index < sharedAbstractCounters.length; index += 1) {
20217
21270
  sharedAbstractCounters[index] = void 0;
20218
21271
  }
20219
- headingCountersByAbstractNumId.set(
21272
+ abstractCountersByAbstractNumId.set(
20220
21273
  abstractNumId,
20221
21274
  sharedAbstractCounters
20222
21275
  );
@@ -20962,6 +22015,14 @@ function tableBorderToCss(border) {
20962
22015
  const color = border?.color ?? "#000000";
20963
22016
  return `${widthPx}px ${cssStyle} ${color}`;
20964
22017
  }
22018
+ function tableBorderStrokeWidthPx(border) {
22019
+ const type = normalizeBorderType(border?.type);
22020
+ if (!type || type === "none" || type === "nil") {
22021
+ return 0;
22022
+ }
22023
+ const sizeEighthPt = border?.sizeEighthPt;
22024
+ return Number.isFinite(sizeEighthPt) && sizeEighthPt > 0 ? Math.max(0.5, Number((sizeEighthPt / 6).toFixed(2))) : 1;
22025
+ }
20965
22026
  function borderTypeVisible(type) {
20966
22027
  const normalizedType = normalizeBorderType(type);
20967
22028
  return Boolean(
@@ -21413,6 +22474,68 @@ function resolveTableCellBorderCss(tableBorders, cellBorders, rowIndex, rowCount
21413
22474
  ...left !== void 0 ? { borderLeft: left } : void 0
21414
22475
  };
21415
22476
  }
22477
+ function resolveCollapsedTableHorizontalOuterBleedPx(table, columnCount = tableColumnCount(table)) {
22478
+ if (columnCount <= 0 || tableUsesSeparateBorderModel(table)) {
22479
+ return 0;
22480
+ }
22481
+ const rowCount = table.rows.length;
22482
+ const tableBorders = table.style?.borders;
22483
+ let maxLeftBorderWidthPx = tableBorderStrokeWidthPx(tableBorders?.left);
22484
+ let maxRightBorderWidthPx = tableBorderStrokeWidthPx(tableBorders?.right);
22485
+ table.rows.forEach((row, rowIndex) => {
22486
+ let columnCursor = 0;
22487
+ row.cells.forEach((cell) => {
22488
+ const columnSpan = cell.style?.gridSpan && cell.style.gridSpan > 1 ? cell.style.gridSpan : 1;
22489
+ const startColumnIndex = columnCursor;
22490
+ const endColumnIndex = Math.min(
22491
+ columnCount - 1,
22492
+ startColumnIndex + columnSpan - 1
22493
+ );
22494
+ columnCursor += columnSpan;
22495
+ if (cell.style?.vMergeContinuation) {
22496
+ return;
22497
+ }
22498
+ if (startColumnIndex === 0) {
22499
+ maxLeftBorderWidthPx = Math.max(
22500
+ maxLeftBorderWidthPx,
22501
+ tableBorderStrokeWidthPx(
22502
+ resolveTableBorder(
22503
+ tableBorders,
22504
+ cell.style?.borders,
22505
+ "left",
22506
+ rowIndex,
22507
+ rowCount,
22508
+ startColumnIndex,
22509
+ endColumnIndex,
22510
+ columnCount
22511
+ )
22512
+ )
22513
+ );
22514
+ }
22515
+ if (endColumnIndex >= columnCount - 1) {
22516
+ maxRightBorderWidthPx = Math.max(
22517
+ maxRightBorderWidthPx,
22518
+ tableBorderStrokeWidthPx(
22519
+ resolveTableBorder(
22520
+ tableBorders,
22521
+ cell.style?.borders,
22522
+ "right",
22523
+ rowIndex,
22524
+ rowCount,
22525
+ startColumnIndex,
22526
+ endColumnIndex,
22527
+ columnCount
22528
+ )
22529
+ )
22530
+ );
22531
+ }
22532
+ });
22533
+ });
22534
+ return Math.max(
22535
+ 0,
22536
+ Math.ceil((maxLeftBorderWidthPx + maxRightBorderWidthPx) / 2)
22537
+ );
22538
+ }
21416
22539
  function resolveTableCellDiagonalOverlayCss(tableBorders, cellBorders) {
21417
22540
  const diagonalDownBorder = cellBorders?.tl2br ?? tableBorders?.tl2br;
21418
22541
  const diagonalUpBorder = cellBorders?.tr2bl ?? tableBorders?.tr2bl;
@@ -23304,6 +24427,7 @@ function useDocxEditor(options = {}) {
23304
24427
  const [status, setStatus] = React.useState(
23305
24428
  options.initialStatus ?? "Ready"
23306
24429
  );
24430
+ const [isImporting, setIsImporting] = React.useState(false);
23307
24431
  const [documentTheme, setDocumentThemeState] = React.useState(options.initialDocumentTheme ?? "light");
23308
24432
  const [showTrackedChanges, setShowTrackedChangesState] = React.useState(options.initialShowTrackedChanges ?? false);
23309
24433
  const [paginationInfo, setPaginationInfo] = React.useState({
@@ -23826,26 +24950,40 @@ function useDocxEditor(options = {}) {
23826
24950
  setStatus("Only .docx files are supported");
23827
24951
  return;
23828
24952
  }
24953
+ setIsImporting(true);
24954
+ setStatus(`Loading ${file.name}\u2026`);
24955
+ await new Promise((resolve) => {
24956
+ if (typeof requestAnimationFrame === "function") {
24957
+ requestAnimationFrame(() => {
24958
+ requestAnimationFrame(() => resolve());
24959
+ });
24960
+ } else {
24961
+ setTimeout(resolve, 0);
24962
+ }
24963
+ });
23829
24964
  try {
23830
24965
  const buffer = await file.arrayBuffer();
23831
- const pkg = await parseDocx(buffer);
24966
+ const { pkg, model: nextModel } = await importDocxViaWorker(buffer);
23832
24967
  await loadEmbeddedFontsFromPackage(pkg);
23833
- const nextModel = buildDocModel(pkg);
23834
- setModel(nextModel);
23835
- setDocumentLoadNonce((current) => current + 1);
23836
- setHistory({ past: [], future: [] });
23837
- setHistoryRestoreRequest(void 0);
23838
- setBasePackage(pkg);
23839
- setFileName(file.name);
23840
- setSelection({ kind: "paragraph", nodeIndex: 0 });
23841
- setActiveTextRangeState(void 0);
23842
- setPendingRunStyle(void 0);
23843
- setSelectedFormFieldLocation(void 0);
24968
+ React.startTransition(() => {
24969
+ setModel(nextModel);
24970
+ setDocumentLoadNonce((current) => current + 1);
24971
+ setHistory({ past: [], future: [] });
24972
+ setHistoryRestoreRequest(void 0);
24973
+ setBasePackage(pkg);
24974
+ setFileName(file.name);
24975
+ setSelection({ kind: "paragraph", nodeIndex: 0 });
24976
+ setActiveTextRangeState(void 0);
24977
+ setPendingRunStyle(void 0);
24978
+ setSelectedFormFieldLocation(void 0);
24979
+ });
23844
24980
  setStatus(`Loaded ${file.name}`);
23845
24981
  } catch (error) {
23846
24982
  setStatus(
23847
24983
  `Failed to load file: ${error instanceof Error ? error.message : "Unknown error"}`
23848
24984
  );
24985
+ } finally {
24986
+ setIsImporting(false);
23849
24987
  }
23850
24988
  },
23851
24989
  [loadEmbeddedFontsFromPackage]
@@ -26770,6 +27908,7 @@ function useDocxEditor(options = {}) {
26770
27908
  documentLoadNonce,
26771
27909
  fileName,
26772
27910
  status,
27911
+ isImporting,
26773
27912
  documentTheme,
26774
27913
  trackedChanges,
26775
27914
  showTrackedChanges,
@@ -27054,12 +28193,9 @@ function useDocxPageThumbnails(editor, options = {}) {
27054
28193
  [pageSurfaceRegistryEditor]
27055
28194
  );
27056
28195
  React.useEffect(
27057
- () => subscribeDocxViewerPageSurfaces(
27058
- pageSurfaceRegistryEditor,
27059
- () => {
27060
- setPageSurfaceEpoch((current) => current + 1);
27061
- }
27062
- ),
28196
+ () => subscribeDocxViewerPageSurfaces(pageSurfaceRegistryEditor, () => {
28197
+ setPageSurfaceEpoch((current) => current + 1);
28198
+ }),
27063
28199
  [pageSurfaceRegistryEditor]
27064
28200
  );
27065
28201
  const mountedPageElements = React.useMemo(
@@ -27146,7 +28282,9 @@ function useDocxPageThumbnails(editor, options = {}) {
27146
28282
  );
27147
28283
  await Promise.all(tasks);
27148
28284
  }, [renderPageThumbnailToCanvas]);
27149
- const renderPageThumbnailToCanvasRef = React.useRef(renderPageThumbnailToCanvas);
28285
+ const renderPageThumbnailToCanvasRef = React.useRef(
28286
+ renderPageThumbnailToCanvas
28287
+ );
27150
28288
  React.useEffect(() => {
27151
28289
  renderPageThumbnailToCanvasRef.current = renderPageThumbnailToCanvas;
27152
28290
  }, [renderPageThumbnailToCanvas]);
@@ -27781,7 +28919,11 @@ function renderHeaderNode(node, keyPrefix, documentTheme, numberingDefinitions,
27781
28919
  return normalizeColumnWidthsPx(widthsPx, columnCount, tableWidthPx, 1);
27782
28920
  })();
27783
28921
  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;
28922
+ const collapsedHorizontalBorderBleedPx = resolveCollapsedTableHorizontalOuterBleedPx(node, columnCount);
28923
+ const maxTableWidthPx = Number.isFinite(maxContentWidthPx) && maxContentWidthPx > 0 ? Math.max(
28924
+ 120,
28925
+ maxContentWidthPx - tableIndentPx - collapsedHorizontalBorderBleedPx
28926
+ ) : void 0;
27785
28927
  const resolvedTableWidthPx = clampTableWidthPx(
27786
28928
  rawResolvedTableWidthPx,
27787
28929
  maxTableWidthPx
@@ -27894,6 +29036,7 @@ function renderHeaderNode(node, keyPrefix, documentTheme, numberingDefinitions,
27894
29036
  "span",
27895
29037
  {
27896
29038
  contentEditable: false,
29039
+ "data-docx-pagination-ignore": "true",
27897
29040
  style: {
27898
29041
  position: "absolute",
27899
29042
  top: -TABLE_HANDLE_SAFEZONE_TOP_PX,
@@ -27911,6 +29054,7 @@ function renderHeaderNode(node, keyPrefix, documentTheme, numberingDefinitions,
27911
29054
  "span",
27912
29055
  {
27913
29056
  contentEditable: false,
29057
+ "data-docx-pagination-ignore": "true",
27914
29058
  style: {
27915
29059
  position: "absolute",
27916
29060
  right: -TABLE_HANDLE_SAFEZONE_RIGHT_PX,
@@ -28522,6 +29666,11 @@ function DocxEditorViewer({
28522
29666
  measuredPageContentIdentityKeysByIndex,
28523
29667
  setMeasuredPageContentIdentityKeysByIndex
28524
29668
  ] = React.useState([]);
29669
+ const [hasMeasuredBodyFooterOverlap, setHasMeasuredBodyFooterOverlap] = React.useState(false);
29670
+ const measuredBodyFooterOverlapCandidateRef = React.useRef({
29671
+ signature: void 0,
29672
+ consecutivePasses: 0
29673
+ });
28525
29674
  const [, setRenderableImageSourceRevision] = React.useState(0);
28526
29675
  const [activeEditableParagraphSegment, setActiveEditableParagraphSegment] = React.useState(void 0);
28527
29676
  const wrappedParagraphTextareaRef = React.useRef(
@@ -28531,6 +29680,10 @@ function DocxEditorViewer({
28531
29680
  const wrappedParagraphSelectionDragRef = React.useRef(void 0);
28532
29681
  const wrappedParagraphSurfaceRegistryRef = React.useRef(/* @__PURE__ */ new Map());
28533
29682
  const [isInitialPaginationSettled, setIsInitialPaginationSettled] = React.useState(!deferInitialPaginationPaint);
29683
+ const [
29684
+ initialPaginationBackgroundRefinementUnlocked,
29685
+ setInitialPaginationBackgroundRefinementUnlocked
29686
+ ] = React.useState(!deferInitialPaginationPaint);
28534
29687
  const [postImportPaginationUnlocked, setPostImportPaginationUnlocked] = React.useState(false);
28535
29688
  const [
28536
29689
  initialPaginationReservedLayoutState,
@@ -28572,6 +29725,11 @@ function DocxEditorViewer({
28572
29725
  React.useEffect(() => {
28573
29726
  setMeasuredPageContentHeightByIndex([]);
28574
29727
  setMeasuredPageContentIdentityKeysByIndex([]);
29728
+ setHasMeasuredBodyFooterOverlap(false);
29729
+ measuredBodyFooterOverlapCandidateRef.current = {
29730
+ signature: void 0,
29731
+ consecutivePasses: 0
29732
+ };
28575
29733
  setTableMeasuredRowHeights({});
28576
29734
  setTableRowHeights({});
28577
29735
  setTableColumnWidths({});
@@ -28615,6 +29773,9 @@ function DocxEditorViewer({
28615
29773
  }
28616
29774
  initialPaginationRevealFrameRef.current = null;
28617
29775
  setIsInitialPaginationSettled(!deferInitialPaginationPaint);
29776
+ setInitialPaginationBackgroundRefinementUnlocked(
29777
+ !deferInitialPaginationPaint
29778
+ );
28618
29779
  }, [deferInitialPaginationPaint, editor.documentLoadNonce]);
28619
29780
  const [activeRowResize, setActiveRowResize] = React.useState();
28620
29781
  const [activeEmbeddedRowResize, setActiveEmbeddedRowResize] = React.useState();
@@ -28903,6 +30064,28 @@ function DocxEditorViewer({
28903
30064
  }
28904
30065
  return widthByNodeIndex;
28905
30066
  }, [editor.model.nodes, paginationSectionMetrics]);
30067
+ const pageContentHeightPxByNodeIndex = React.useMemo(() => {
30068
+ const heightByNodeIndex = /* @__PURE__ */ new Map();
30069
+ if (editor.model.nodes.length === 0 || paginationSectionMetrics.length === 0) {
30070
+ return heightByNodeIndex;
30071
+ }
30072
+ let currentMetricsIndex = 0;
30073
+ for (let nodeIndex = 0; nodeIndex < editor.model.nodes.length; nodeIndex += 1) {
30074
+ currentMetricsIndex = resolvePaginationSectionMetricsIndexForNodeIndex(
30075
+ paginationSectionMetrics,
30076
+ nodeIndex,
30077
+ currentMetricsIndex
30078
+ );
30079
+ const pageContentHeightPx = paginationSectionMetrics[currentMetricsIndex]?.pageContentHeightPx;
30080
+ if (Number.isFinite(pageContentHeightPx) && pageContentHeightPx > 0) {
30081
+ heightByNodeIndex.set(
30082
+ nodeIndex,
30083
+ Math.round(pageContentHeightPx)
30084
+ );
30085
+ }
30086
+ }
30087
+ return heightByNodeIndex;
30088
+ }, [editor.model.nodes, paginationSectionMetrics]);
28906
30089
  const sectionColumnsBySectionIndex = React.useMemo(
28907
30090
  () => documentSections.map(
28908
30091
  (section) => parseSectionColumns(section.sectionPropertiesXml)
@@ -28952,6 +30135,7 @@ function DocxEditorViewer({
28952
30135
  activeDraftKeys,
28953
30136
  numberingDefinitions: editor.model.metadata.numberingDefinitions,
28954
30137
  pageContentWidthPxByNodeIndex,
30138
+ pageContentHeightPxByNodeIndex,
28955
30139
  docGridLinePitchPxByNodeIndex
28956
30140
  }
28957
30141
  );
@@ -28961,6 +30145,7 @@ function DocxEditorViewer({
28961
30145
  editor.canUndo,
28962
30146
  editor.model.metadata.numberingDefinitions,
28963
30147
  editor.model.nodes,
30148
+ pageContentHeightPxByNodeIndex,
28964
30149
  pageContentWidthPxByNodeIndex,
28965
30150
  disableMeasuredImportPagination,
28966
30151
  tableDraftLayoutEpoch,
@@ -29018,17 +30203,43 @@ function DocxEditorViewer({
29018
30203
  (count, node) => count + (node.type === "paragraph" && paragraphHasLastRenderedPageBreak(node) ? 1 : 0),
29019
30204
  0
29020
30205
  ) : void 0;
30206
+ const hasMultiColumnRenderedPageBreakHints = editor.model.nodes.some(
30207
+ (node, nodeIndex) => {
30208
+ if (node.type !== "paragraph" || !paragraphStartsWithLastRenderedPageBreak(node)) {
30209
+ return false;
30210
+ }
30211
+ const metricsIndex = resolvePaginationSectionMetricsIndexForNodeIndex(
30212
+ paginationSectionMetrics,
30213
+ nodeIndex,
30214
+ 0
30215
+ );
30216
+ return (paginationSectionMetrics[metricsIndex]?.pageContentHeightMultiplier ?? 1) > 1;
30217
+ }
30218
+ );
29021
30219
  const minimumPageCount = Math.max(1, hardBreakCount + 1);
29022
30220
  const targetPageCount = Number.isFinite(storedDocumentPageCount2) && storedDocumentPageCount2 > 0 ? Math.max(
29023
30221
  minimumPageCount,
29024
30222
  Math.round(storedDocumentPageCount2)
29025
30223
  ) : void 0;
30224
+ let estimatedPages = buildEstimatedPages(
30225
+ tableMeasuredRowHeightsForPagination
30226
+ );
30227
+ let estimatedPagesUseMeasuredPageContentHeightsForRender = canUseMeasuredPageContentHeights;
30228
+ let estimatedRenderMeasuredPageContentHeightsPxByPageIndex = canUseMeasuredPageContentHeights ? measuredPageContentHeightByIndex : void 0;
30229
+ let estimatedRenderPageContentHeightScale = void 0;
30230
+ const deferExpensiveInitialPaginationReconciliation = deferInitialPaginationPaint && !initialPaginationBackgroundRefinementUnlocked;
30231
+ if (deferExpensiveInitialPaginationReconciliation) {
30232
+ return {
30233
+ pages: estimatedPages,
30234
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30235
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30236
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
30237
+ };
30238
+ }
29026
30239
  const pureEstimatedPages = buildEstimatedPages(
29027
30240
  tableMeasuredRowHeightsForPagination,
29028
30241
  null
29029
30242
  );
29030
- let estimatedPages = buildEstimatedPages(tableMeasuredRowHeightsForPagination);
29031
- let estimatedPagesUseMeasuredPageContentHeightsForRender = canUseMeasuredPageContentHeights;
29032
30243
  if (measuredPageContentHeightByIndex && measuredPageContentHeightByIndex.length > 0) {
29033
30244
  const measuredPagesAreOnlySplitParagraphs = estimatedPages.length > 0 && estimatedPages.every(
29034
30245
  (pageSegments) => documentPageContainsOnlySplitParagraphSegments(pageSegments)
@@ -29039,21 +30250,29 @@ function DocxEditorViewer({
29039
30250
  if (measuredPagesAreOnlySplitParagraphs && purePagesAreOnlySplitParagraphs && pureEstimatedPages.length < estimatedPages.length) {
29040
30251
  estimatedPages = pureEstimatedPages;
29041
30252
  estimatedPagesUseMeasuredPageContentHeightsForRender = false;
30253
+ estimatedRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30254
+ estimatedRenderPageContentHeightScale = void 0;
29042
30255
  }
29043
30256
  }
29044
- if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && tableMeasuredRowHeightsForPagination) {
30257
+ if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && tableMeasuredRowHeightsForPagination && !hasMultiColumnRenderedPageBreakHints) {
29045
30258
  const candidatePages = [
29046
30259
  {
29047
30260
  pages: estimatedPages,
29048
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30261
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30262
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30263
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
29049
30264
  },
29050
30265
  {
29051
30266
  pages: buildEstimatedPages(void 0),
29052
- useMeasuredPageContentHeightsForRender: canUseMeasuredPageContentHeights
30267
+ useMeasuredPageContentHeightsForRender: canUseMeasuredPageContentHeights,
30268
+ renderMeasuredPageContentHeightsPxByPageIndex: canUseMeasuredPageContentHeights ? measuredPageContentHeightByIndex : void 0,
30269
+ renderPageContentHeightScale: void 0
29053
30270
  },
29054
30271
  {
29055
30272
  pages: buildEstimatedPages(void 0, null),
29056
- useMeasuredPageContentHeightsForRender: false
30273
+ useMeasuredPageContentHeightsForRender: false,
30274
+ renderMeasuredPageContentHeightsPxByPageIndex: void 0,
30275
+ renderPageContentHeightScale: void 0
29057
30276
  }
29058
30277
  ];
29059
30278
  const bestCandidate = candidatePages.reduce((best, candidate) => {
@@ -29065,11 +30284,15 @@ function DocxEditorViewer({
29065
30284
  });
29066
30285
  estimatedPages = bestCandidate.pages;
29067
30286
  estimatedPagesUseMeasuredPageContentHeightsForRender = bestCandidate.useMeasuredPageContentHeightsForRender;
29068
- } else if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0) {
30287
+ estimatedRenderMeasuredPageContentHeightsPxByPageIndex = bestCandidate.renderMeasuredPageContentHeightsPxByPageIndex;
30288
+ estimatedRenderPageContentHeightScale = bestCandidate.renderPageContentHeightScale;
30289
+ } else if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && !hasMultiColumnRenderedPageBreakHints) {
29069
30290
  const pureEstimatedPages2 = buildEstimatedPages(void 0, null);
29070
30291
  if (Math.abs(pureEstimatedPages2.length - targetPageCount) < Math.abs(estimatedPages.length - targetPageCount)) {
29071
30292
  estimatedPages = pureEstimatedPages2;
29072
30293
  estimatedPagesUseMeasuredPageContentHeightsForRender = false;
30294
+ estimatedRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30295
+ estimatedRenderPageContentHeightScale = void 0;
29073
30296
  }
29074
30297
  }
29075
30298
  const measuredPageHeightOverridesReduceContent = !editor.canUndo && !editor.canRedo && !floatingMovePreview && !dropCapMovePreview && estimatedPages.some((segments, pageIndex) => {
@@ -29096,7 +30319,9 @@ function DocxEditorViewer({
29096
30319
  if (!Number.isFinite(storedDocumentPageCount2) || storedDocumentPageCount2 <= 0) {
29097
30320
  return {
29098
30321
  pages: estimatedPages,
29099
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30322
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30323
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30324
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
29100
30325
  };
29101
30326
  }
29102
30327
  const resolvedTargetPageCount = targetPageCount ?? minimumPageCount;
@@ -29106,22 +30331,26 @@ function DocxEditorViewer({
29106
30331
  )
29107
30332
  );
29108
30333
  const allowMeasuredReductionOverPaginationReconciliation = measuredPageHeightOverridesReduceContent && estimatedPages.length > resolvedTargetPageCount;
29109
- const allowStoredPageCountReconciliation = !editor.canUndo && !editor.canRedo && !hasPageAnchoredFloatingFooterContent && shouldAllowStoredPageCountReduction({
30334
+ const allowStoredPageCountReconciliation = !editor.canUndo && !editor.canRedo && !hasPageAnchoredFloatingFooterContent && !hasMultiColumnRenderedPageBreakHints && shouldAllowStoredPageCountReduction({
29110
30335
  estimatedPageCount: estimatedPages.length,
29111
30336
  targetPageCount: resolvedTargetPageCount,
29112
30337
  hasLastRenderedPageBreakHints,
29113
- renderedBreakHintPageCount
30338
+ renderedBreakHintPageCount,
30339
+ hasMeasuredBodyFooterOverlap
29114
30340
  }) && (!measuredPageHeightOverridesReduceContent || allowMeasuredReductionOverPaginationReconciliation);
29115
30341
  if (!allowStoredPageCountReconciliation) {
29116
30342
  return {
29117
30343
  pages: estimatedPages,
29118
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30344
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30345
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30346
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
29119
30347
  };
29120
30348
  }
29121
30349
  if (estimatedPages.length === resolvedTargetPageCount) {
29122
30350
  return {
29123
30351
  pages: estimatedPages,
29124
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30352
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30353
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex
29125
30354
  };
29126
30355
  }
29127
30356
  const reconciliationScales = allowMeasuredReductionOverPaginationReconciliation ? [
@@ -29141,7 +30370,7 @@ function DocxEditorViewer({
29141
30370
  1.28,
29142
30371
  1.3
29143
30372
  ] : void 0;
29144
- const reconcileCandidatePages = (initialPages, measuredTableRowHeightsByNodeIndex, measuredPageContentHeightsOverride) => reconcilePagesToTargetCountByScalingHeight({
30373
+ const reconcileCandidatePages = (initialPages, measuredTableRowHeightsByNodeIndex, measuredPageContentHeightsOverride) => reconcilePageCountCandidateToTargetCountByScalingHeight({
29145
30374
  initialPages,
29146
30375
  targetPageCount: resolvedTargetPageCount,
29147
30376
  maxDifference: hasTableInternalPageBreaks ? 2 : 3,
@@ -29167,27 +30396,38 @@ function DocxEditorViewer({
29167
30396
  }
29168
30397
  )
29169
30398
  });
29170
- let reconciledPages = reconcileCandidatePages(
30399
+ let reconciledCandidate = reconcileCandidatePages(
29171
30400
  estimatedPages,
29172
30401
  tableMeasuredRowHeightsForPagination,
29173
30402
  estimatedPagesUseMeasuredPageContentHeightsForRender ? measuredPageContentHeightByIndex : null
29174
30403
  );
30404
+ let reconciledPages = reconciledCandidate.pages;
29175
30405
  let reconciledPagesUseMeasuredPageContentHeightsForRender = estimatedPagesUseMeasuredPageContentHeightsForRender;
30406
+ let reconciledRenderMeasuredPageContentHeightsPxByPageIndex = reconciledPagesUseMeasuredPageContentHeightsForRender ? scaleMeasuredPageContentHeights(
30407
+ measuredPageContentHeightByIndex,
30408
+ reconciledCandidate.scale
30409
+ ) : void 0;
30410
+ let reconciledRenderPageContentHeightScale = reconciledPagesUseMeasuredPageContentHeightsForRender ? void 0 : reconciledCandidate.scale;
29176
30411
  if (!editor.canUndo && !editor.canRedo) {
29177
30412
  const pureEstimatedPages2 = buildEstimatedPages(void 0, null);
29178
- const pureReconciledPages = reconcileCandidatePages(
30413
+ const pureReconciledCandidate = reconcileCandidatePages(
29179
30414
  pureEstimatedPages2,
29180
30415
  void 0,
29181
30416
  null
29182
30417
  );
30418
+ const pureReconciledPages = pureReconciledCandidate.pages;
29183
30419
  if (Math.abs(pureReconciledPages.length - resolvedTargetPageCount) < Math.abs(reconciledPages.length - resolvedTargetPageCount)) {
29184
30420
  reconciledPages = pureReconciledPages;
29185
30421
  reconciledPagesUseMeasuredPageContentHeightsForRender = false;
30422
+ reconciledRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30423
+ reconciledRenderPageContentHeightScale = pureReconciledCandidate.scale;
29186
30424
  }
29187
30425
  }
29188
30426
  return {
29189
30427
  pages: reconciledPages,
29190
- useMeasuredPageContentHeightsForRender: reconciledPagesUseMeasuredPageContentHeightsForRender
30428
+ useMeasuredPageContentHeightsForRender: reconciledPagesUseMeasuredPageContentHeightsForRender,
30429
+ renderMeasuredPageContentHeightsPxByPageIndex: reconciledRenderMeasuredPageContentHeightsPxByPageIndex,
30430
+ renderPageContentHeightScale: reconciledRenderPageContentHeightScale
29191
30431
  };
29192
30432
  }, [
29193
30433
  editor.canRedo,
@@ -29206,12 +30446,17 @@ function DocxEditorViewer({
29206
30446
  isReadOnly,
29207
30447
  floatingMovePreview,
29208
30448
  dropCapMovePreview,
30449
+ deferInitialPaginationPaint,
29209
30450
  disableMeasuredImportPagination,
30451
+ hasMeasuredBodyFooterOverlap,
30452
+ initialPaginationBackgroundRefinementUnlocked,
29210
30453
  measuredPageContentHeightByIndex,
29211
30454
  tableMeasuredRowHeightsForPagination
29212
30455
  ]);
29213
30456
  const pageNodeSegmentsByPage = pageSegmentationPlan.pages;
29214
30457
  const useMeasuredPageContentHeightsForRender = pageSegmentationPlan.useMeasuredPageContentHeightsForRender;
30458
+ const renderMeasuredPageContentHeightsPxByPageIndex = pageSegmentationPlan.renderMeasuredPageContentHeightsPxByPageIndex;
30459
+ const renderPageContentHeightScale = pageSegmentationPlan.renderPageContentHeightScale;
29215
30460
  const pageNodeSegmentIdentityKeysByPage = React.useMemo(
29216
30461
  () => pageNodeSegmentsByPage.map(
29217
30462
  (pageSegments) => documentPageNodeSegmentsIdentityKey(pageSegments)
@@ -29427,6 +30672,32 @@ function DocxEditorViewer({
29427
30672
  };
29428
30673
  }, [editor.model.nodes, pageNodeSegmentsByPage]);
29429
30674
  const pageCount = pageNodeSegmentsByPage.length;
30675
+ const hasLargeTableLayoutSurface = React.useMemo(() => {
30676
+ let tableParagraphCount = 0;
30677
+ let tableCellCount = 0;
30678
+ let largestRowParagraphCount = 0;
30679
+ for (const node of editor.model.nodes) {
30680
+ if (node.type !== "table") {
30681
+ continue;
30682
+ }
30683
+ for (const row of node.rows) {
30684
+ let rowParagraphCount = 0;
30685
+ tableCellCount += row.cells.length;
30686
+ for (const cell of row.cells) {
30687
+ const paragraphCount = tableCellParagraphsRecursively(
30688
+ cell.nodes
30689
+ ).length;
30690
+ tableParagraphCount += paragraphCount;
30691
+ rowParagraphCount += paragraphCount;
30692
+ }
30693
+ largestRowParagraphCount = Math.max(
30694
+ largestRowParagraphCount,
30695
+ rowParagraphCount
30696
+ );
30697
+ }
30698
+ }
30699
+ return tableParagraphCount >= 1e3 || tableCellCount >= 240 || largestRowParagraphCount >= 100;
30700
+ }, [editor.model.nodes]);
29430
30701
  const hideDocumentUntilPaginationSettled = deferInitialPaginationPaint && !isInitialPaginationSettled;
29431
30702
  const estimateDocumentStackHeightPx = React.useCallback(
29432
30703
  (count) => {
@@ -29498,28 +30769,34 @@ function DocxEditorViewer({
29498
30769
  const hasExternalVisiblePageRange = Number.isFinite(Number(visiblePageRange?.startPageIndex)) || Number.isFinite(Number(visiblePageRange?.endPageIndex));
29499
30770
  const [deferInternalPageVirtualization, setDeferInternalPageVirtualization] = React.useState(false);
29500
30771
  const [internalVirtualScrollElement, setInternalVirtualScrollElement] = React.useState(null);
30772
+ const [observedVisiblePageRange, setObservedVisiblePageRange] = React.useState(void 0);
29501
30773
  const pageVirtualizationSettleDelayMs = Math.max(
29502
30774
  0,
29503
30775
  Math.round(
29504
30776
  Number.isFinite(pageVirtualization?.settleDelayMs) ? pageVirtualization?.settleDelayMs : DEFAULT_PAGE_VIRTUALIZATION_SETTLE_DELAY_MS
29505
30777
  )
29506
30778
  );
29507
- const pageVirtualizationOverscan = Math.max(
30779
+ const rawPageVirtualizationOverscan = Math.max(
29508
30780
  0,
29509
30781
  Math.round(
29510
30782
  Number.isFinite(pageVirtualization?.overscan) ? pageVirtualization?.overscan : DEFAULT_PAGE_VIRTUALIZATION_OVERSCAN
29511
30783
  )
29512
30784
  );
30785
+ const pageVirtualizationOverscan = hasLargeTableLayoutSurface && !Number.isFinite(pageVirtualization?.overscan) ? 0 : rawPageVirtualizationOverscan;
29513
30786
  const webdriverActive = typeof navigator !== "undefined" && navigator.webdriver === true;
29514
30787
  const internalPageVirtualizationRequested = pageVirtualization?.enabled !== false && !hasExternalVisiblePageRange && !hideDocumentUntilPaginationSettled && isInitialPaginationSettled && !deferInternalPageVirtualization && !webdriverActive && pageCount > 1;
29515
30788
  React.useEffect(() => {
29516
- setDeferInternalPageVirtualization(true);
29517
- }, [editor.documentLoadNonce]);
30789
+ setDeferInternalPageVirtualization(!hasLargeTableLayoutSurface);
30790
+ }, [editor.documentLoadNonce, hasLargeTableLayoutSurface]);
29518
30791
  React.useEffect(() => {
29519
30792
  if (typeof window === "undefined" || webdriverActive || pageCount <= 1) {
29520
30793
  setDeferInternalPageVirtualization(true);
29521
30794
  return;
29522
30795
  }
30796
+ if (hasLargeTableLayoutSurface) {
30797
+ setDeferInternalPageVirtualization(false);
30798
+ return;
30799
+ }
29523
30800
  const timeoutId = window.setTimeout(() => {
29524
30801
  setDeferInternalPageVirtualization(false);
29525
30802
  }, pageVirtualizationSettleDelayMs);
@@ -29528,6 +30805,7 @@ function DocxEditorViewer({
29528
30805
  };
29529
30806
  }, [
29530
30807
  editor.documentLoadNonce,
30808
+ hasLargeTableLayoutSurface,
29531
30809
  pageCount,
29532
30810
  pageVirtualizationSettleDelayMs,
29533
30811
  webdriverActive
@@ -29541,15 +30819,30 @@ function DocxEditorViewer({
29541
30819
  );
29542
30820
  }, [editor.documentLoadNonce, pageCount, trackedChangesEnabled]);
29543
30821
  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) => {
30822
+ const internalPageVirtualizationPending = typeof window !== "undefined" && internalPageVirtualizationRequested && internalVirtualScrollElement === null;
30823
+ const internalVirtualScrollUsesWindow = typeof document !== "undefined" && internalVirtualScrollElement !== null && (internalVirtualScrollElement === document.scrollingElement || internalVirtualScrollElement === document.documentElement || internalVirtualScrollElement === document.body);
30824
+ const internalElementPageVirtualizationEnabled = internalPageVirtualizationEnabled && !internalVirtualScrollUsesWindow;
30825
+ const internalWindowPageVirtualizationEnabled = internalPageVirtualizationEnabled && internalVirtualScrollUsesWindow;
30826
+ const estimateVirtualPageSize = React.useCallback(
30827
+ (pageIndex) => {
29548
30828
  const pageLayout = pageSectionInfoByIndex[pageIndex]?.layout ?? documentLayout;
29549
30829
  return Math.max(1, pageLayout.pageHeightPx + DOC_PAGE_BREAK_GAP);
29550
30830
  },
30831
+ [documentLayout, pageSectionInfoByIndex]
30832
+ );
30833
+ const internalElementPageVirtualizer = (0, import_react_virtual.useVirtualizer)({
30834
+ count: Math.max(1, pageCount),
30835
+ getScrollElement: () => internalElementPageVirtualizationEnabled ? internalVirtualScrollElement : null,
30836
+ estimateSize: estimateVirtualPageSize,
30837
+ overscan: pageVirtualizationOverscan
30838
+ });
30839
+ const internalWindowPageVirtualizer = (0, import_react_virtual.useWindowVirtualizer)({
30840
+ count: Math.max(1, pageCount),
30841
+ getScrollElement: () => internalWindowPageVirtualizationEnabled && typeof window !== "undefined" ? window : null,
30842
+ estimateSize: estimateVirtualPageSize,
29551
30843
  overscan: pageVirtualizationOverscan
29552
30844
  });
30845
+ const internalPageVirtualizer = internalVirtualScrollUsesWindow ? internalWindowPageVirtualizer : internalElementPageVirtualizer;
29553
30846
  const internalVirtualItems = internalPageVirtualizer.getVirtualItems();
29554
30847
  const internalVisiblePageRange = React.useMemo(() => {
29555
30848
  if (!internalPageVirtualizationEnabled) {
@@ -29584,7 +30877,134 @@ function DocxEditorViewer({
29584
30877
  endPageIndex
29585
30878
  };
29586
30879
  }, [internalPageVirtualizationEnabled, internalVirtualItems, pageCount]);
29587
- const effectiveVisiblePageRange = visiblePageRange ?? internalVisiblePageRange;
30880
+ React.useLayoutEffect(() => {
30881
+ if (!internalPageVirtualizationEnabled || !internalVirtualScrollElement || typeof window === "undefined") {
30882
+ setObservedVisiblePageRange(
30883
+ (current) => current === void 0 ? current : void 0
30884
+ );
30885
+ return;
30886
+ }
30887
+ const rootElement = viewerRootRef.current;
30888
+ if (!rootElement) {
30889
+ setObservedVisiblePageRange(
30890
+ (current) => current === void 0 ? current : void 0
30891
+ );
30892
+ return;
30893
+ }
30894
+ let frameId = null;
30895
+ const syncVisiblePageRange = () => {
30896
+ frameId = null;
30897
+ const viewportRect = internalVirtualScrollUsesWindow ? {
30898
+ top: 0,
30899
+ bottom: window.innerHeight
30900
+ } : internalVirtualScrollElement.getBoundingClientRect();
30901
+ const pageWrappers = rootElement.querySelectorAll(
30902
+ '[data-docx-page-wrapper="true"][data-index]'
30903
+ );
30904
+ let firstVisiblePageIndex;
30905
+ let lastVisiblePageIndex;
30906
+ for (const pageWrapper of pageWrappers) {
30907
+ const rawPageIndex = pageWrapper.getAttribute("data-index");
30908
+ const pageIndex = Number.parseInt(rawPageIndex ?? "", 10);
30909
+ if (!Number.isFinite(pageIndex)) {
30910
+ continue;
30911
+ }
30912
+ const pageRect = pageWrapper.getBoundingClientRect();
30913
+ if (pageRect.bottom <= viewportRect.top) {
30914
+ continue;
30915
+ }
30916
+ if (pageRect.top >= viewportRect.bottom) {
30917
+ if (firstVisiblePageIndex !== void 0) {
30918
+ break;
30919
+ }
30920
+ continue;
30921
+ }
30922
+ if (firstVisiblePageIndex === void 0) {
30923
+ firstVisiblePageIndex = pageIndex;
30924
+ }
30925
+ lastVisiblePageIndex = pageIndex;
30926
+ }
30927
+ if (firstVisiblePageIndex === void 0 || lastVisiblePageIndex === void 0) {
30928
+ setObservedVisiblePageRange(
30929
+ (current) => current === void 0 ? current : void 0
30930
+ );
30931
+ return;
30932
+ }
30933
+ const startPageIndex = clampNumber(
30934
+ firstVisiblePageIndex - pageVirtualizationOverscan,
30935
+ 0,
30936
+ pageCount - 1
30937
+ );
30938
+ const endPageIndex = clampNumber(
30939
+ lastVisiblePageIndex + pageVirtualizationOverscan,
30940
+ startPageIndex,
30941
+ pageCount - 1
30942
+ );
30943
+ setObservedVisiblePageRange((current) => {
30944
+ if (current?.startPageIndex === startPageIndex && current?.endPageIndex === endPageIndex) {
30945
+ return current;
30946
+ }
30947
+ return {
30948
+ startPageIndex,
30949
+ endPageIndex
30950
+ };
30951
+ });
30952
+ };
30953
+ const scheduleVisiblePageRangeSync = () => {
30954
+ if (frameId !== null) {
30955
+ return;
30956
+ }
30957
+ frameId = window.requestAnimationFrame(syncVisiblePageRange);
30958
+ };
30959
+ const resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(() => {
30960
+ scheduleVisiblePageRangeSync();
30961
+ }) : void 0;
30962
+ if (!internalVirtualScrollUsesWindow) {
30963
+ resizeObserver?.observe(internalVirtualScrollElement);
30964
+ }
30965
+ resizeObserver?.observe(rootElement);
30966
+ if (internalVirtualScrollUsesWindow) {
30967
+ window.addEventListener("scroll", scheduleVisiblePageRangeSync, {
30968
+ passive: true
30969
+ });
30970
+ } else {
30971
+ internalVirtualScrollElement.addEventListener(
30972
+ "scroll",
30973
+ scheduleVisiblePageRangeSync,
30974
+ { passive: true }
30975
+ );
30976
+ }
30977
+ window.addEventListener("resize", scheduleVisiblePageRangeSync);
30978
+ scheduleVisiblePageRangeSync();
30979
+ return () => {
30980
+ if (internalVirtualScrollUsesWindow) {
30981
+ window.removeEventListener("scroll", scheduleVisiblePageRangeSync);
30982
+ } else {
30983
+ internalVirtualScrollElement.removeEventListener(
30984
+ "scroll",
30985
+ scheduleVisiblePageRangeSync
30986
+ );
30987
+ }
30988
+ window.removeEventListener("resize", scheduleVisiblePageRangeSync);
30989
+ resizeObserver?.disconnect();
30990
+ if (frameId !== null) {
30991
+ window.cancelAnimationFrame(frameId);
30992
+ }
30993
+ };
30994
+ }, [
30995
+ internalPageVirtualizationEnabled,
30996
+ internalVirtualScrollElement,
30997
+ internalVirtualScrollUsesWindow,
30998
+ pageCount,
30999
+ pageVirtualizationOverscan
31000
+ ]);
31001
+ const effectiveVisiblePageRange = visiblePageRange ?? observedVisiblePageRange ?? internalVisiblePageRange ?? (internalPageVirtualizationPending ? {
31002
+ startPageIndex: 0,
31003
+ endPageIndex: Math.min(
31004
+ pageCount - 1,
31005
+ Math.max(0, pageVirtualizationOverscan)
31006
+ )
31007
+ } : void 0);
29588
31008
  const normalizedVisiblePageRange = React.useMemo(() => {
29589
31009
  if (pageCount <= 0) {
29590
31010
  return {
@@ -29612,7 +31032,8 @@ function DocxEditorViewer({
29612
31032
  pageCount
29613
31033
  ]);
29614
31034
  const initialPremeasureStartPageIndex = hasExternalVisiblePageRange ? normalizedVisiblePageRange.startPageIndex : 0;
29615
- const initialPremeasureEndPageIndex = hasExternalVisiblePageRange ? normalizedVisiblePageRange.endPageIndex : Math.min(pageCount - 1, INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT - 1);
31035
+ const initialPremeasurePageLimit = hasLargeTableLayoutSurface ? Math.min(2, INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT) : INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT;
31036
+ const initialPremeasureEndPageIndex = hasExternalVisiblePageRange ? normalizedVisiblePageRange.endPageIndex : Math.min(pageCount - 1, initialPremeasurePageLimit - 1);
29616
31037
  const measureAllPagesBeforeInitialReveal = hideDocumentUntilPaginationSettled && pageCount > 0 && initialPremeasureStartPageIndex === 0 && initialPremeasureEndPageIndex >= pageCount - 1;
29617
31038
  const visiblePageStartIndex = measureAllPagesBeforeInitialReveal ? 0 : hideDocumentUntilPaginationSettled ? initialPremeasureStartPageIndex : normalizedVisiblePageRange.startPageIndex;
29618
31039
  const visiblePageEndIndex = measureAllPagesBeforeInitialReveal ? pageCount - 1 : hideDocumentUntilPaginationSettled ? initialPremeasureEndPageIndex : normalizedVisiblePageRange.endPageIndex;
@@ -29626,20 +31047,64 @@ function DocxEditorViewer({
29626
31047
  }
29627
31048
  return indexes;
29628
31049
  }, [pageCount, visiblePageEndIndex, visiblePageStartIndex]);
31050
+ const visibleTableRowIndexesByNodeIndex = React.useMemo(() => {
31051
+ const rowsByNodeIndex = /* @__PURE__ */ new Map();
31052
+ const addRowIndex = (nodeIndex, rowIndex) => {
31053
+ const tableNode = editor.model.nodes[nodeIndex];
31054
+ if (!tableNode || tableNode.type !== "table" || rowIndex < 0 || rowIndex >= tableNode.rows.length) {
31055
+ return;
31056
+ }
31057
+ const existing = rowsByNodeIndex.get(nodeIndex);
31058
+ if (existing) {
31059
+ existing.add(rowIndex);
31060
+ } else {
31061
+ rowsByNodeIndex.set(nodeIndex, /* @__PURE__ */ new Set([rowIndex]));
31062
+ }
31063
+ };
31064
+ for (const pageIndex of visiblePageIndexes) {
31065
+ for (const segment of pageNodeSegmentsByPage[pageIndex] ?? []) {
31066
+ const tableNode = editor.model.nodes[segment.nodeIndex];
31067
+ if (!tableNode || tableNode.type !== "table") {
31068
+ continue;
31069
+ }
31070
+ if (segment.tableRowSlice) {
31071
+ addRowIndex(segment.nodeIndex, segment.tableRowSlice.rowIndex);
31072
+ continue;
31073
+ }
31074
+ if (segment.tableRowRange) {
31075
+ for (let rowIndex = segment.tableRowRange.startRowIndex; rowIndex < segment.tableRowRange.endRowIndex; rowIndex += 1) {
31076
+ addRowIndex(segment.nodeIndex, rowIndex);
31077
+ }
31078
+ continue;
31079
+ }
31080
+ for (let rowIndex = 0; rowIndex < tableNode.rows.length; rowIndex += 1) {
31081
+ addRowIndex(segment.nodeIndex, rowIndex);
31082
+ }
31083
+ }
31084
+ }
31085
+ return rowsByNodeIndex;
31086
+ }, [editor.model.nodes, pageNodeSegmentsByPage, visiblePageIndexes]);
29629
31087
  const paginationMeasurementEnabled = hideDocumentUntilPaginationSettled || postImportPaginationUnlocked;
29630
31088
  const visiblePagesHavePendingPaginationMeasurements = React.useMemo(() => {
29631
31089
  if (pageCount === 0) {
29632
31090
  return false;
29633
31091
  }
29634
31092
  for (const pageIndex of visiblePageIndexes) {
29635
- if (!Number.isFinite(measuredPageContentHeightByIndex[pageIndex])) {
31093
+ const pageSegments = pageNodeSegmentsByPage[pageIndex] ?? [];
31094
+ const pageContainsTableRowSlice = pageSegments.some(
31095
+ (segment) => Boolean(segment.tableRowSlice)
31096
+ );
31097
+ if (!Number.isFinite(measuredPageContentHeightByIndex[pageIndex]) && !(hasLargeTableLayoutSurface && pageContainsTableRowSlice)) {
29636
31098
  return true;
29637
31099
  }
29638
- for (const segment of pageNodeSegmentsByPage[pageIndex] ?? []) {
31100
+ for (const segment of pageSegments) {
29639
31101
  const tableNode = editor.model.nodes[segment.nodeIndex];
29640
31102
  if (!tableNode || tableNode.type !== "table") {
29641
31103
  continue;
29642
31104
  }
31105
+ if (segment.tableRowSlice) {
31106
+ continue;
31107
+ }
29643
31108
  const measuredHeights = tableMeasuredRowHeights[segment.nodeIndex];
29644
31109
  if (!measuredHeights || measuredHeights.length !== tableNode.rows.length) {
29645
31110
  return true;
@@ -29649,6 +31114,7 @@ function DocxEditorViewer({
29649
31114
  return false;
29650
31115
  }, [
29651
31116
  editor.model.nodes,
31117
+ hasLargeTableLayoutSurface,
29652
31118
  measuredPageContentHeightByIndex,
29653
31119
  pageCount,
29654
31120
  pageNodeSegmentsByPage,
@@ -30285,7 +31751,9 @@ function DocxEditorViewer({
30285
31751
  const footerElement = pageFooterElementsRef.current.get(pageIndex);
30286
31752
  const headerHeightPx = headerElement ? Math.max(
30287
31753
  0,
30288
- Math.round(headerElement.getBoundingClientRect().height / zoomScale)
31754
+ Math.round(
31755
+ headerElement.getBoundingClientRect().height / zoomScale
31756
+ )
30289
31757
  ) : 0;
30290
31758
  const docxFooterTopPx = resolveFooterNodesFloatingBoundaryTopPx(
30291
31759
  pageHeaderAndFooterNodes[pageIndex]?.footerNodes ?? [],
@@ -30351,7 +31819,9 @@ function DocxEditorViewer({
30351
31819
  bottomPx: rect.bottom,
30352
31820
  widthPx: rect.width,
30353
31821
  heightPx: rect.height,
30354
- ignore: !element.isConnected || Boolean(element.closest("[data-docx-image-location]")) || Boolean(
31822
+ ignore: !element.isConnected || Boolean(
31823
+ element.closest("[data-docx-image-location]")
31824
+ ) || Boolean(
30355
31825
  element.closest(
30356
31826
  `[${PAGE_CONTENT_MEASUREMENT_IGNORE_ATTRIBUTE}="true"]`
30357
31827
  )
@@ -30381,7 +31851,31 @@ function DocxEditorViewer({
30381
31851
  const nextMeasuredHeights = nextMeasuredPageDiagnostics.map(
30382
31852
  (diagnostics) => diagnostics.heightPx
30383
31853
  );
31854
+ const overlappingPageIndexes = nextMeasuredPageDiagnostics.reduce(
31855
+ (indexes, diagnostics, pageIndex) => {
31856
+ if (diagnostics.bodyOverrunsFooter) {
31857
+ indexes.push(pageIndex);
31858
+ }
31859
+ return indexes;
31860
+ },
31861
+ []
31862
+ );
31863
+ const nextMeasuredBodyFooterOverlapLatchState = resolveMeasuredBodyFooterOverlapLatchState({
31864
+ pageCount,
31865
+ targetPageCount: editor.model.metadata.documentPageCount,
31866
+ overlappingPageIndexes,
31867
+ previousSignature: measuredBodyFooterOverlapCandidateRef.current.signature,
31868
+ previousConsecutivePasses: measuredBodyFooterOverlapCandidateRef.current.consecutivePasses,
31869
+ stabilityThreshold: MEASURED_BODY_FOOTER_OVERLAP_STABILITY_THRESHOLD
31870
+ });
31871
+ measuredBodyFooterOverlapCandidateRef.current = {
31872
+ signature: nextMeasuredBodyFooterOverlapLatchState.signature,
31873
+ consecutivePasses: nextMeasuredBodyFooterOverlapLatchState.consecutivePasses
31874
+ };
30384
31875
  const frameId = window.requestAnimationFrame(() => {
31876
+ if (nextMeasuredBodyFooterOverlapLatchState.shouldLatch) {
31877
+ setHasMeasuredBodyFooterOverlap(true);
31878
+ }
30385
31879
  setMeasuredPageContentHeightByIndex((current) => {
30386
31880
  const stabilizedHeights = stabilizeMeasuredPageContentHeights(
30387
31881
  current,
@@ -30434,6 +31928,7 @@ function DocxEditorViewer({
30434
31928
  paginationMeasurementEnabled,
30435
31929
  paginationMeasurementEpoch,
30436
31930
  pageCount,
31931
+ editor.model.metadata.documentPageCount,
30437
31932
  pageNodeSegmentsByPage,
30438
31933
  pageNodeSegmentIdentityKeysByPage,
30439
31934
  pageSectionInfoByIndex,
@@ -30466,6 +31961,27 @@ function DocxEditorViewer({
30466
31961
  isInitialPaginationSettled,
30467
31962
  pageCount
30468
31963
  ]);
31964
+ React.useEffect(() => {
31965
+ if (!deferInitialPaginationPaint || !isInitialPaginationSettled || initialPaginationBackgroundRefinementUnlocked) {
31966
+ return;
31967
+ }
31968
+ if (typeof window === "undefined") {
31969
+ setInitialPaginationBackgroundRefinementUnlocked(true);
31970
+ return;
31971
+ }
31972
+ const timeoutId = window.setTimeout(() => {
31973
+ React.startTransition(() => {
31974
+ setInitialPaginationBackgroundRefinementUnlocked(true);
31975
+ });
31976
+ }, INITIAL_PAGINATION_BACKGROUND_REFINEMENT_DELAY_MS);
31977
+ return () => {
31978
+ window.clearTimeout(timeoutId);
31979
+ };
31980
+ }, [
31981
+ deferInitialPaginationPaint,
31982
+ initialPaginationBackgroundRefinementUnlocked,
31983
+ isInitialPaginationSettled
31984
+ ]);
30469
31985
  React.useEffect(() => {
30470
31986
  if (!deferInitialPaginationPaint || isInitialPaginationSettled) {
30471
31987
  return;
@@ -34684,10 +36200,14 @@ function DocxEditorViewer({
34684
36200
  if (node.type !== "table") {
34685
36201
  return;
34686
36202
  }
36203
+ const visibleRowIndexes = visibleTableRowIndexesByNodeIndex.get(nodeIndex);
36204
+ if (!visibleRowIndexes || visibleRowIndexes.size === 0) {
36205
+ return;
36206
+ }
34687
36207
  const measuredByRowIndex = /* @__PURE__ */ new Map();
34688
36208
  const recordMeasuredRow = (rowIndex, rowHeightPx) => {
34689
36209
  const normalizedRowIndex = Math.max(0, Math.round(rowIndex));
34690
- if (normalizedRowIndex >= node.rows.length) {
36210
+ if (normalizedRowIndex >= node.rows.length || !visibleRowIndexes.has(normalizedRowIndex)) {
34691
36211
  return;
34692
36212
  }
34693
36213
  const normalizedHeight = normalizeMeasuredTableRowHeightPx(rowHeightPx);
@@ -34720,7 +36240,8 @@ function DocxEditorViewer({
34720
36240
  );
34721
36241
  });
34722
36242
  }
34723
- const rowCells = document.querySelectorAll(
36243
+ const measurementRoot = viewerRootRef.current ?? document;
36244
+ const rowCells = measurementRoot.querySelectorAll(
34724
36245
  `[data-docx-table-cell='true'][data-docx-table-index='${nodeIndex}'][data-docx-row-index]`
34725
36246
  );
34726
36247
  rowCells.forEach((cellElement) => {
@@ -34751,7 +36272,8 @@ function DocxEditorViewer({
34751
36272
  node,
34752
36273
  pageContentWidthPxByNodeIndex.get(nodeIndex),
34753
36274
  editor.model.metadata.numberingDefinitions,
34754
- docGridLinePitchPxByNodeIndex.get(nodeIndex)
36275
+ docGridLinePitchPxByNodeIndex.get(nodeIndex),
36276
+ pageContentHeightPxByNodeIndex.get(nodeIndex)
34755
36277
  );
34756
36278
  const previousMeasuredRowHeights = tableMeasuredRowHeights[nodeIndex];
34757
36279
  const measuredHeights = node.rows.map((_, rowIndex) => {
@@ -34817,8 +36339,7 @@ function DocxEditorViewer({
34817
36339
  tableColumnWidths,
34818
36340
  tableRowHeights,
34819
36341
  tableDraftLayoutEpoch,
34820
- visiblePageEndIndex,
34821
- visiblePageStartIndex
36342
+ visibleTableRowIndexesByNodeIndex
34822
36343
  ]);
34823
36344
  const normalizeResizableHeights = React.useCallback(
34824
36345
  (rowHeights) => {
@@ -36278,6 +37799,29 @@ function DocxEditorViewer({
36278
37799
  `${keyPrefix}-fragment-image-${lineIndex}-${run.key}-${overlapStart}`
36279
37800
  );
36280
37801
  }
37802
+ if (run.kind === "tab" && Number.isFinite(run.tabWidthPx)) {
37803
+ const overlapRatio = run.endOffset > run.startOffset ? (overlapEnd - overlapStart) / (run.endOffset - run.startOffset) : 1;
37804
+ const tabWidthPx = Math.max(
37805
+ 1,
37806
+ Math.round(run.tabWidthPx * overlapRatio)
37807
+ );
37808
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
37809
+ "span",
37810
+ {
37811
+ "data-docx-tab-char": "true",
37812
+ style: {
37813
+ ...runStyleToCss(run.style, documentContentTheme),
37814
+ display: "inline-block",
37815
+ width: tabWidthPx,
37816
+ minWidth: tabWidthPx,
37817
+ whiteSpace: "pre",
37818
+ lineHeight: "1em"
37819
+ },
37820
+ children: "\xA0"
37821
+ },
37822
+ `${keyPrefix}-fragment-tab-${lineIndex}-${run.key}-${overlapStart}`
37823
+ );
37824
+ }
36281
37825
  const slice = run.text.slice(
36282
37826
  overlapStart - run.startOffset,
36283
37827
  overlapEnd - run.startOffset
@@ -39113,6 +40657,488 @@ function DocxEditorViewer({
39113
40657
  boxSizing: "border-box",
39114
40658
  overflow: floatingMovePreview || dropCapMovePreview ? "visible" : "clip"
39115
40659
  };
40660
+ const tableCellParagraphSliceLayoutCacheRef = React.useRef(
40661
+ /* @__PURE__ */ new Map()
40662
+ );
40663
+ const tableCellParagraphFlowLayoutCacheRef = React.useRef(
40664
+ /* @__PURE__ */ new Map()
40665
+ );
40666
+ const tableCellParagraphSlicePlanCacheRef = React.useRef(
40667
+ /* @__PURE__ */ new Map()
40668
+ );
40669
+ const tableCellParagraphSliceSignatureCacheRef = React.useRef(
40670
+ /* @__PURE__ */ new WeakMap()
40671
+ );
40672
+ React.useEffect(() => {
40673
+ tableCellParagraphSliceLayoutCacheRef.current.clear();
40674
+ tableCellParagraphFlowLayoutCacheRef.current.clear();
40675
+ tableCellParagraphSlicePlanCacheRef.current.clear();
40676
+ tableCellParagraphSliceSignatureCacheRef.current = /* @__PURE__ */ new WeakMap();
40677
+ }, [paragraphStructureEpoch]);
40678
+ const resolveTableCellParagraphSliceSignature = (cell) => {
40679
+ const cellKey = cell;
40680
+ const cached = tableCellParagraphSliceSignatureCacheRef.current.get(cellKey);
40681
+ if (cached) {
40682
+ return cached;
40683
+ }
40684
+ const signature = [
40685
+ JSON.stringify(cell.style ?? null),
40686
+ ...cell.nodes.map(
40687
+ (paragraph, paragraphIndex) => isParagraphCellContentNode(paragraph) ? `${paragraphIndex}:${paragraph.sourceXml ?? paragraphText(paragraph)}` : `${paragraphIndex}:${paragraph.type}`
40688
+ )
40689
+ ].join("");
40690
+ tableCellParagraphSliceSignatureCacheRef.current.set(cellKey, signature);
40691
+ return signature;
40692
+ };
40693
+ const resolveTableCellParagraphSlicePlans = (params) => {
40694
+ const {
40695
+ cell,
40696
+ rowHeightPx,
40697
+ sliceStartPx,
40698
+ sliceHeightPx,
40699
+ cellContentWidthPx,
40700
+ tableCellMarginTwips,
40701
+ applyWordTableDefaults,
40702
+ docGridLinePitchPx
40703
+ } = params;
40704
+ if (!cell.nodes.every(isParagraphCellContentNode)) {
40705
+ return void 0;
40706
+ }
40707
+ const numberingDefinitions = editor.model.metadata.numberingDefinitions;
40708
+ const cellSignature = resolveTableCellParagraphSliceSignature(cell);
40709
+ const flowLayoutCacheKey = [
40710
+ cellContentWidthPx,
40711
+ JSON.stringify(tableCellMarginTwips ?? null),
40712
+ applyWordTableDefaults ? 1 : 0,
40713
+ docGridLinePitchPx ?? 0,
40714
+ cellSignature
40715
+ ].join(":");
40716
+ let flowLayout = tableCellParagraphFlowLayoutCacheRef.current.get(flowLayoutCacheKey);
40717
+ if (!flowLayout) {
40718
+ const contentHeightPx = estimateTableCellContentHeightPx(
40719
+ cell.nodes,
40720
+ cellContentWidthPx,
40721
+ numberingDefinitions,
40722
+ applyWordTableDefaults,
40723
+ docGridLinePitchPx
40724
+ );
40725
+ const paddingPx = resolveTableSpacingPaddingPx(
40726
+ mergeTableSpacing(tableCellMarginTwips, cell.style?.marginTwips)
40727
+ );
40728
+ let paragraphTopPx = paddingPx.top;
40729
+ const entries = [];
40730
+ for (let paragraphIndex = 0; paragraphIndex < cell.nodes.length; paragraphIndex += 1) {
40731
+ const paragraph = cell.nodes[paragraphIndex];
40732
+ if (!paragraph) {
40733
+ continue;
40734
+ }
40735
+ const disableDocGridSnap = paragraphDocGridSnapState(paragraph) === "disable";
40736
+ const layoutCacheKey2 = `${cellContentWidthPx}:${applyWordTableDefaults ? 1 : 0}:${docGridLinePitchPx ?? 0}:${paragraphIndex}:${paragraph.sourceXml ?? paragraphText(paragraph)}`;
40737
+ let layoutEntry = tableCellParagraphSliceLayoutCacheRef.current.get(layoutCacheKey2);
40738
+ if (!layoutEntry) {
40739
+ const paragraphForLayout = wordLikeTableCellParagraph(
40740
+ paragraph,
40741
+ applyWordTableDefaults
40742
+ );
40743
+ const paragraphHeightPx2 = estimateParagraphHeightPx(
40744
+ paragraphForLayout,
40745
+ cellContentWidthPx,
40746
+ numberingDefinitions,
40747
+ docGridLinePitchPx,
40748
+ disableDocGridSnap
40749
+ );
40750
+ const suppressTopSpacing = paragraphIndex === 0 && suppressFirstTableCellParagraphTopSpacing(paragraph);
40751
+ const beforeSpacingPx = suppressTopSpacing ? 0 : twipsToPixels(paragraphForLayout.style?.spacing?.beforeTwips) ?? 0;
40752
+ const topBorderInsetPx = paragraphBorderInsetPx(
40753
+ paragraphForLayout.style?.borders?.top
40754
+ );
40755
+ const lineHeightPx = Math.max(
40756
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
40757
+ estimateParagraphLineHeightPx(
40758
+ paragraphForLayout,
40759
+ docGridLinePitchPx,
40760
+ disableDocGridSnap
40761
+ )
40762
+ );
40763
+ const pretextSource = buildParagraphPretextLayoutSource(
40764
+ paragraphForLayout,
40765
+ {
40766
+ allowExplicitLineBreakText: true,
40767
+ expandTabsForLayout: true
40768
+ }
40769
+ );
40770
+ const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
40771
+ paragraphForLayout,
40772
+ cellContentWidthPx,
40773
+ numberingDefinitions
40774
+ );
40775
+ const pretextLayout = pretextSource ? layoutParagraphPretextSource(
40776
+ paragraphForLayout,
40777
+ pretextSource,
40778
+ paragraphTextWidthPx,
40779
+ lineHeightPx,
40780
+ []
40781
+ ) : void 0;
40782
+ const totalLineCount = Math.max(
40783
+ 1,
40784
+ pretextLayout?.lineCount ?? paragraphLineCountWithinWidth(
40785
+ paragraphForLayout,
40786
+ cellContentWidthPx,
40787
+ numberingDefinitions
40788
+ )
40789
+ );
40790
+ layoutEntry = {
40791
+ paragraphForLayout,
40792
+ paragraphHeightPx: paragraphHeightPx2,
40793
+ textTopOffsetPx: beforeSpacingPx + topBorderInsetPx,
40794
+ lineHeightPx,
40795
+ lineTopOffsetsPx: pretextLayout ? pretextLayout.lines.map(
40796
+ (line) => Math.max(0, Math.round(line.y))
40797
+ ) : Array.from(
40798
+ { length: totalLineCount },
40799
+ (_, lineIndex) => lineIndex * lineHeightPx
40800
+ ),
40801
+ pretextSource: pretextSource ?? void 0,
40802
+ pretextLayout: pretextLayout ?? void 0
40803
+ };
40804
+ tableCellParagraphSliceLayoutCacheRef.current.set(
40805
+ layoutCacheKey2,
40806
+ layoutEntry
40807
+ );
40808
+ }
40809
+ const paragraphHeightPx = layoutEntry.paragraphHeightPx;
40810
+ const textTopPx = paragraphTopPx + layoutEntry.textTopOffsetPx;
40811
+ const textBottomPx = textTopPx + (layoutEntry.pretextLayout ? wrappedPretextParagraphBlockHeightPx(layoutEntry.pretextLayout) : layoutEntry.lineHeightPx * layoutEntry.lineTopOffsetsPx.length);
40812
+ const paragraphBottomPx = resolveTableCellParagraphVisualBottomPx({
40813
+ paragraphTopPx,
40814
+ paragraphHeightPx,
40815
+ textBottomPx
40816
+ });
40817
+ entries.push({
40818
+ paragraph,
40819
+ paragraphIndex,
40820
+ paragraphTopPx,
40821
+ textTopPx,
40822
+ paragraphBottomPx,
40823
+ layoutEntry
40824
+ });
40825
+ paragraphTopPx = paragraphBottomPx;
40826
+ }
40827
+ flowLayout = {
40828
+ contentHeightPx,
40829
+ paddingPx,
40830
+ entries
40831
+ };
40832
+ tableCellParagraphFlowLayoutCacheRef.current.set(
40833
+ flowLayoutCacheKey,
40834
+ flowLayout
40835
+ );
40836
+ }
40837
+ const availableContentHeightPx = Math.max(
40838
+ 0,
40839
+ rowHeightPx - flowLayout.paddingPx.top - flowLayout.paddingPx.bottom
40840
+ );
40841
+ const extraVerticalSpacePx = Math.max(
40842
+ 0,
40843
+ availableContentHeightPx - flowLayout.contentHeightPx
40844
+ );
40845
+ const verticalOffsetPx = cell.style?.verticalAlign === "center" ? Math.round(extraVerticalSpacePx / 2) : cell.style?.verticalAlign === "bottom" ? extraVerticalSpacePx : 0;
40846
+ const sliceBottomPx = sliceStartPx + sliceHeightPx;
40847
+ const slicePlanCacheKey = [
40848
+ flowLayoutCacheKey,
40849
+ rowHeightPx,
40850
+ sliceStartPx,
40851
+ sliceHeightPx
40852
+ ].join(":");
40853
+ const cachedPlans = tableCellParagraphSlicePlanCacheRef.current.get(slicePlanCacheKey);
40854
+ if (cachedPlans) {
40855
+ return cachedPlans;
40856
+ }
40857
+ const plans = [];
40858
+ let firstCandidateIndex = 0;
40859
+ let low = 0;
40860
+ let high = flowLayout.entries.length;
40861
+ while (low < high) {
40862
+ const mid = Math.floor((low + high) / 2);
40863
+ const entryBottomPx = (flowLayout.entries[mid]?.paragraphBottomPx ?? 0) + verticalOffsetPx;
40864
+ if (entryBottomPx <= sliceStartPx + PAGE_OVERFLOW_TOLERANCE_PX) {
40865
+ low = mid + 1;
40866
+ } else {
40867
+ high = mid;
40868
+ }
40869
+ }
40870
+ firstCandidateIndex = low;
40871
+ for (let entryIndex = firstCandidateIndex; entryIndex < flowLayout.entries.length; entryIndex += 1) {
40872
+ const entry = flowLayout.entries[entryIndex];
40873
+ if (!entry) {
40874
+ continue;
40875
+ }
40876
+ const paragraphTopPx = entry.paragraphTopPx + verticalOffsetPx;
40877
+ const textTopPx = entry.textTopPx + verticalOffsetPx;
40878
+ const paragraphBottomPx = entry.paragraphBottomPx + verticalOffsetPx;
40879
+ if (paragraphTopPx >= sliceBottomPx - PAGE_OVERFLOW_TOLERANCE_PX) {
40880
+ break;
40881
+ }
40882
+ const intersectsParagraph = sliceBottomPx > paragraphTopPx + PAGE_OVERFLOW_TOLERANCE_PX && sliceStartPx < paragraphBottomPx - PAGE_OVERFLOW_TOLERANCE_PX;
40883
+ if (!intersectsParagraph) {
40884
+ continue;
40885
+ }
40886
+ const fullyVisible = tableCellParagraphFitsFullyWithinSlice({
40887
+ sliceStartPx,
40888
+ sliceBottomPx,
40889
+ paragraphTopPx,
40890
+ paragraphBottomPx
40891
+ });
40892
+ if (fullyVisible) {
40893
+ plans.push({
40894
+ paragraph: entry.paragraph,
40895
+ paragraphIndex: entry.paragraphIndex,
40896
+ topPx: Math.max(0, Math.round(paragraphTopPx - sliceStartPx)),
40897
+ layoutEntry: entry.layoutEntry
40898
+ });
40899
+ continue;
40900
+ }
40901
+ const paragraphLineRange = resolveLineRangeWithinVerticalSlice(
40902
+ entry.layoutEntry.lineTopOffsetsPx,
40903
+ entry.layoutEntry.lineHeightPx,
40904
+ sliceStartPx - textTopPx,
40905
+ sliceBottomPx - textTopPx
40906
+ );
40907
+ if (!paragraphLineRange) {
40908
+ continue;
40909
+ }
40910
+ const lineRangeTopPx = paragraphLineRange.startLineIndex > 0 ? textTopPx + entry.layoutEntry.lineTopOffsetsPx[paragraphLineRange.startLineIndex] : paragraphTopPx;
40911
+ plans.push({
40912
+ paragraph: entry.paragraph,
40913
+ paragraphIndex: entry.paragraphIndex,
40914
+ topPx: Math.max(0, Math.round(lineRangeTopPx - sliceStartPx)),
40915
+ layoutEntry: entry.layoutEntry,
40916
+ paragraphLineRange
40917
+ });
40918
+ }
40919
+ tableCellParagraphSlicePlanCacheRef.current.set(slicePlanCacheKey, plans);
40920
+ return plans;
40921
+ };
40922
+ const renderSlicedTableCellParagraph = (params) => {
40923
+ const {
40924
+ paragraph,
40925
+ paragraphIndex,
40926
+ tableIndex,
40927
+ rowIndex,
40928
+ cellIndex,
40929
+ contentIndex,
40930
+ cellContentWidthPx,
40931
+ applyWordTableDefaults,
40932
+ docGridLinePitchPx,
40933
+ layoutEntry,
40934
+ paragraphLineRange
40935
+ } = params;
40936
+ const numberingDefinitions = editor.model.metadata.numberingDefinitions;
40937
+ const paragraphForLayout = layoutEntry.paragraphForLayout;
40938
+ const hasPartialLineRange = paragraphSegmentHasPartialLineRange(paragraphLineRange);
40939
+ const paragraphSegmentLineHeightPx = Math.max(
40940
+ 1,
40941
+ paragraphLineRange?.lineHeightPx ?? layoutEntry.lineHeightPx
40942
+ );
40943
+ const paragraphSegmentStartLine = paragraphLineRange?.startLineIndex ?? 0;
40944
+ const paragraphSegmentEndLine = paragraphLineRange?.endLineIndex ?? paragraphLineRange?.totalLineCount ?? 1;
40945
+ const paragraphSegmentTotalLines = paragraphLineRange?.totalLineCount ?? Math.max(1, paragraphSegmentEndLine);
40946
+ const paragraphSegmentVisibleLineCount = Math.max(
40947
+ 1,
40948
+ paragraphSegmentEndLine - paragraphSegmentStartLine
40949
+ );
40950
+ const paragraphSegmentVisibleHeightPx = paragraphSegmentVisibleLineCount * paragraphSegmentLineHeightPx;
40951
+ const paragraphSegmentTranslateYPx = paragraphSegmentStartLine * paragraphSegmentLineHeightPx;
40952
+ const location = {
40953
+ kind: "table-cell",
40954
+ tableIndex,
40955
+ rowIndex,
40956
+ cellIndex,
40957
+ paragraphIndex
40958
+ };
40959
+ const numberingLabel = paragraphNumberingLabels.get(
40960
+ paragraphLocationKey(location)
40961
+ );
40962
+ const paragraphRenderTextWidthPx = paragraphAvailableTextWidthPx(
40963
+ paragraphForLayout,
40964
+ cellContentWidthPx,
40965
+ numberingDefinitions
40966
+ );
40967
+ const pretextParagraphLayout = hasPartialLineRange && layoutEntry.pretextSource ? layoutEntry.pretextLayout && Math.abs(paragraphSegmentLineHeightPx - layoutEntry.lineHeightPx) <= 1 ? layoutEntry.pretextLayout : layoutParagraphPretextSource(
40968
+ paragraphForLayout,
40969
+ layoutEntry.pretextSource,
40970
+ paragraphRenderTextWidthPx,
40971
+ paragraphSegmentLineHeightPx,
40972
+ []
40973
+ ) : void 0;
40974
+ const pretextParagraphTotalLines = Math.max(
40975
+ 0,
40976
+ pretextParagraphLayout?.lineCount ?? 0
40977
+ );
40978
+ const pretextParagraphSliceStartLine = hasPartialLineRange && paragraphLineRange && pretextParagraphTotalLines > 0 ? Math.max(
40979
+ 0,
40980
+ Math.min(
40981
+ paragraphLineRange.startLineIndex,
40982
+ pretextParagraphTotalLines
40983
+ )
40984
+ ) : void 0;
40985
+ const pretextParagraphSliceEndLine = hasPartialLineRange && paragraphLineRange && pretextParagraphTotalLines > 0 && pretextParagraphSliceStartLine !== void 0 ? Math.max(
40986
+ pretextParagraphSliceStartLine,
40987
+ Math.min(
40988
+ paragraphLineRange.endLineIndex,
40989
+ pretextParagraphTotalLines
40990
+ )
40991
+ ) : void 0;
40992
+ const pretextParagraphSliceLayout = hasPartialLineRange && pretextParagraphLayout && pretextParagraphSliceStartLine !== void 0 && pretextParagraphSliceEndLine !== void 0 && pretextParagraphLayout.lineCount > 0 ? sliceLayoutToLineRange(
40993
+ pretextParagraphLayout,
40994
+ pretextParagraphSliceStartLine,
40995
+ pretextParagraphSliceEndLine
40996
+ ) : void 0;
40997
+ const shouldRenderParagraphSegmentWithPretext = hasPartialLineRange && Boolean(layoutEntry.pretextSource) && Boolean(pretextParagraphLayout) && pretextParagraphTotalLines > 0;
40998
+ const paragraphSegmentClipBleed = shouldRenderParagraphSegmentWithPretext ? resolveParagraphSegmentClipBleedPx(paragraphLineRange) : resolveFallbackParagraphSegmentClipBleedPx(
40999
+ paragraphForLayout,
41000
+ paragraphLineRange
41001
+ );
41002
+ const paragraphSegmentClipBleedTopPx = paragraphSegmentClipBleed.topPx;
41003
+ const paragraphSegmentClipBleedBottomPx = paragraphSegmentClipBleed.bottomPx;
41004
+ const pretextSegmentNumberingMarkerBoxWidthPx = numberingLabel && paragraphSegmentStartLine === 0 ? resolveNumberingMarkerBoxWidthPx(
41005
+ paragraph,
41006
+ numberingDefinitions,
41007
+ numberingLabel
41008
+ ) ?? Math.max(
41009
+ 16,
41010
+ Math.ceil(
41011
+ measureTextWidthPx2(
41012
+ numberingLabel.imageSrc ? numberingLabel.trailingText ?? "" : numberingLabel.text ?? "",
41013
+ numberingLabel.style,
41014
+ paragraphBaseFontSizePx(paragraph)
41015
+ )
41016
+ ) + (numberingLabel.imageSrc ? Math.ceil(numberingLabel.imageWidthPx ?? 12) + 2 : 0) + 4
41017
+ ) : void 0;
41018
+ const pretextSegmentNumberingMarkerNode = shouldRenderParagraphSegmentWithPretext && numberingLabel && paragraphSegmentStartLine === 0 && Number.isFinite(pretextSegmentNumberingMarkerBoxWidthPx) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41019
+ "span",
41020
+ {
41021
+ contentEditable: false,
41022
+ "data-docx-numbering-label": "true",
41023
+ style: {
41024
+ ...numberingMarkerStyle(
41025
+ paragraph,
41026
+ numberingDefinitions,
41027
+ numberingLabel,
41028
+ numberingLabel.style ? runStyleToCss(numberingLabel.style, documentContentTheme) : void 0,
41029
+ documentContentTheme
41030
+ ),
41031
+ position: "absolute",
41032
+ left: -Math.round(
41033
+ pretextSegmentNumberingMarkerBoxWidthPx
41034
+ ),
41035
+ top: 0,
41036
+ marginRight: 0,
41037
+ zIndex: 1,
41038
+ pointerEvents: "none"
41039
+ },
41040
+ children: numberingLabel.imageSrc ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
41041
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41042
+ "img",
41043
+ {
41044
+ src: numberingLabel.imageSrc,
41045
+ alt: "",
41046
+ "aria-hidden": "true",
41047
+ draggable: false,
41048
+ style: {
41049
+ display: "inline-block",
41050
+ verticalAlign: "text-bottom",
41051
+ width: numberingLabel.imageWidthPx ?? 12,
41052
+ height: numberingLabel.imageHeightPx ?? 12,
41053
+ marginRight: 2,
41054
+ filter: documentContentFilter
41055
+ }
41056
+ }
41057
+ ),
41058
+ numberingLabel.trailingText ?? ""
41059
+ ] }) : numberingLabel.text ?? ""
41060
+ },
41061
+ `table-cell-${tableIndex}-${rowIndex}-${cellIndex}-${paragraphIndex}-numbering-marker-${paragraphSegmentStartLine}`
41062
+ ) : void 0;
41063
+ const baseParagraphStyle = tableCellParagraphBlockStyle(
41064
+ paragraph,
41065
+ numberingDefinitions,
41066
+ headingStyles,
41067
+ paragraphIndex,
41068
+ applyWordTableDefaults,
41069
+ docGridLinePitchPx
41070
+ );
41071
+ const paragraphStyle = {
41072
+ ...baseParagraphStyle,
41073
+ ...hasPartialLineRange ? {
41074
+ marginTop: paragraphSegmentStartLine === 0 ? baseParagraphStyle.marginTop : 0,
41075
+ marginBottom: paragraphSegmentEndLine >= paragraphSegmentTotalLines ? baseParagraphStyle.marginBottom : 0
41076
+ } : void 0,
41077
+ outline: "none"
41078
+ };
41079
+ const fallbackParagraphRuns = renderInteractiveParagraphRuns(
41080
+ paragraph,
41081
+ `body-cell-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
41082
+ location
41083
+ );
41084
+ const renderedInteractiveParagraphContent = shouldRenderParagraphSegmentWithPretext ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41085
+ "div",
41086
+ {
41087
+ style: {
41088
+ minHeight: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
41089
+ marginTop: -paragraphSegmentClipBleedTopPx,
41090
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
41091
+ paddingTop: paragraphSegmentClipBleedTopPx,
41092
+ paddingBottom: paragraphSegmentClipBleedBottomPx,
41093
+ overflow: "visible"
41094
+ },
41095
+ children: layoutEntry.pretextSource && pretextParagraphSliceLayout && pretextParagraphSliceLayout.lineCount > 0 ? renderWrappedPretextParagraph({
41096
+ location,
41097
+ keyPrefix: `body-cell-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}-lines-${paragraphSegmentStartLine}-${paragraphSegmentEndLine}`,
41098
+ source: layoutEntry.pretextSource,
41099
+ layout: pretextParagraphSliceLayout,
41100
+ lineHeightPx: paragraphSegmentLineHeightPx,
41101
+ baseTextStyle: firstRunStyle(paragraph),
41102
+ blockHeightPx: pretextParagraphSliceLayout.height,
41103
+ obstacleNodes: pretextSegmentNumberingMarkerNode
41104
+ }) : null
41105
+ }
41106
+ ) : hasPartialLineRange ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41107
+ "div",
41108
+ {
41109
+ style: {
41110
+ height: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
41111
+ marginTop: -paragraphSegmentClipBleedTopPx,
41112
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
41113
+ overflow: "hidden"
41114
+ },
41115
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41116
+ "div",
41117
+ {
41118
+ style: {
41119
+ transform: `translateY(-${paragraphSegmentTranslateYPx - paragraphSegmentClipBleedTopPx}px)`
41120
+ },
41121
+ children: fallbackParagraphRuns
41122
+ }
41123
+ )
41124
+ }
41125
+ ) : fallbackParagraphRuns;
41126
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41127
+ "div",
41128
+ {
41129
+ "data-docx-paragraph-host": "true",
41130
+ "data-docx-paragraph-kind": "table-cell",
41131
+ "data-docx-table-index": tableIndex,
41132
+ "data-docx-row-index": rowIndex,
41133
+ "data-docx-cell-index": cellIndex,
41134
+ "data-docx-paragraph-index": paragraphIndex,
41135
+ "data-docx-table-paragraph-index": paragraphIndex,
41136
+ style: paragraphStyle,
41137
+ children: renderedInteractiveParagraphContent
41138
+ },
41139
+ `body-cell-slice-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}`
41140
+ );
41141
+ };
39116
41142
  const renderDocumentNode = (node, nodeIndex, tableRowRange, tableRowSlice, paragraphLineRange, options) => {
39117
41143
  const nodeDocGridLinePitchPx = docGridLinePitchPxByNodeIndex.get(nodeIndex);
39118
41144
  const nodeContentWidthPx = Math.max(
@@ -39150,7 +41176,7 @@ function DocxEditorViewer({
39150
41176
  paragraphLineRange
39151
41177
  );
39152
41178
  const paragraphHasActiveEditableSegment = activeEditableParagraphSegment?.nodeIndex === nodeIndex;
39153
- const shouldTrackParagraphElement = !hasPartialLineRange || paragraphSegmentIsActiveEditable || !paragraphHasActiveEditableSegment && paragraphSegmentStartLine === 0;
41179
+ const shouldTrackParagraphElement = options?.suppressParagraphElementTracking === true ? false : !hasPartialLineRange || paragraphSegmentIsActiveEditable || !paragraphHasActiveEditableSegment && paragraphSegmentStartLine === 0;
39154
41180
  const isManualPageBreakParagraph = paragraphIsOnlyExplicitPageBreak2(node);
39155
41181
  const paragraphContentWidthPx = nodeContentWidthPx;
39156
41182
  const paragraphRenderTextWidthPx = paragraphAvailableTextWidthPx(
@@ -39159,7 +41185,8 @@ function DocxEditorViewer({
39159
41185
  editor.model.metadata.numberingDefinitions
39160
41186
  );
39161
41187
  const pretextParagraphSource = hasPartialLineRange ? buildParagraphPretextLayoutSource(node, {
39162
- allowExplicitLineBreakText: true
41188
+ allowExplicitLineBreakText: true,
41189
+ expandTabsForLayout: true
39163
41190
  }) : void 0;
39164
41191
  const pretextParagraphLayout = hasPartialLineRange && pretextParagraphSource ? layoutParagraphPretextSource(
39165
41192
  node,
@@ -39254,7 +41281,13 @@ function DocxEditorViewer({
39254
41281
  },
39255
41282
  `node-${nodeIndex}-numbering-marker-${paragraphSegmentStartLine}`
39256
41283
  ) : void 0;
39257
- const editable = !hasImage && !isReadOnly && (!hasPartialLineRange || paragraphSegmentIsActiveEditable) && !isManualPageBreakParagraph;
41284
+ const resolvedBeforeSpacingPx = Number.isFinite(
41285
+ options?.overrideBeforeSpacingPx
41286
+ ) ? Math.max(0, Math.round(options?.overrideBeforeSpacingPx)) : void 0;
41287
+ const resolvedAfterSpacingPx = Number.isFinite(
41288
+ options?.overrideAfterSpacingPx
41289
+ ) ? Math.max(0, Math.round(options?.overrideAfterSpacingPx)) : void 0;
41290
+ const editable = !hasImage && !isReadOnly && options?.forceReadOnly !== true && (!hasPartialLineRange || paragraphSegmentIsActiveEditable) && !isManualPageBreakParagraph;
39258
41291
  const resolvedPageLayout = options?.pageLayout ?? documentLayout;
39259
41292
  const paragraphContainsLikelyFullPageCoverImage = node.children.some(
39260
41293
  (child) => child.type === "image" && shouldRenderAbsoluteFloatingImage(child) && likelyFullPageCoverImageRelativeToContentBox(
@@ -39324,8 +41357,11 @@ function DocxEditorViewer({
39324
41357
  const paragraphStyle = {
39325
41358
  ...baseParagraphStyle,
39326
41359
  ...hasPartialLineRange ? {
39327
- marginTop: paragraphSegmentStartLine === 0 ? beforeSpacingPx : 0,
39328
- marginBottom: paragraphSegmentEndLine >= paragraphSegmentTotalLines ? afterSpacingPx : 0
41360
+ marginTop: paragraphSegmentStartLine === 0 ? resolvedBeforeSpacingPx ?? beforeSpacingPx : 0,
41361
+ marginBottom: paragraphSegmentEndLine >= paragraphSegmentTotalLines ? resolvedAfterSpacingPx ?? afterSpacingPx : 0
41362
+ } : resolvedBeforeSpacingPx !== void 0 || resolvedAfterSpacingPx !== void 0 ? {
41363
+ ...resolvedBeforeSpacingPx !== void 0 ? { marginTop: resolvedBeforeSpacingPx } : void 0,
41364
+ ...resolvedAfterSpacingPx !== void 0 ? { marginBottom: resolvedAfterSpacingPx } : void 0
39329
41365
  } : void 0,
39330
41366
  ...letterheadStyleAdjustments ?? void 0,
39331
41367
  ...options?.suppressLetterheadColumnLayout && options?.isFirstInLetterheadColumn ? { marginTop: 0 } : void 0,
@@ -39364,7 +41400,8 @@ function DocxEditorViewer({
39364
41400
  {
39365
41401
  style: {
39366
41402
  minHeight: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
39367
- marginBottom: -(paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx),
41403
+ marginTop: -paragraphSegmentClipBleedTopPx,
41404
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
39368
41405
  paddingTop: paragraphSegmentClipBleedTopPx,
39369
41406
  paddingBottom: paragraphSegmentClipBleedBottomPx,
39370
41407
  overflow: "visible"
@@ -39388,7 +41425,8 @@ function DocxEditorViewer({
39388
41425
  {
39389
41426
  style: {
39390
41427
  height: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
39391
- marginBottom: -(paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx),
41428
+ marginTop: -paragraphSegmentClipBleedTopPx,
41429
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
39392
41430
  overflow: "hidden"
39393
41431
  },
39394
41432
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -39974,7 +42012,7 @@ ${currentText.slice(end)}`;
39974
42012
  },
39975
42013
  children: !editable ? renderedInteractiveParagraphContent : null
39976
42014
  },
39977
- paragraphLineRange ? `epoch-${paragraphStructureEpoch}-node-${nodeIndex}-lines-${paragraphSegmentStartLine}-${paragraphSegmentEndLine}` : `epoch-${paragraphStructureEpoch}-node-${nodeIndex}`
42015
+ paragraphLineRange ? `epoch-${paragraphStructureEpoch}-node-${nodeIndex}-lines-${paragraphSegmentStartLine}-${paragraphSegmentEndLine}${options?.syntheticKeySuffix ? `-${options.syntheticKeySuffix}` : ""}` : `epoch-${paragraphStructureEpoch}-node-${nodeIndex}${options?.syntheticKeySuffix ? `-${options.syntheticKeySuffix}` : ""}`
39978
42016
  );
39979
42017
  }
39980
42018
  const tableRowSliceOffsetPxForWrapper = tableRowSlice ? Math.max(0, Math.round(tableRowSlice.startOffsetPx)) : 0;
@@ -40007,7 +42045,7 @@ ${currentText.slice(end)}`;
40007
42045
  paddingTop: tableRowSliceTopBleedPxForWrapper,
40008
42046
  paddingBottom: tableRowSliceBottomBleedPxForWrapper,
40009
42047
  boxSizing: "border-box",
40010
- overflow: "clip"
42048
+ overflow: "visible"
40011
42049
  } : void 0
40012
42050
  },
40013
42051
  onPointerEnter: () => {
@@ -40040,11 +42078,12 @@ ${currentText.slice(end)}`;
40040
42078
  },
40041
42079
  children: (() => {
40042
42080
  const tableIndentPx = twipsToSignedPixels(node.style?.indentTwips) ?? 0;
42081
+ const columnCount = tableColumnCount(node);
42082
+ const collapsedHorizontalBorderBleedPx = resolveCollapsedTableHorizontalOuterBleedPx(node, columnCount);
40043
42083
  const maxTableWidthPx = Math.max(
40044
42084
  120,
40045
- nodeContentWidthPx - tableIndentPx
42085
+ nodeContentWidthPx - tableIndentPx - collapsedHorizontalBorderBleedPx
40046
42086
  );
40047
- const columnCount = tableColumnCount(node);
40048
42087
  const tableWidthPx = twipsToPixels(node.style?.widthTwips);
40049
42088
  const hasStoredColumnWidths = (tableColumnWidths[nodeIndex]?.length ?? 0) === columnCount;
40050
42089
  const rawColumnWidthsPx = resolveTableColumnWidths(
@@ -40137,6 +42176,7 @@ ${currentText.slice(end)}`;
40137
42176
  "span",
40138
42177
  {
40139
42178
  contentEditable: false,
42179
+ "data-docx-pagination-ignore": "true",
40140
42180
  style: {
40141
42181
  position: "absolute",
40142
42182
  top: -TABLE_HANDLE_SAFEZONE_TOP_PX,
@@ -40154,6 +42194,7 @@ ${currentText.slice(end)}`;
40154
42194
  "span",
40155
42195
  {
40156
42196
  contentEditable: false,
42197
+ "data-docx-pagination-ignore": "true",
40157
42198
  style: {
40158
42199
  position: "absolute",
40159
42200
  right: -TABLE_HANDLE_SAFEZONE_RIGHT_PX,
@@ -40243,10 +42284,7 @@ ${currentText.slice(end)}`;
40243
42284
  style: {
40244
42285
  width: resolvedTableWidthPx > 0 ? `${resolvedTableWidthPx}px` : "100%",
40245
42286
  ...tableElementBorderStyle(node, tableBorderSpacingPx),
40246
- tableLayout: node.style?.layout === "autofit" ? "auto" : "fixed",
40247
- ...hasTableRowSlice && tableRowSliceOffsetPx > 0 ? {
40248
- transform: `translateY(-${tableRowSliceOffsetPx - tableRowSliceTopBleedPx}px)`
40249
- } : void 0
42287
+ tableLayout: node.style?.layout === "autofit" ? "auto" : "fixed"
40250
42288
  },
40251
42289
  children: [
40252
42290
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("colgroup", { children: columnWidthsPx.map((widthPx, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -40294,7 +42332,7 @@ ${currentText.slice(end)}`;
40294
42332
  );
40295
42333
  const recursiveCellParagraphs = tableCellParagraphsRecursively(cell.nodes);
40296
42334
  const cellHasImage = tableCellHasImage(cell.nodes);
40297
- const editableCell = selectedByAnchor && !isMultiCellSelectionActive && !cellHasImage && !isReadOnly && cellParagraphs.length > 0;
42335
+ const editableCell = selectedByAnchor && !isSlicedRow && !isMultiCellSelectionActive && !cellHasImage && !isReadOnly && cellParagraphs.length > 0;
40298
42336
  const nestedParagraphIndexesByNode = /* @__PURE__ */ new Map();
40299
42337
  recursiveCellParagraphs.forEach(
40300
42338
  (paragraph, paragraphIndex) => {
@@ -40304,7 +42342,7 @@ ${currentText.slice(end)}`;
40304
42342
  );
40305
42343
  }
40306
42344
  );
40307
- const tableCellEditScope = recursiveCellParagraphs.length > 0 && !isReadOnly && !isMultiCellSelectionActive && !cellHasImage ? {
42345
+ const tableCellEditScope = recursiveCellParagraphs.length > 0 && !isReadOnly && !isSlicedRow && !isMultiCellSelectionActive && !cellHasImage ? {
40308
42346
  isEditable: true,
40309
42347
  draftKeyPrefix: `${nodeIndex}:${rowIndex}:${cellIndex}`,
40310
42348
  paragraphIndexesByNode: nestedParagraphIndexesByNode,
@@ -40345,6 +42383,38 @@ ${currentText.slice(end)}`;
40345
42383
  ).reduce((sum, widthPx) => sum + widthPx, 0);
40346
42384
  const cellBackgroundColor = cell.style?.backgroundColor ?? row.style?.backgroundColor;
40347
42385
  const hasCustomCellRowHeight = hasCustomRowHeight || hasResolvedRowHeight;
42386
+ const mergedCellMarginTwips = mergeTableSpacing(
42387
+ tableCellMarginTwips,
42388
+ cell.style?.marginTwips
42389
+ );
42390
+ const cellPaddingPx = resolveTableSpacingPaddingPx(
42391
+ mergedCellMarginTwips
42392
+ );
42393
+ const cellRenderedWidthPx = cellWidthPx ?? spannedWidthPx;
42394
+ const cellContentWidthPx = Math.max(
42395
+ 1,
42396
+ cellRenderedWidthPx - cellPaddingPx.left - cellPaddingPx.right
42397
+ );
42398
+ const slicedRowHeightPx = Math.max(
42399
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
42400
+ Math.round(
42401
+ rowBoundarySourceHeightsPx[rowIndex] ?? rowHeightPx ?? MIN_PARAGRAPH_LINE_HEIGHT_PX
42402
+ )
42403
+ );
42404
+ const slicedCellViewportHeightPx = isSlicedRow && tableRowSlice ? Math.max(
42405
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
42406
+ Math.round(tableRowSlice.sliceHeightPx)
42407
+ ) : void 0;
42408
+ const slicedParagraphPlans = isSlicedRow && tableRowSlice && !editableCell && slicedCellViewportHeightPx ? resolveTableCellParagraphSlicePlans({
42409
+ cell,
42410
+ rowHeightPx: slicedRowHeightPx,
42411
+ sliceStartPx: tableRowSliceOffsetPx,
42412
+ sliceHeightPx: slicedCellViewportHeightPx,
42413
+ cellContentWidthPx,
42414
+ tableCellMarginTwips,
42415
+ applyWordTableDefaults,
42416
+ docGridLinePitchPx: nodeDocGridLinePitchPx
42417
+ }) : void 0;
40348
42418
  const renderedEditableCellContent = editableCell ? (() => {
40349
42419
  let paragraphCursor = 0;
40350
42420
  return cell.nodes.map(
@@ -40442,10 +42512,7 @@ ${currentText.slice(end)}`;
40442
42512
  cell.style?.borders
40443
42513
  ),
40444
42514
  ...tableSpacingPaddingStyle(
40445
- mergeTableSpacing(
40446
- tableCellMarginTwips,
40447
- cell.style?.marginTwips
40448
- )
42515
+ mergedCellMarginTwips
40449
42516
  ),
40450
42517
  backgroundColor: cellBackgroundColor,
40451
42518
  verticalAlign: cell.style?.verticalAlign ?? "top",
@@ -41266,6 +43333,45 @@ ${currentText.slice(end)}`;
41266
43333
  );
41267
43334
  }
41268
43335
  }
43336
+ ) : slicedParagraphPlans && slicedCellViewportHeightPx ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43337
+ "div",
43338
+ {
43339
+ style: {
43340
+ position: "relative",
43341
+ height: slicedCellViewportHeightPx,
43342
+ overflow: "visible"
43343
+ },
43344
+ children: slicedParagraphPlans.map((plan) => {
43345
+ const contentIndex = cell.nodes.indexOf(
43346
+ plan.paragraph
43347
+ );
43348
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43349
+ "div",
43350
+ {
43351
+ style: {
43352
+ position: "absolute",
43353
+ left: 0,
43354
+ right: 0,
43355
+ top: plan.topPx
43356
+ },
43357
+ children: renderSlicedTableCellParagraph({
43358
+ paragraph: plan.paragraph,
43359
+ paragraphIndex: plan.paragraphIndex,
43360
+ tableIndex: nodeIndex,
43361
+ rowIndex,
43362
+ cellIndex,
43363
+ contentIndex,
43364
+ cellContentWidthPx,
43365
+ applyWordTableDefaults,
43366
+ docGridLinePitchPx: nodeDocGridLinePitchPx,
43367
+ layoutEntry: plan.layoutEntry,
43368
+ paragraphLineRange: plan.paragraphLineRange
43369
+ })
43370
+ },
43371
+ `body-cell-slice-host-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`
43372
+ );
43373
+ })
43374
+ }
41269
43375
  ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "grid", gap: 4 }, children: (() => {
41270
43376
  let paragraphCursor = 0;
41271
43377
  return cell.nodes.map(
@@ -42757,10 +44863,11 @@ ${currentText.slice(end)}`;
42757
44863
  pageLayout.pageHeightPx - pageLayout.marginsPx.top - pageLayout.marginsPx.bottom
42758
44864
  ),
42759
44865
  metricsBySection: paginationSectionMetrics,
42760
- measuredPageContentHeightsPxByPageIndex: measuredPageContentHeightByIndex,
44866
+ measuredPageContentHeightsPxByPageIndex: renderMeasuredPageContentHeightsPxByPageIndex,
42761
44867
  measuredPageContentIdentityKeysByPageIndex: measuredPageContentIdentityKeysByIndex,
42762
44868
  pageIdentityKey: pageNodeSegmentIdentityKeysByPage[pageIndex],
42763
- useMeasuredPageContentHeights: useMeasuredPageContentHeightsForRender
44869
+ useMeasuredPageContentHeights: useMeasuredPageContentHeightsForRender,
44870
+ pageContentHeightScale: renderPageContentHeightScale
42764
44871
  });
42765
44872
  const headerFooterBodyDimmed = pageHeaderFooterEditActive;
42766
44873
  const documentPageBackgroundColor = editor.model.metadata.documentBackgroundColor;
@@ -43054,6 +45161,7 @@ ${currentText.slice(end)}`;
43054
45161
  display: "flex",
43055
45162
  flexDirection: "column",
43056
45163
  minHeight: pageBodyAvailableHeightPx,
45164
+ overflow: "visible",
43057
45165
  ...documentContentFilter ? { filter: documentContentFilter } : void 0
43058
45166
  },
43059
45167
  children: [
@@ -43121,6 +45229,44 @@ ${currentText.slice(end)}`;
43121
45229
  if (!columnNode) {
43122
45230
  return null;
43123
45231
  }
45232
+ const explicitColumnBreakParagraphSegments = columnNode.type === "paragraph" && !columnSegment.tableRowRange && !columnSegment.tableRowSlice && !columnSegment.paragraphLineRange && !explicitColumnWidthsPx && (sectionColumns?.count ?? 0) > 1 ? splitParagraphAtExplicitColumnBreaks(columnNode) : void 0;
45233
+ if (explicitColumnBreakParagraphSegments && explicitColumnBreakParagraphSegments.length > 1) {
45234
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
45235
+ React.Fragment,
45236
+ {
45237
+ children: explicitColumnBreakParagraphSegments.map(
45238
+ (segmentParagraph, segmentIndex) => {
45239
+ const isLastSegment = segmentIndex >= explicitColumnBreakParagraphSegments.length - 1;
45240
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
45241
+ "div",
45242
+ {
45243
+ style: segmentIndex > 0 ? { breakBefore: "column" } : void 0,
45244
+ children: renderDocumentNode(
45245
+ segmentParagraph,
45246
+ columnSegment.nodeIndex,
45247
+ void 0,
45248
+ void 0,
45249
+ void 0,
45250
+ {
45251
+ pageLayout,
45252
+ contentWidthPxOverride: columnContentWidthPx,
45253
+ suppressLikelyFullPageCoverImageKeys: suppressedLikelyFullPageCoverImageKeys,
45254
+ forceReadOnly: true,
45255
+ suppressParagraphElementTracking: segmentIndex > 0,
45256
+ syntheticKeySuffix: `column-break-${segmentIndex}`,
45257
+ overrideBeforeSpacingPx: segmentIndex === 0 ? void 0 : 0,
45258
+ overrideAfterSpacingPx: isLastSegment ? void 0 : 0
45259
+ }
45260
+ )
45261
+ },
45262
+ `column-layout-node-${pageIndex}-${columnSegment.nodeIndex}-column-break-${segmentIndex}`
45263
+ );
45264
+ }
45265
+ )
45266
+ },
45267
+ `column-layout-node-${pageIndex}-${columnSegment.nodeIndex}-column-break-group`
45268
+ );
45269
+ }
43124
45270
  const renderedNode = renderDocumentNode(
43125
45271
  columnNode,
43126
45272
  columnSegment.nodeIndex,
@@ -44792,6 +46938,9 @@ var DEFAULT_MIN_PARAGRAPH_LINE_HEIGHT_PX = 14;
44792
46938
  var PARAGRAPH_SEGMENT_TOP_BLEED_PX2 = 22;
44793
46939
  var PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX2 = 6;
44794
46940
  var PARAGRAPH_SEGMENT_VISUAL_SAFETY_PX2 = 24;
46941
+ var LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_RATIO2 = 0.18;
46942
+ var LAST_RENDERED_PAGE_BREAK_HINT_MIN_REMAINING_SPACE_PX2 = DEFAULT_MIN_PARAGRAPH_LINE_HEIGHT_PX * 3;
46943
+ var LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_PX2 = 120;
44795
46944
  function paragraphSegmentHasPartialLineRange2(paragraphLineRange) {
44796
46945
  if (!paragraphLineRange) {
44797
46946
  return false;
@@ -44860,6 +47009,48 @@ function normalizedPositivePixelValue(value, fallback) {
44860
47009
  }
44861
47010
  return Math.max(1, Math.round(value));
44862
47011
  }
47012
+ function shouldHonorParagraphStartLastRenderedPageBreak2(params) {
47013
+ const pageConsumedHeightPx = Math.max(
47014
+ 0,
47015
+ Math.round(params.pageConsumedHeightPx)
47016
+ );
47017
+ const pageContentHeightPx = Math.max(
47018
+ 0,
47019
+ Math.round(params.pageContentHeightPx)
47020
+ );
47021
+ if (pageConsumedHeightPx <= 0 || pageContentHeightPx <= 0) {
47022
+ return false;
47023
+ }
47024
+ const remainingHeightPx = Math.max(
47025
+ 0,
47026
+ pageContentHeightPx - pageConsumedHeightPx
47027
+ );
47028
+ const maxAllowedRemainingHeightPx = Math.max(
47029
+ LAST_RENDERED_PAGE_BREAK_HINT_MIN_REMAINING_SPACE_PX2,
47030
+ Math.min(
47031
+ LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_PX2,
47032
+ Math.round(
47033
+ pageContentHeightPx * LAST_RENDERED_PAGE_BREAK_HINT_MAX_REMAINING_SPACE_RATIO2
47034
+ )
47035
+ )
47036
+ );
47037
+ return remainingHeightPx <= maxAllowedRemainingHeightPx;
47038
+ }
47039
+ function keepNextParagraphReservePx(paragraph, nextParagraph, callbacks, docGridLinePitchPx) {
47040
+ if (paragraph.style?.keepNext !== true || !nextParagraph || !Number.isFinite(paragraph.style?.headingLevel)) {
47041
+ return 0;
47042
+ }
47043
+ const nextParagraphText = nextParagraph.children.filter((child) => child.type === "text").map((child) => child.text).join(" ").replace(/\s+/g, " ").trim();
47044
+ if (nextParagraph.style?.numbering === void 0 && nextParagraphText.length < 80) {
47045
+ return 0;
47046
+ }
47047
+ return Math.max(
47048
+ nextParagraph.style?.numbering ? 10 : 6,
47049
+ Math.round(
47050
+ callbacks.estimateParagraphLineHeightPx(nextParagraph, docGridLinePitchPx) * (nextParagraph.style?.numbering ? 1 : 0.5)
47051
+ )
47052
+ );
47053
+ }
44863
47054
  function normalizedMeasuredTableRowHeights(measuredRowHeightsPx, expectedRowCount, minParagraphLineHeightPx) {
44864
47055
  if (!measuredRowHeightsPx || measuredRowHeightsPx.length !== expectedRowCount) {
44865
47056
  return void 0;
@@ -45052,6 +47243,12 @@ function collectDocxEstimatedOverflowBreakStartNodeIndexes(model, hardBreakStart
45052
47243
  paragraphBeforeSpacingPx2(nextChainNode)
45053
47244
  );
45054
47245
  requiredHeightPx += Math.max(1, nextRawHeightPx - collapsedChainMarginPx);
47246
+ requiredHeightPx += keepNextParagraphReservePx(
47247
+ currentChainNode,
47248
+ nextChainNode,
47249
+ callbacks,
47250
+ chainMetrics.docGridLinePitchPx
47251
+ );
45055
47252
  chainPreviousParagraphAfterPx = paragraphAfterSpacingPx2(nextChainNode);
45056
47253
  }
45057
47254
  }
@@ -45148,7 +47345,10 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
45148
47345
  nodeMetrics.pageContentHeightPx
45149
47346
  );
45150
47347
  }
45151
- if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak2(node) && currentPageSegments.length > 0) {
47348
+ if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak2(node) && shouldHonorParagraphStartLastRenderedPageBreak2({
47349
+ pageConsumedHeightPx,
47350
+ pageContentHeightPx: currentPageContentHeightPx
47351
+ }) && currentPageSegments.length > 0) {
45152
47352
  startNextPage();
45153
47353
  pageConsumedHeightPx = 0;
45154
47354
  previousParagraphAfterPx = 0;
@@ -45373,6 +47573,12 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
45373
47573
  paragraphBeforeSpacingPx2(nextChainNode)
45374
47574
  );
45375
47575
  requiredHeightPx += Math.max(1, nextRawHeightPx - collapsedChainMarginPx);
47576
+ requiredHeightPx += keepNextParagraphReservePx(
47577
+ currentChainNode,
47578
+ nextChainNode,
47579
+ callbacks,
47580
+ chainMetrics.docGridLinePitchPx
47581
+ );
45376
47582
  chainPreviousParagraphAfterPx = paragraphAfterSpacingPx2(nextChainNode);
45377
47583
  }
45378
47584
  }