@extend-ai/react-docx 0.4.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
@@ -109,6 +109,7 @@ __export(index_exports, {
109
109
  useDocxPagination: () => useDocxPagination,
110
110
  useDocxParagraphStyles: () => useDocxParagraphStyles,
111
111
  useDocxTrackChanges: () => useDocxTrackChanges,
112
+ useDocxViewerThumbnails: () => useDocxViewerThumbnails,
112
113
  withPart: () => withPart
113
114
  });
114
115
  module.exports = __toCommonJS(index_exports);
@@ -4946,6 +4947,7 @@ function parseTable(tableXml2, context) {
4946
4947
  const rowHeightRuleRaw = rowHeightTag ? getAttribute(rowHeightTag, "w:hRule")?.toLowerCase() : void 0;
4947
4948
  const rowHeightRule = rowHeightRuleRaw === "atleast" || rowHeightRuleRaw === "exact" || rowHeightRuleRaw === "auto" ? rowHeightRuleRaw === "atleast" ? "atLeast" : rowHeightRuleRaw : void 0;
4948
4949
  const rowCantSplit = rowPropertiesXml ? parseOnOffAttribute(rowPropertiesXml, "cantSplit") : void 0;
4950
+ const rowIsHeader = rowPropertiesXml ? parseOnOffAttribute(rowPropertiesXml, "tblHeader") : void 0;
4949
4951
  const parsedCells = extractBalancedTagBlocks(rowXml, "w:tc").map(
4950
4952
  (cellXml) => parseTableCell(cellXml, context)
4951
4953
  );
@@ -5002,11 +5004,12 @@ function parseTable(tableXml2, context) {
5002
5004
  rows.push({
5003
5005
  type: "table-row",
5004
5006
  cells,
5005
- 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 ? {
5006
5008
  backgroundColor: rowBackgroundColor,
5007
5009
  heightTwips: rowHeightTwips,
5008
5010
  ...rowHeightRule !== void 0 ? { heightRule: rowHeightRule } : void 0,
5009
- ...rowCantSplit !== void 0 ? { cantSplit: rowCantSplit } : void 0
5011
+ ...rowCantSplit !== void 0 ? { cantSplit: rowCantSplit } : void 0,
5012
+ ...rowIsHeader !== void 0 ? { isHeader: rowIsHeader } : void 0
5010
5013
  } : void 0
5011
5014
  });
5012
5015
  }
@@ -7796,6 +7799,107 @@ function parseParagraphsFromClipboard(input) {
7796
7799
  }
7797
7800
  }
7798
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
+
7799
7903
  // ../serializer/src/index.ts
7800
7904
  var REL_TYPE_IMAGE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
7801
7905
  var REL_TYPE_HYPERLINK = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
@@ -9121,18 +9225,63 @@ function collectTopLevelExplicitPageBreakStartNodeIndexes(nodes) {
9121
9225
  }
9122
9226
 
9123
9227
  // src/page-count-reconciliation.ts
9228
+ var PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS = 10;
9124
9229
  function shouldAllowStoredPageCountReduction(options) {
9125
- const estimatedPageCount = Math.max(1, Math.round(options.estimatedPageCount));
9230
+ const estimatedPageCount = Math.max(
9231
+ 1,
9232
+ Math.round(options.estimatedPageCount)
9233
+ );
9126
9234
  const targetPageCount = Math.max(1, Math.round(options.targetPageCount));
9127
9235
  if (targetPageCount >= estimatedPageCount) {
9128
9236
  return true;
9129
9237
  }
9238
+ if (options.hasMeasuredBodyFooterOverlap === true) {
9239
+ return false;
9240
+ }
9130
9241
  if (options.hasLastRenderedPageBreakHints !== true) {
9131
9242
  return true;
9132
9243
  }
9133
- 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;
9134
9247
  return renderedBreakHintPageCount !== void 0 && targetPageCount >= renderedBreakHintPageCount;
9135
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
+ }
9136
9285
  function isBetterCandidate(candidate, incumbent, targetPageCount) {
9137
9286
  const candidateDifference = Math.abs(candidate.pageCount - targetPageCount);
9138
9287
  const incumbentDifference = Math.abs(incumbent.pageCount - targetPageCount);
@@ -9146,7 +9295,7 @@ function isBetterCandidate(candidate, incumbent, targetPageCount) {
9146
9295
  }
9147
9296
  return candidate.pageCount === targetPageCount && incumbent.pageCount !== targetPageCount;
9148
9297
  }
9149
- function reconcilePagesToTargetCountByScalingHeight(options) {
9298
+ function reconcilePageCountCandidateToTargetCountByScalingHeight(options) {
9150
9299
  const {
9151
9300
  initialPages,
9152
9301
  targetPageCount,
@@ -9158,7 +9307,11 @@ function reconcilePagesToTargetCountByScalingHeight(options) {
9158
9307
  const initialPageCount = initialPages.length;
9159
9308
  const initialDifference = Math.abs(initialPageCount - safeTargetPageCount);
9160
9309
  if (initialDifference === 0 || initialDifference > maxDifference) {
9161
- return initialPages;
9310
+ return {
9311
+ pageCount: initialPageCount,
9312
+ pages: initialPages,
9313
+ scale: 1
9314
+ };
9162
9315
  }
9163
9316
  const bestCandidate = {
9164
9317
  pageCount: initialPageCount,
@@ -9208,22 +9361,71 @@ function reconcilePagesToTargetCountByScalingHeight(options) {
9208
9361
  0.24,
9209
9362
  0.22,
9210
9363
  0.2
9211
- ] : [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];
9212
- 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) => {
9213
9382
  const pages = buildPagesAtScale(scale);
9214
- const candidate = {
9383
+ return {
9215
9384
  pageCount: pages.length,
9216
9385
  pages,
9217
9386
  scale
9218
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);
9219
9415
  if (isBetterCandidate(candidate, selectedCandidate, safeTargetPageCount)) {
9220
9416
  selectedCandidate = candidate;
9221
9417
  }
9222
9418
  if (candidate.pageCount === safeTargetPageCount) {
9223
- return candidate.pages;
9419
+ const crossedIntoExactTarget = needMorePages ? previousPageCount < safeTargetPageCount : previousPageCount > safeTargetPageCount;
9420
+ if (crossedIntoExactTarget) {
9421
+ return refineExactTargetCandidate(previousScale, scale);
9422
+ }
9423
+ return candidate;
9224
9424
  }
9425
+ previousScale = scale;
9426
+ previousPageCount = candidate.pageCount;
9225
9427
  }
9226
- return selectedCandidate.pages;
9428
+ return selectedCandidate;
9227
9429
  }
9228
9430
 
9229
9431
  // src/pretext-layout.ts
@@ -9448,6 +9650,22 @@ function prepareCached(text, font, wordBreak = "normal") {
9448
9650
  return void 0;
9449
9651
  }
9450
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
+ }
9451
9669
  function cloneItemCursor(cursor) {
9452
9670
  return {
9453
9671
  itemIndex: cursor.itemIndex,
@@ -10189,7 +10407,7 @@ var SCRIPT_FONT_SCALE = 0.65;
10189
10407
  var DEFAULT_PARAGRAPH_LINE_MULTIPLE = 1;
10190
10408
  var WORD_SINGLE_LINE_AUTO_SCALE = 0.88;
10191
10409
  var WORD_SINGLE_LINE_AUTO_SCALE_SANS = 0.9;
10192
- var WORD_SINGLE_LINE_AUTO_SCALE_SERIF = 1.12;
10410
+ var WORD_SINGLE_LINE_AUTO_SCALE_SERIF = 1.08;
10193
10411
  var WORD_AUTO_LINE_SCALE_BLEND_END_MULTIPLE = 1.08;
10194
10412
  var MIN_AUTO_LINE_MULTIPLE = 0.1;
10195
10413
  var MIN_PARAGRAPH_LINE_HEIGHT_PX = 14;
@@ -10199,10 +10417,12 @@ var MEASURED_PAGE_FOOTER_CLEARANCE_BUFFER_PX = 24;
10199
10417
  var UNOVERLAPPED_FOOTER_MIN_CLEARANCE_PX = 16;
10200
10418
  var FLOATING_FOOTER_BASELINE_CLEARANCE_RESERVE_PX = 16;
10201
10419
  var PAGINATION_MEASUREMENT_INTERACTION_DEBOUNCE_MS = 180;
10420
+ var MEASURED_BODY_FOOTER_OVERLAP_STABILITY_THRESHOLD = 3;
10202
10421
  var WORD_TABLE_CELL_PARAGRAPH_AUTO_LINE_TWIPS = 240;
10203
10422
  var WORD_TABLE_CELL_PARAGRAPH_BEFORE_TWIPS = 0;
10204
10423
  var WORD_TABLE_CELL_PARAGRAPH_AFTER_TWIPS = 0;
10205
10424
  var TABLE_ROW_SLICE_VISUAL_BLEED_PX = 1;
10425
+ var TABLE_CELL_SLICE_FULLY_VISIBLE_BOTTOM_BUFFER_PX = 4;
10206
10426
  var DEFAULT_SPLIT_PARAGRAPH_LINE_TWIPS = 259;
10207
10427
  var DEFAULT_SPLIT_PARAGRAPH_AFTER_TWIPS = 160;
10208
10428
  var PAGE_CONTENT_MEASUREMENT_IGNORE_ATTRIBUTE = "data-docx-pagination-ignore";
@@ -10235,15 +10455,19 @@ var LEADING_COVER_SPACER_EXTRA_HEIGHT_PX = 2;
10235
10455
  var PARAGRAPH_SEGMENT_TOP_BLEED_PX = 22;
10236
10456
  var PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX = 6;
10237
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;
10238
10461
  var PARAGRAPH_SEGMENT_FALLBACK_TOP_BLEED_MAX_PX = 4;
10239
10462
  var PARAGRAPH_SEGMENT_FALLBACK_BOTTOM_BLEED_MAX_PX = 0;
10240
10463
  var PARAGRAPH_SEGMENT_FALLBACK_VISUAL_SAFETY_PX = 4;
10241
10464
  var INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT = 8;
10242
10465
  var INITIAL_PAGINATION_PAGE_COUNT_OSCILLATION_DISTINCT_THRESHOLD = 2;
10243
10466
  var INITIAL_PAGINATION_PAGE_COUNT_OSCILLATION_CHANGE_THRESHOLD = 4;
10467
+ var INITIAL_PAGINATION_BACKGROUND_REFINEMENT_DELAY_MS = 96;
10244
10468
  var DEFAULT_PAGE_VIRTUALIZATION_OVERSCAN = 2;
10245
10469
  var DEFAULT_PAGE_VIRTUALIZATION_SETTLE_DELAY_MS = 350;
10246
- var ENABLE_TABLE_ROW_SLICING = false;
10470
+ var ENABLE_TABLE_ROW_SLICING = true;
10247
10471
  var TOP_AND_BOTTOM_VERTICAL_DRAG_SNAP_PX = 10;
10248
10472
  var HEADER_FOOTER_INACTIVE_OPACITY = 0.5;
10249
10473
  var LETTERHEAD_INDENT_MIN_TWIPS = 900;
@@ -10548,7 +10772,11 @@ function nearestScrollableAncestor(element) {
10548
10772
  }
10549
10773
  current = current.parentElement;
10550
10774
  }
10551
- 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;
10552
10780
  }
10553
10781
  function resolveEffectiveZoomScale(element) {
10554
10782
  let current = element;
@@ -10650,7 +10878,7 @@ function normalizeMeasuredTableRowHeightPx(heightPx) {
10650
10878
  }
10651
10879
  return Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, Math.round(heightPx));
10652
10880
  }
10653
- function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowHeights, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx) {
10881
+ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowHeights, maxAvailableWidthPx, pageContentHeightPx, numberingDefinitions, docGridLinePitchPx) {
10654
10882
  if (measuredRowHeights.length !== table.rows.length) {
10655
10883
  return void 0;
10656
10884
  }
@@ -10658,7 +10886,8 @@ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowH
10658
10886
  table,
10659
10887
  maxAvailableWidthPx,
10660
10888
  numberingDefinitions,
10661
- docGridLinePitchPx
10889
+ docGridLinePitchPx,
10890
+ pageContentHeightPx
10662
10891
  );
10663
10892
  if (estimatedRowHeights.length !== table.rows.length) {
10664
10893
  return void 0;
@@ -10666,6 +10895,7 @@ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowH
10666
10895
  return measuredRowHeights.map((heightPx, rowIndex) => {
10667
10896
  const row = table.rows[rowIndex];
10668
10897
  const normalizedMeasuredHeightPx = normalizeMeasuredTableRowHeightPx(heightPx);
10898
+ const normalizedPageContentHeightPx = Number.isFinite(pageContentHeightPx) && pageContentHeightPx > 0 ? Math.max(120, Math.round(pageContentHeightPx)) : void 0;
10669
10899
  const estimatedHeightPx = Math.max(
10670
10900
  MIN_PARAGRAPH_LINE_HEIGHT_PX,
10671
10901
  Math.round(estimatedRowHeights[rowIndex] ?? MIN_PARAGRAPH_LINE_HEIGHT_PX)
@@ -10683,6 +10913,9 @@ function reconcileMeasuredTableRowHeightsForImportPagination(table, measuredRowH
10683
10913
  if (rowAllowsPageSplit(row) && row.style?.heightRule !== "exact") {
10684
10914
  return Math.max(explicitMinimumHeightPx, normalizedMeasuredHeightPx);
10685
10915
  }
10916
+ if (Number.isFinite(normalizedPageContentHeightPx) && normalizedMeasuredHeightPx > normalizedPageContentHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
10917
+ return Math.max(explicitMinimumHeightPx, normalizedMeasuredHeightPx);
10918
+ }
10686
10919
  const minimumHeightPx = Math.max(
10687
10920
  estimatedHeightPx,
10688
10921
  explicitMinimumHeightPx
@@ -10728,6 +10961,7 @@ function resolveTableMeasuredRowHeightsForPagination(nodes, tableMeasuredRowHeig
10728
10961
  tableNode,
10729
10962
  measuredRowHeights,
10730
10963
  options?.pageContentWidthPxByNodeIndex?.get(tableIndex),
10964
+ options?.pageContentHeightPxByNodeIndex?.get(tableIndex),
10731
10965
  options?.numberingDefinitions,
10732
10966
  options?.docGridLinePitchPxByNodeIndex?.get(tableIndex)
10733
10967
  ) ?? measuredRowHeights.map(
@@ -11492,9 +11726,9 @@ function resolveFooterPaginationReservePx(footerSections, layout) {
11492
11726
  )
11493
11727
  );
11494
11728
  const footerBodyOverlapPx = estimatedFooterHeightPx + layout.footerDistancePx - layout.marginsPx.bottom;
11495
- const explicitFooterOverlapReservePx = Math.max(
11729
+ const explicitFooterBoundaryReservePx = Math.max(
11496
11730
  0,
11497
- Math.round(footerBodyOverlapPx)
11731
+ Math.round(footerBodyOverlapPx + UNOVERLAPPED_FOOTER_MIN_CLEARANCE_PX)
11498
11732
  );
11499
11733
  const floatingFooterBoundaryReservePx = Number.isFinite(
11500
11734
  floatingFooterBoundaryTopPx
@@ -11506,13 +11740,13 @@ function resolveFooterPaginationReservePx(footerSections, layout) {
11506
11740
  ) : 0;
11507
11741
  if (hasFloatingFooterBodyIntrusionRisk) {
11508
11742
  return Math.max(
11509
- explicitFooterOverlapReservePx,
11743
+ explicitFooterBoundaryReservePx,
11510
11744
  floatingFooterBoundaryReservePx,
11511
11745
  FLOATING_FOOTER_BASELINE_CLEARANCE_RESERVE_PX
11512
11746
  );
11513
11747
  }
11514
11748
  return Math.max(
11515
- explicitFooterOverlapReservePx,
11749
+ explicitFooterBoundaryReservePx,
11516
11750
  floatingFooterBoundaryReservePx
11517
11751
  );
11518
11752
  }
@@ -11732,7 +11966,7 @@ function resolvePageContentHeightPxForPageSegments(pageSegments, pageIndex, defa
11732
11966
  );
11733
11967
  }
11734
11968
  function resolveRenderPageContentHeightPxForPageSegments(params) {
11735
- return resolvePageContentHeightPxForPageSegments(
11969
+ const resolvedHeightPx = resolvePageContentHeightPxForPageSegments(
11736
11970
  params.pageSegments,
11737
11971
  params.pageIndex,
11738
11972
  params.defaultPageContentHeightPx,
@@ -11741,6 +11975,13 @@ function resolveRenderPageContentHeightPxForPageSegments(params) {
11741
11975
  params.useMeasuredPageContentHeights === false ? void 0 : params.measuredPageContentIdentityKeysByPageIndex,
11742
11976
  params.pageIdentityKey
11743
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;
11744
11985
  }
11745
11986
  function documentPageContainsOnlySplitParagraphSegments(pageSegments) {
11746
11987
  return pageSegments.length > 0 && pageSegments.every(
@@ -12277,28 +12518,74 @@ function nodeTreeContainsExplicitFontFamily(nodes) {
12277
12518
  return false;
12278
12519
  });
12279
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
+ }
12280
12548
  function resolveDocumentInheritedFontFamily(model) {
12281
12549
  const paragraphStyles = model.metadata.paragraphStyles ?? [];
12282
- 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(
12283
12559
  (style) => Boolean(style.runStyle?.fontFamily?.trim())
12284
- );
12285
- if (styleDefinesFontFamily) {
12286
- return void 0;
12560
+ )?.runStyle?.fontFamily;
12561
+ if (paragraphStyleFontFamily) {
12562
+ return cssFontFamily(paragraphStyleFontFamily);
12287
12563
  }
12288
- if (nodeTreeContainsExplicitFontFamily(model.nodes)) {
12289
- return void 0;
12564
+ const explicitBodyFontFamily = firstExplicitFontFamilyInNodeTree(model.nodes);
12565
+ if (explicitBodyFontFamily) {
12566
+ return cssFontFamily(explicitBodyFontFamily);
12290
12567
  }
12291
- if ((model.metadata.headerSections ?? []).some(
12292
- (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12293
- )) {
12294
- 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
+ }
12295
12575
  }
12296
- if ((model.metadata.footerSections ?? []).some(
12297
- (section) => nodeTreeContainsExplicitFontFamily(section.nodes)
12298
- )) {
12299
- 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
+ }
12300
12583
  }
12301
- 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);
12302
12589
  }
12303
12590
  function replaceTabLayoutMarkersWithTabText(root) {
12304
12591
  const centerLayouts = Array.from(
@@ -12666,6 +12953,11 @@ function sectionNodesNeedFullPageFooterOverlay(nodes) {
12666
12953
  function paragraphHasFormField2(paragraph) {
12667
12954
  return paragraph.children.some((child) => child.type === "form-field");
12668
12955
  }
12956
+ function paragraphHasCheckboxFormField(paragraph) {
12957
+ return paragraph.children.some(
12958
+ (child) => child.type === "form-field" && child.fieldType === "checkbox"
12959
+ );
12960
+ }
12669
12961
  function paragraphHasVisibleText2(paragraph) {
12670
12962
  return paragraph.children.some(
12671
12963
  (child) => child.type === "text" && child.text.trim().length > 0 || child.type === "form-field" && formFieldDisplayValue2(child).trim().length > 0
@@ -12984,6 +13276,9 @@ function paragraphLooksLikeCheckboxChoiceRow(paragraph) {
12984
13276
  }
12985
13277
  var KEEP_ALL_SCRIPT_RE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u;
12986
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();
12987
13282
  function imageWrapModeFromFloating(floating) {
12988
13283
  if (!floating) {
12989
13284
  return "inline";
@@ -13129,16 +13424,67 @@ function resolveFloatingForImageWrapMode(mode, currentFloating, seedFloating) {
13129
13424
  };
13130
13425
  }
13131
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
+ }
13132
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
+ };
13133
13476
  if (paragraphHasFormField2(paragraph)) {
13134
- return void 0;
13477
+ return storeCachedSource(void 0);
13135
13478
  }
13136
13479
  if (!options?.allowExplicitLineBreakText && paragraphContainsExplicitLineBreakText(paragraph)) {
13137
- return void 0;
13480
+ return storeCachedSource(void 0);
13138
13481
  }
13139
13482
  const runs = [];
13140
13483
  let combinedText = "";
13141
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;
13142
13488
  let lastTextStyle = firstRunStyle(paragraph);
13143
13489
  for (let childIndex = 0; childIndex < paragraph.children.length; childIndex += 1) {
13144
13490
  const child = paragraph.children[childIndex];
@@ -13168,10 +13514,63 @@ function buildParagraphPretextLayoutSource(paragraph, options) {
13168
13514
  continue;
13169
13515
  }
13170
13516
  if (child.type !== "text") {
13171
- return void 0;
13172
- }
13173
- if (child.noteReference || child.text.includes(" ")) {
13174
- 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;
13175
13574
  }
13176
13575
  const startOffset = combinedText.length;
13177
13576
  combinedText += child.text;
@@ -13184,15 +13583,142 @@ function buildParagraphPretextLayoutSource(paragraph, options) {
13184
13583
  style: child.style,
13185
13584
  link: child.link
13186
13585
  });
13586
+ approximateLineWidthPx = updateEstimatedLineWidthPxForText(
13587
+ approximateLineWidthPx,
13588
+ child.text,
13589
+ child.style
13590
+ );
13187
13591
  lastTextStyle = child.style ?? lastTextStyle;
13188
13592
  }
13189
13593
  if (combinedText.length === 0) {
13190
- return void 0;
13594
+ return storeCachedSource(void 0);
13191
13595
  }
13192
- return {
13596
+ return storeCachedSource({
13193
13597
  text: combinedText,
13194
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 = [];
13195
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;
13196
13722
  }
13197
13723
  function buildSyntheticPretextLayoutSource(text, style) {
13198
13724
  return {
@@ -13216,16 +13742,50 @@ function sanitizeRenderedPretextFragmentText(text) {
13216
13742
  return text.replace(/\r\n?|\n/g, "");
13217
13743
  }
13218
13744
  function buildParagraphPretextLayoutItems(paragraph, source) {
13745
+ const cachedItems = paragraphPretextLayoutItemsBySource.get(source);
13746
+ if (cachedItems) {
13747
+ return cachedItems;
13748
+ }
13219
13749
  const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
13220
13750
  const wordBreak = pretextWordBreakModeForText(source.text);
13221
- return source.runs.filter((run) => run.endOffset > run.startOffset).map((run) => ({
13751
+ const items = source.runs.filter((run) => run.endOffset > run.startOffset).map((run) => ({
13222
13752
  text: run.text,
13223
13753
  font: resolveMeasureFont(run.style, paragraphBaseFontPx),
13224
13754
  startOffset: run.startOffset,
13225
13755
  endOffset: run.endOffset,
13226
- break: run.kind === "image" ? "never" : "normal",
13756
+ break: run.kind === "image" || run.kind === "tab" ? "never" : "normal",
13227
13757
  wordBreak
13228
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;
13229
13789
  }
13230
13790
  function buildMeasureSegmentsPretextLayoutItems(segments, paragraphBaseFontPx, text) {
13231
13791
  const wordBreak = pretextWordBreakModeForText(text);
@@ -14012,6 +14572,31 @@ function paragraphStartsWithLastRenderedPageBreak(paragraph) {
14012
14572
  ).replace(/<\/?w:(?:ins|smartTag)\b[^>]*>/gi, "").replace(/\s+/g, "");
14013
14573
  return leadingXml.length === 0;
14014
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
+ }
14015
14600
  function isOnOffTagEnabled2(tagXml) {
14016
14601
  if (!tagXml) {
14017
14602
  return false;
@@ -14155,7 +14740,8 @@ function sectionBreakAfterParagraphStartsNewPage(paragraph) {
14155
14740
  if (cached) {
14156
14741
  return cached.sectionBreakStartsNewPage;
14157
14742
  }
14158
- return paragraphHasExplicitPageBreak2(paragraph) ? paragraphBreakFlagsBySourceXml.get(xml)?.sectionBreakStartsNewPage ?? false : false;
14743
+ paragraphHasExplicitPageBreak2(paragraph);
14744
+ return paragraphBreakFlagsBySourceXml.get(xml)?.sectionBreakStartsNewPage ?? false;
14159
14745
  }
14160
14746
  function nodeAlreadyEndsAtExplicitPageBoundary(node) {
14161
14747
  if (!node || node.type !== "paragraph") {
@@ -14395,6 +14981,10 @@ function singleLineAutoScaleForFontFamily(fontFamily) {
14395
14981
  }
14396
14982
  return WORD_SINGLE_LINE_AUTO_SCALE;
14397
14983
  }
14984
+ function resolveParagraphSingleLineAutoScale(paragraph, fontFamily) {
14985
+ const baseScale = singleLineAutoScaleForFontFamily(fontFamily);
14986
+ return paragraphHasCheckboxFormField(paragraph) ? Math.max(1.08, baseScale) : baseScale;
14987
+ }
14398
14988
  function paragraphContainsExplicitLineBreakText(paragraph) {
14399
14989
  return paragraph.children.some(
14400
14990
  (child) => child.type === "text" && /[\r\n]/.test(child.text)
@@ -14483,6 +15073,23 @@ function resolveParagraphTabStopsPx(paragraph) {
14483
15073
  ).map((value) => Math.round(value)).sort((left, right) => left - right);
14484
15074
  return stopsPx;
14485
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
+ }
14486
15093
  function resolveNextTabStopPx(currentLineWidthPx, tabStopsPx) {
14487
15094
  const nextExplicit = tabStopsPx.find(
14488
15095
  (stopPx) => stopPx > currentLineWidthPx + 0.5
@@ -14716,6 +15323,21 @@ function estimateWrappedLineCountForParagraph(paragraph, availableWidthPx) {
14716
15323
  if (!pretextSource) {
14717
15324
  return void 0;
14718
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
+ }
14719
15341
  const lineHeightPx = estimateParagraphLineHeightPx(paragraph);
14720
15342
  const layout = layoutParagraphPretextSource(
14721
15343
  paragraph,
@@ -14970,6 +15592,58 @@ function wrappedPretextParagraphBlockHeightPx(layout) {
14970
15592
  }
14971
15593
  return Math.max(1, Math.round(layout.height));
14972
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
+ }
14973
15647
  function estimateAbsoluteFloatingImageFootprintPx(paragraph, image) {
14974
15648
  if (!shouldRenderAbsoluteFloatingImage(image)) {
14975
15649
  return 0;
@@ -15009,10 +15683,7 @@ function resolveAutoLineSpacingMultiple(lineTwips, fallbackMultiple) {
15009
15683
  function autoLineHeightScaleForMultiple(multiple, singleLineScale) {
15010
15684
  const safeSingleLineScale = Math.max(
15011
15685
  MIN_AUTO_LINE_MULTIPLE,
15012
- Math.min(
15013
- 1,
15014
- Number.isFinite(singleLineScale) ? singleLineScale : WORD_SINGLE_LINE_AUTO_SCALE
15015
- )
15686
+ Number.isFinite(singleLineScale) ? singleLineScale : WORD_SINGLE_LINE_AUTO_SCALE
15016
15687
  );
15017
15688
  if (!Number.isFinite(multiple)) {
15018
15689
  return safeSingleLineScale;
@@ -15028,9 +15699,9 @@ function autoLineHeightScaleForMultiple(multiple, singleLineScale) {
15028
15699
  (safeSingleLineScale + (1 - safeSingleLineScale) * blendProgress).toFixed(4)
15029
15700
  );
15030
15701
  }
15031
- function calibrateAutoLineSpacingMultiple(multiple, fontFamily) {
15702
+ function calibrateAutoLineSpacingMultiple(multiple, fontFamily, singleLineScaleOverride) {
15032
15703
  const normalizedMultiple = Math.max(MIN_AUTO_LINE_MULTIPLE, multiple);
15033
- const singleLineScale = singleLineAutoScaleForFontFamily(fontFamily);
15704
+ const singleLineScale = singleLineScaleOverride ?? singleLineAutoScaleForFontFamily(fontFamily);
15034
15705
  return Math.max(
15035
15706
  MIN_AUTO_LINE_MULTIPLE,
15036
15707
  Number(
@@ -15074,13 +15745,18 @@ function estimateParagraphLineHeightPx(paragraph, docGridLinePitchPx, disableDoc
15074
15745
  );
15075
15746
  const baseFontPx = paragraphBaseFontSizePx(paragraph);
15076
15747
  const baseFontFamily = paragraphDominantFontFamily(paragraph);
15748
+ const singleLineScale = resolveParagraphSingleLineAutoScale(
15749
+ paragraph,
15750
+ baseFontFamily
15751
+ );
15077
15752
  const defaultLineMultiple = isTableOfContentsParagraph(paragraph) ? 1.05 : DEFAULT_PARAGRAPH_LINE_MULTIPLE;
15078
15753
  const normalLineHeightPx = Math.max(
15079
15754
  1,
15080
15755
  Math.round(
15081
15756
  baseFontPx * calibrateAutoLineSpacingMultiple(
15082
15757
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
15083
- baseFontFamily
15758
+ baseFontFamily,
15759
+ singleLineScale
15084
15760
  )
15085
15761
  )
15086
15762
  );
@@ -15097,7 +15773,8 @@ function estimateParagraphLineHeightPx(paragraph, docGridLinePitchPx, disableDoc
15097
15773
  }
15098
15774
  const multiple = calibrateAutoLineSpacingMultiple(
15099
15775
  resolveAutoLineSpacingMultiple(lineTwips, defaultLineMultiple),
15100
- baseFontFamily
15776
+ baseFontFamily,
15777
+ singleLineScale
15101
15778
  );
15102
15779
  const autoLineHeightPx = Math.max(1, Math.round(baseFontPx * multiple));
15103
15780
  const minimumReadableAutoLineHeightPx = paragraph.style?.numbering ? Math.ceil(baseFontPx) : 0;
@@ -15263,14 +15940,17 @@ function suppressFirstTableCellParagraphTopSpacing(paragraph) {
15263
15940
  }
15264
15941
  function estimateTableCellContentHeightPx(nodeContent, availableWidthPx, numberingDefinitions, applyWordTableDefaults = false, docGridLinePitchPx) {
15265
15942
  let paragraphIndex = 0;
15266
- return nodeContent.reduce((sum, contentNode) => {
15943
+ let expandedWithPretextLayout = false;
15944
+ let totalHeightPx = 0;
15945
+ for (const contentNode of nodeContent) {
15267
15946
  if (!isParagraphCellContentNode(contentNode)) {
15268
- return sum + estimateTableHeightPx(
15947
+ totalHeightPx += estimateTableHeightPx(
15269
15948
  contentNode,
15270
15949
  availableWidthPx,
15271
15950
  numberingDefinitions,
15272
15951
  docGridLinePitchPx
15273
15952
  );
15953
+ continue;
15274
15954
  }
15275
15955
  const disableDocGridSnap = paragraphDocGridSnapState(contentNode) === "disable";
15276
15956
  const paragraphForLayout = wordLikeTableCellParagraph(
@@ -15284,14 +15964,55 @@ function estimateTableCellContentHeightPx(nodeContent, availableWidthPx, numberi
15284
15964
  docGridLinePitchPx,
15285
15965
  disableDocGridSnap
15286
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;
15287
15994
  const suppressTopSpacing = paragraphIndex === 0 && suppressFirstTableCellParagraphTopSpacing(contentNode);
15288
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
+ }
15289
16009
  if (!suppressTopSpacing) {
15290
- return sum + baseHeight;
16010
+ totalHeightPx += resolvedBaseHeight;
16011
+ continue;
15291
16012
  }
15292
- const beforeSpacing = twipsToPixels(paragraphForLayout.style?.spacing?.beforeTwips) ?? 0;
15293
- return sum + Math.max(1, baseHeight - beforeSpacing);
15294
- }, 0);
16013
+ totalHeightPx += Math.max(1, resolvedBaseHeight - beforeSpacing);
16014
+ }
16015
+ return totalHeightPx + (expandedWithPretextLayout ? Math.max(1, MIN_PARAGRAPH_LINE_HEIGHT_PX) : 0);
15295
16016
  }
15296
16017
  function rowAllowsPageSplit(row) {
15297
16018
  return row.style?.cantSplit !== true && row.style?.heightRule !== "exact";
@@ -15309,7 +16030,7 @@ function rowHasDeepFlowContent(row) {
15309
16030
  }
15310
16031
  return nestedTableCount > 0 || blockNodeCount >= SPLITTABLE_TABLE_ROW_DEEP_CONTENT_NODE_THRESHOLD;
15311
16032
  }
15312
- function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitHeightPx) {
16033
+ function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitHeightPx, pageContentHeightPx) {
15313
16034
  if (!rowAllowsPageSplit(row)) {
15314
16035
  return estimatedRowHeightPx;
15315
16036
  }
@@ -15323,6 +16044,13 @@ function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitH
15323
16044
  MIN_PARAGRAPH_LINE_HEIGHT_PX * 2,
15324
16045
  Math.round(explicitHeightPx)
15325
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
+ }
15326
16054
  const cappedHeightPx = safeExplicitHeightPx + MIN_PARAGRAPH_LINE_HEIGHT_PX * SPLITTABLE_TABLE_ROW_ESTIMATE_EXTRA_LINE_COUNT;
15327
16055
  return Math.min(estimatedRowHeightPx, cappedHeightPx);
15328
16056
  }
@@ -15360,7 +16088,7 @@ function tableUsesWordLikeParagraphDefaults(table) {
15360
16088
  }
15361
16089
  return table.style?.layout === "fixed" && tableHasVisibleBorders(table) && tableContainsParagraphsWithoutExplicitSpacing(table);
15362
16090
  }
15363
- function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx) {
16091
+ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx, pageContentHeightPx) {
15364
16092
  const defaultCellMargin = table.style?.cellMarginTwips;
15365
16093
  const columnCount = tableColumnCount(table);
15366
16094
  const tableWidthPx = twipsToPixels(table.style?.widthTwips);
@@ -15378,7 +16106,11 @@ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefiniti
15378
16106
  return normalizeColumnWidthsPx(widthsPx, columnCount, tableWidthPx, 1);
15379
16107
  })();
15380
16108
  const rawResolvedTableWidthPx = tableWidthPx ?? rawTableColumnWidthsPx.reduce((sum, widthPx) => sum + widthPx, 0);
15381
- 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;
15382
16114
  const resolvedTableWidthPx = clampTableWidthPx(
15383
16115
  rawResolvedTableWidthPx,
15384
16116
  maxTableWidthPx
@@ -15425,7 +16157,8 @@ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefiniti
15425
16157
  rowHeightPx = capSplitFriendlyTableRowEstimatePx(
15426
16158
  row,
15427
16159
  rowHeightPx,
15428
- explicitHeightPx
16160
+ explicitHeightPx,
16161
+ pageContentHeightPx
15429
16162
  );
15430
16163
  return Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, rowHeightPx);
15431
16164
  });
@@ -15526,6 +16259,45 @@ function paragraphSegmentHasPartialLineRange(paragraphLineRange) {
15526
16259
  }
15527
16260
  return paragraphLineRange.startLineIndex > 0 || paragraphLineRange.endLineIndex < paragraphLineRange.totalLineCount;
15528
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
+ }
15529
16301
  function resolveParagraphSegmentClipBleedPx(paragraphLineRange) {
15530
16302
  if (!paragraphSegmentHasPartialLineRange(paragraphLineRange)) {
15531
16303
  return {
@@ -15535,7 +16307,7 @@ function resolveParagraphSegmentClipBleedPx(paragraphLineRange) {
15535
16307
  }
15536
16308
  return {
15537
16309
  topPx: paragraphLineRange && paragraphLineRange.startLineIndex > 0 ? Math.max(0, PARAGRAPH_SEGMENT_TOP_BLEED_PX) : 0,
15538
- 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
15539
16311
  };
15540
16312
  }
15541
16313
  function resolveFallbackParagraphSegmentClipBleedPx(paragraph, paragraphLineRange) {
@@ -15609,12 +16381,32 @@ function estimateRenderedPageSegmentHeightPx(node, segment, model, availableWidt
15609
16381
  false
15610
16382
  ) : 0;
15611
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);
15612
16407
  return Math.max(
15613
16408
  1,
15614
- beforeSpacingPx + Math.max(
15615
- 1,
15616
- paragraphLineRange.endLineIndex - paragraphLineRange.startLineIndex
15617
- ) * Math.max(1, paragraphLineRange.lineHeightPx) + afterSpacingPx
16409
+ beforeSpacingPx + segmentContentHeightPx + afterSpacingPx
15618
16410
  );
15619
16411
  }
15620
16412
  return Math.max(
@@ -15755,6 +16547,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15755
16547
  let pageConsumedHeightPx = 0;
15756
16548
  let previousParagraphAfterPx = 0;
15757
16549
  let currentMetricsIndex = 0;
16550
+ let currentSectionPageFlowOriginPx = 0;
15758
16551
  let currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15759
16552
  0,
15760
16553
  metricsBySection[0]
@@ -15796,11 +16589,13 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15796
16589
  currentPageIndex,
15797
16590
  nodeMetrics
15798
16591
  );
16592
+ currentSectionPageFlowOriginPx = pageConsumedHeightPx;
15799
16593
  }
15800
16594
  if (hardBreakStartNodeIndexes.has(nodeIndex) && currentPageSegments.length > 0) {
15801
16595
  startNextPage();
15802
16596
  pageConsumedHeightPx = 0;
15803
16597
  previousParagraphAfterPx = 0;
16598
+ currentSectionPageFlowOriginPx = 0;
15804
16599
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15805
16600
  currentPageIndex,
15806
16601
  nodeMetrics
@@ -15855,6 +16650,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15855
16650
  startNextPage();
15856
16651
  pageConsumedHeightPx = 0;
15857
16652
  previousParagraphAfterPx = 0;
16653
+ currentSectionPageFlowOriginPx = 0;
15858
16654
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15859
16655
  currentPageIndex,
15860
16656
  nodeMetrics
@@ -15864,15 +16660,20 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15864
16660
  startNextPage();
15865
16661
  pageConsumedHeightPx = 0;
15866
16662
  previousParagraphAfterPx = 0;
16663
+ currentSectionPageFlowOriginPx = 0;
15867
16664
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15868
16665
  currentPageIndex,
15869
16666
  nodeMetrics
15870
16667
  );
15871
16668
  }
15872
- 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) {
15873
16673
  startNextPage();
15874
16674
  pageConsumedHeightPx = 0;
15875
16675
  previousParagraphAfterPx = 0;
16676
+ currentSectionPageFlowOriginPx = 0;
15876
16677
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15877
16678
  currentPageIndex,
15878
16679
  nodeMetrics
@@ -15892,7 +16693,36 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15892
16693
  nodeIndex,
15893
16694
  node
15894
16695
  );
15895
- 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(
15896
16726
  1,
15897
16727
  estimateParagraphHeightPx(
15898
16728
  node,
@@ -15916,6 +16746,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15916
16746
  startNextPage();
15917
16747
  pageConsumedHeightPx = 0;
15918
16748
  previousParagraphAfterPx = 0;
16749
+ currentSectionPageFlowOriginPx = 0;
15919
16750
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
15920
16751
  currentPageIndex,
15921
16752
  nodeMetrics
@@ -15926,38 +16757,33 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15926
16757
  1,
15927
16758
  Math.max(rawNodeHeightPx, coverFootprintPx) - collapsedMarginPx
15928
16759
  );
15929
- const paragraphLineHeightPx = estimateParagraphLineHeightPx(
15930
- node,
15931
- nodeMetrics.docGridLinePitchPx
15932
- );
15933
- const paragraphPretextSourceForSegmentRendering = buildParagraphPretextLayoutSource(node, {
15934
- allowExplicitLineBreakText: true
15935
- });
15936
16760
  const paragraphSupportsPretextSegmentRendering = Boolean(
15937
16761
  paragraphPretextSourceForSegmentRendering
15938
16762
  );
15939
- const paragraphPretextLineCount = (() => {
15940
- if (!paragraphContainsExplicitLineBreakText(node)) {
15941
- return void 0;
15942
- }
15943
- const pretextSource = paragraphPretextSourceForSegmentRendering;
15944
- if (!pretextSource) {
15945
- 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
+ );
15946
16780
  }
15947
- const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
15948
- node,
15949
- nodeMetrics.pageContentWidthPx,
15950
- numberingDefinitions
15951
- );
15952
- const pretextLayout = layoutParagraphPretextSource(
15953
- node,
15954
- pretextSource,
15955
- paragraphTextWidthPx,
15956
- paragraphLineHeightPx,
15957
- []
15958
- );
15959
- return pretextLayout?.lineCount;
15960
- })();
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;
15961
16787
  const supportsImageParagraphLineSplit = paragraphHasImage2(node) && paragraphSupportsPretextSegmentRendering;
15962
16788
  const paragraphLineCount = paragraphLineCountWithinWidth(
15963
16789
  node,
@@ -15965,6 +16791,54 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15965
16791
  numberingDefinitions
15966
16792
  );
15967
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
+ }
15968
16842
  const widowControlEnabled = paragraphWidowControlEnabled(node);
15969
16843
  const minLinesPerSegment = widowControlEnabled ? 2 : 1;
15970
16844
  const canSplitParagraphAcrossPages = paragraphCanSplitAcrossPages(node, resolvedParagraphLineCount, {
@@ -15973,6 +16847,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15973
16847
  allowImageParagraphSplit: supportsImageParagraphLineSplit
15974
16848
  }) && (!widowControlEnabled || resolvedParagraphLineCount > 3);
15975
16849
  if (canSplitParagraphAcrossPages && allowParagraphLineSplitting) {
16850
+ const pretextLayoutForSegmentSplitting = resolveParagraphPretextLayoutForSegmentRendering();
15976
16851
  const resolveSegmentReservePx = (startLineIndex, endLineIndex) => {
15977
16852
  const paragraphSegmentRange = {
15978
16853
  startLineIndex,
@@ -15985,6 +16860,16 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
15985
16860
  paragraphSegmentRange
15986
16861
  );
15987
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
+ };
15988
16873
  let lineCursor = 0;
15989
16874
  let isFirstSegment = true;
15990
16875
  while (lineCursor < resolvedParagraphLineCount) {
@@ -16000,7 +16885,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16000
16885
  lineCursor,
16001
16886
  resolvedParagraphLineCount
16002
16887
  );
16003
- const allRemainingHeightPx = topSpacingPx + linesRemaining * paragraphLineHeightPx + bottomSpacingPx;
16888
+ const allRemainingHeightPx = topSpacingPx + resolveSegmentContentHeightPx(
16889
+ lineCursor,
16890
+ resolvedParagraphLineCount
16891
+ ) + bottomSpacingPx;
16004
16892
  if (allRemainingHeightPx + allRemainingSegmentReservePx <= remainingHeightPx2) {
16005
16893
  currentPageSegments.push({
16006
16894
  nodeIndex,
@@ -16032,11 +16920,27 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16032
16920
  availableForLinesPx / paragraphLineHeightPx
16033
16921
  );
16034
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
+ }
16035
16938
  if (linesThatFit < minLinesPerSegment) {
16036
16939
  if (currentPageSegments.length > 0) {
16037
16940
  startNextPage();
16038
16941
  pageConsumedHeightPx = 0;
16039
16942
  previousParagraphAfterPx = 0;
16943
+ currentSectionPageFlowOriginPx = 0;
16040
16944
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16041
16945
  currentPageIndex,
16042
16946
  nodeMetrics
@@ -16066,7 +16970,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16066
16970
  lineCursor,
16067
16971
  segmentEndLineIndex
16068
16972
  );
16069
- if (topSpacingPx + (segmentEndLineIndex - lineCursor) * paragraphLineHeightPx + segmentReservePx <= remainingHeightPx2) {
16973
+ if (topSpacingPx + resolveSegmentContentHeightPx(
16974
+ lineCursor,
16975
+ segmentEndLineIndex
16976
+ ) + segmentReservePx <= remainingHeightPx2) {
16070
16977
  break;
16071
16978
  }
16072
16979
  linesThatFit -= 1;
@@ -16088,7 +16995,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16088
16995
  lineHeightPx: paragraphLineHeightPx
16089
16996
  }
16090
16997
  });
16091
- pageConsumedHeightPx += topSpacingPx + (safeSegmentEndLineIndex - lineCursor) * paragraphLineHeightPx;
16998
+ pageConsumedHeightPx += topSpacingPx + resolveSegmentContentHeightPx(lineCursor, safeSegmentEndLineIndex);
16092
16999
  previousParagraphAfterPx = 0;
16093
17000
  lineCursor = safeSegmentEndLineIndex;
16094
17001
  isFirstSegment = false;
@@ -16096,6 +17003,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16096
17003
  startNextPage();
16097
17004
  pageConsumedHeightPx = 0;
16098
17005
  previousParagraphAfterPx = 0;
17006
+ currentSectionPageFlowOriginPx = 0;
16099
17007
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16100
17008
  currentPageIndex,
16101
17009
  nodeMetrics
@@ -16104,7 +17012,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16104
17012
  }
16105
17013
  continue;
16106
17014
  }
16107
- let requiredHeightPx = collapsedNodeHeightPx;
17015
+ let requiredHeightPx = collapsedNodeHeightPxAdjusted;
16108
17016
  if (node.style?.keepNext === true && paragraphHasVisibleText2(node)) {
16109
17017
  let chainCursor = nodeIndex;
16110
17018
  let chainPreviousParagraphAfterPx = afterSpacingPx;
@@ -16158,6 +17066,11 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16158
17066
  1,
16159
17067
  nextRawHeightPx - collapsedChainMarginPx
16160
17068
  );
17069
+ requiredHeightPx += keepNextPaginationReservePx(
17070
+ currentChainNode,
17071
+ nextChainNode,
17072
+ chainMetrics.docGridLinePitchPx
17073
+ );
16161
17074
  chainPreviousParagraphAfterPx = nextAfterSpacingPx;
16162
17075
  }
16163
17076
  }
@@ -16195,6 +17108,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16195
17108
  startNextPage();
16196
17109
  pageConsumedHeightPx = 0;
16197
17110
  previousParagraphAfterPx = 0;
17111
+ currentSectionPageFlowOriginPx = 0;
16198
17112
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16199
17113
  currentPageIndex,
16200
17114
  nodeMetrics
@@ -16220,7 +17134,8 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16220
17134
  node,
16221
17135
  nodeMetrics.pageContentWidthPx,
16222
17136
  numberingDefinitions,
16223
- nodeMetrics.docGridLinePitchPx
17137
+ nodeMetrics.docGridLinePitchPx,
17138
+ nodeMetrics.pageContentHeightPx
16224
17139
  );
16225
17140
  if (!measuredRowHeightsPx && !estimatedRowHeightsByTableNodeIndex.has(nodeIndex)) {
16226
17141
  estimatedRowHeightsByTableNodeIndex.set(nodeIndex, estimatedRowHeightsPx);
@@ -16236,14 +17151,45 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16236
17151
  startNextPage();
16237
17152
  pageConsumedHeightPx = 0;
16238
17153
  previousParagraphAfterPx = 0;
17154
+ currentSectionPageFlowOriginPx = 0;
16239
17155
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16240
17156
  currentPageIndex,
16241
17157
  nodeMetrics
16242
17158
  );
16243
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;
16244
17174
  let rowStartIndex = 0;
16245
17175
  let rowSliceOffsetPx = 0;
17176
+ let repeatedHeaderHeightPxOnThisPage = 0;
16246
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
+ }
16247
17193
  const remainingHeightPx = Math.max(
16248
17194
  0,
16249
17195
  currentPageContentHeightPx - pageConsumedHeightPx
@@ -16257,7 +17203,11 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16257
17203
  0,
16258
17204
  currentRowTotalHeightPx - rowSliceOffsetPx
16259
17205
  );
16260
- 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;
16261
17211
  const canSplitCurrentRow = rowSliceOffsetPx > 0 || rowAllowsPageSplit(currentRow) || rowExceedsFreshPageHeightPx;
16262
17212
  const shouldContinueExistingRowSlice = rowSliceOffsetPx > 0;
16263
17213
  const rowNeedsSliceOnThisPage = ENABLE_TABLE_ROW_SLICING && canSplitCurrentRow && currentRowRemainingHeightPx > remainingHeightPx + PAGE_OVERFLOW_TOLERANCE_PX && (shouldContinueExistingRowSlice || rowExceedsFreshPageHeightPx);
@@ -16265,6 +17215,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16265
17215
  startNextPage();
16266
17216
  pageConsumedHeightPx = 0;
16267
17217
  previousParagraphAfterPx = 0;
17218
+ currentSectionPageFlowOriginPx = 0;
16268
17219
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16269
17220
  currentPageIndex,
16270
17221
  nodeMetrics
@@ -16276,6 +17227,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16276
17227
  startNextPage();
16277
17228
  pageConsumedHeightPx = 0;
16278
17229
  previousParagraphAfterPx = 0;
17230
+ currentSectionPageFlowOriginPx = 0;
16279
17231
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16280
17232
  currentPageIndex,
16281
17233
  nodeMetrics
@@ -16317,6 +17269,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16317
17269
  startNextPage();
16318
17270
  pageConsumedHeightPx = 0;
16319
17271
  previousParagraphAfterPx = 0;
17272
+ currentSectionPageFlowOriginPx = 0;
16320
17273
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16321
17274
  currentPageIndex,
16322
17275
  nodeMetrics
@@ -16325,6 +17278,24 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16325
17278
  continue;
16326
17279
  }
16327
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;
16328
17299
  rowStartIndex += 1;
16329
17300
  rowSliceOffsetPx = 0;
16330
17301
  continue;
@@ -16347,6 +17318,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16347
17318
  startNextPage();
16348
17319
  pageConsumedHeightPx = 0;
16349
17320
  previousParagraphAfterPx = 0;
17321
+ currentSectionPageFlowOriginPx = 0;
16350
17322
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16351
17323
  currentPageIndex,
16352
17324
  nodeMetrics
@@ -16377,6 +17349,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16377
17349
  startNextPage();
16378
17350
  pageConsumedHeightPx = 0;
16379
17351
  previousParagraphAfterPx = 0;
17352
+ currentSectionPageFlowOriginPx = 0;
16380
17353
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16381
17354
  currentPageIndex,
16382
17355
  nodeMetrics
@@ -16405,6 +17378,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16405
17378
  startNextPage();
16406
17379
  pageConsumedHeightPx = 0;
16407
17380
  previousParagraphAfterPx = 0;
17381
+ currentSectionPageFlowOriginPx = 0;
16408
17382
  currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
16409
17383
  currentPageIndex,
16410
17384
  nodeMetrics
@@ -16876,6 +17850,10 @@ function resolveHighlightColor(value) {
16876
17850
  }
16877
17851
  function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap = false) {
16878
17852
  const baseFontFamily = paragraphDominantFontFamily(paragraph);
17853
+ const singleLineScale = resolveParagraphSingleLineAutoScale(
17854
+ paragraph,
17855
+ baseFontFamily
17856
+ );
16879
17857
  const lineTwips = paragraph.style?.spacing?.lineTwips;
16880
17858
  const docGridMinimumLineHeightPx = resolveParagraphDocGridLinePitchPx(
16881
17859
  paragraph,
@@ -16892,7 +17870,8 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16892
17870
  }
16893
17871
  return calibrateAutoLineSpacingMultiple(
16894
17872
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16895
- baseFontFamily
17873
+ baseFontFamily,
17874
+ singleLineScale
16896
17875
  );
16897
17876
  }
16898
17877
  const lineRule = paragraph.style?.spacing?.lineRule ?? "auto";
@@ -16909,7 +17888,8 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16909
17888
  lineTwips,
16910
17889
  DEFAULT_PARAGRAPH_LINE_MULTIPLE
16911
17890
  ),
16912
- baseFontFamily
17891
+ baseFontFamily,
17892
+ singleLineScale
16913
17893
  );
16914
17894
  return Number(lineMultiple.toFixed(3));
16915
17895
  }
@@ -16920,7 +17900,8 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16920
17900
  Math.round(
16921
17901
  paragraphBaseFontSizePx(paragraph) * calibrateAutoLineSpacingMultiple(
16922
17902
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16923
- baseFontFamily
17903
+ baseFontFamily,
17904
+ singleLineScale
16924
17905
  )
16925
17906
  )
16926
17907
  );
@@ -16936,12 +17917,29 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
16936
17917
  if (lineRule === "exact") {
16937
17918
  return calibrateAutoLineSpacingMultiple(
16938
17919
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16939
- baseFontFamily
17920
+ baseFontFamily,
17921
+ singleLineScale
16940
17922
  );
16941
17923
  }
16942
17924
  return calibrateAutoLineSpacingMultiple(
16943
17925
  DEFAULT_PARAGRAPH_LINE_MULTIPLE,
16944
- 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
+ )
16945
17943
  );
16946
17944
  }
16947
17945
  function paragraphBorderToCss(border) {
@@ -17515,6 +18513,17 @@ function tableOfContentsLeadingLeftTabStopPx(paragraph) {
17515
18513
  ).sort((left, right) => left - right);
17516
18514
  return leftTabStopPositionsPx[0];
17517
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
+ }
17518
18527
  function paragraphTabCharacterCount(paragraph) {
17519
18528
  return paragraph.children.reduce((count, child) => {
17520
18529
  const text = child.type === "text" ? child.text : child.type === "form-field" ? formFieldDisplayValue2(child) : "";
@@ -18909,6 +19918,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
18909
19918
  ) ? Math.round(options?.floatingAnchorOriginCorrectionXPx) : 0;
18910
19919
  const checkboxChoiceRow = paragraphLooksLikeCheckboxChoiceRow(paragraph);
18911
19920
  const fallbackTabWidthPx = checkboxChoiceRow ? checkboxChoiceRowTabWidthPx(paragraph) : DEFAULT_TAB_STOP_PX;
19921
+ const tabLeaderLeftTabStopPositionsPx = useTabLeaderLayout ? resolveParagraphFirstLineLeftTabStopsPx(paragraph) : [];
18912
19922
  const shouldTrackTabLineWidth = !useTabLeaderLayout && !useAnchoredTabLayout;
18913
19923
  let approximateLineWidthPx = 0;
18914
19924
  let trackedVisibleChildCursor = 0;
@@ -19027,6 +20037,32 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19027
20037
  lineHeight: "1em"
19028
20038
  };
19029
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
+ };
19030
20066
  const resolvePageFieldText = (value, preferredZone) => {
19031
20067
  if (!hasPageField || value.trim().length === 0) {
19032
20068
  return value;
@@ -19316,7 +20352,10 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19316
20352
  (() => {
19317
20353
  const cropLayout = imageCropLayout(child, widthPx, heightPx);
19318
20354
  const imageVisualStyle = {
19319
- filter: appendCssFilters(child.cssFilter, options?.imageFilterSuffix),
20355
+ filter: appendCssFilters(
20356
+ child.cssFilter,
20357
+ options?.imageFilterSuffix
20358
+ ),
19320
20359
  opacity: child.cssOpacity
19321
20360
  };
19322
20361
  const imageTransformStyle = resolveImageRenderTransformStyle(child, {
@@ -19637,14 +20676,42 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19637
20676
  return;
19638
20677
  }
19639
20678
  if (leftText.length > 0) {
19640
- renderRun(
19641
- runsLeft,
19642
- child,
19643
- `${keyPrefix}-run-${childIndex}-left`,
19644
- resolveFieldText(leftText, 0),
19645
- trackedInlineChange,
19646
- childIndex
19647
- );
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
+ });
19648
20715
  }
19649
20716
  renderRun(
19650
20717
  runsRight,
@@ -19870,10 +20937,10 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19870
20937
  {
19871
20938
  "data-docx-tab-zone": "left",
19872
20939
  style: {
19873
- display: "inline-flex",
20940
+ display: "block",
20941
+ flex: "0 1 auto",
19874
20942
  minWidth: 0,
19875
- whiteSpace: "pre-wrap",
19876
- alignItems: "baseline"
20943
+ whiteSpace: "pre-wrap"
19877
20944
  },
19878
20945
  children: runsLeft
19879
20946
  }
@@ -19901,12 +20968,13 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
19901
20968
  {
19902
20969
  "data-docx-tab-zone": "right",
19903
20970
  style: {
19904
- display: "inline-flex",
19905
- minWidth: 0,
19906
- justifyContent: "flex-end",
20971
+ display: "block",
20972
+ flex: "0 0 max-content",
20973
+ minWidth: "max-content",
20974
+ width: "max-content",
19907
20975
  textAlign: "right",
19908
- whiteSpace: "pre-wrap",
19909
- alignItems: "baseline"
20976
+ whiteSpace: "nowrap",
20977
+ textIndent: 0
19910
20978
  },
19911
20979
  children: runsRight
19912
20980
  }
@@ -20156,20 +21224,7 @@ function buildParagraphNumberingLabels(model) {
20156
21224
  ])
20157
21225
  );
20158
21226
  const countersByNumId = /* @__PURE__ */ new Map();
20159
- const headingCountersByAbstractNumId = /* @__PURE__ */ new Map();
20160
- const isHeadingLikeParagraph = (paragraph) => {
20161
- if (Number.isFinite(paragraph.style?.headingLevel)) {
20162
- return true;
20163
- }
20164
- if (isTableOfContentsParagraph(paragraph)) {
20165
- return true;
20166
- }
20167
- const styleId = paragraph.style?.styleId?.trim().toLowerCase();
20168
- if (!styleId) {
20169
- return false;
20170
- }
20171
- return /(?:^|[\s_-])heading(?:[\s_-]?\d+)?$/.test(styleId) || /^heading\d*$/.test(styleId);
20172
- };
21227
+ const abstractCountersByAbstractNumId = /* @__PURE__ */ new Map();
20173
21228
  const registerParagraph = (paragraph, key) => {
20174
21229
  const paragraphNumbering = paragraph.style?.numbering;
20175
21230
  if (!paragraphNumbering || paragraphNumbering.numId <= 0) {
@@ -20180,13 +21235,12 @@ function buildParagraphNumberingLabels(model) {
20180
21235
  const level = findNumberingLevelDefinition(numbering, numId, ilvl);
20181
21236
  const numberingInstance = numberingInstanceByNumId.get(numId);
20182
21237
  const abstractNumId = numberingInstance?.abstractNumId;
20183
- const isSharedCounterParagraph = isHeadingLikeParagraph(paragraph);
20184
21238
  const template = level?.text ?? `%${ilvl + 1}.`;
20185
21239
  if (!template || template.trim().length === 0) {
20186
21240
  return;
20187
21241
  }
20188
21242
  const counters = countersByNumId.get(numId) ?? [];
20189
- const sharedAbstractCounters = isSharedCounterParagraph && Number.isFinite(abstractNumId) ? headingCountersByAbstractNumId.get(abstractNumId) ?? [] : void 0;
21243
+ const sharedAbstractCounters = Number.isFinite(abstractNumId) ? abstractCountersByAbstractNumId.get(abstractNumId) ?? [] : void 0;
20190
21244
  let parentCountersChanged = false;
20191
21245
  for (let index = 0; index < ilvl; index += 1) {
20192
21246
  const abstractCounterValue = sharedAbstractCounters && Number.isFinite(sharedAbstractCounters[index]) ? Math.max(1, Math.round(sharedAbstractCounters[index])) : void 0;
@@ -20215,7 +21269,7 @@ function buildParagraphNumberingLabels(model) {
20215
21269
  for (let index = ilvl + 1; index < sharedAbstractCounters.length; index += 1) {
20216
21270
  sharedAbstractCounters[index] = void 0;
20217
21271
  }
20218
- headingCountersByAbstractNumId.set(
21272
+ abstractCountersByAbstractNumId.set(
20219
21273
  abstractNumId,
20220
21274
  sharedAbstractCounters
20221
21275
  );
@@ -20961,6 +22015,14 @@ function tableBorderToCss(border) {
20961
22015
  const color = border?.color ?? "#000000";
20962
22016
  return `${widthPx}px ${cssStyle} ${color}`;
20963
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
+ }
20964
22026
  function borderTypeVisible(type) {
20965
22027
  const normalizedType = normalizeBorderType(type);
20966
22028
  return Boolean(
@@ -21412,6 +22474,68 @@ function resolveTableCellBorderCss(tableBorders, cellBorders, rowIndex, rowCount
21412
22474
  ...left !== void 0 ? { borderLeft: left } : void 0
21413
22475
  };
21414
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
+ }
21415
22539
  function resolveTableCellDiagonalOverlayCss(tableBorders, cellBorders) {
21416
22540
  const diagonalDownBorder = cellBorders?.tl2br ?? tableBorders?.tl2br;
21417
22541
  const diagonalUpBorder = cellBorders?.tr2bl ?? tableBorders?.tr2bl;
@@ -23303,6 +24427,7 @@ function useDocxEditor(options = {}) {
23303
24427
  const [status, setStatus] = React.useState(
23304
24428
  options.initialStatus ?? "Ready"
23305
24429
  );
24430
+ const [isImporting, setIsImporting] = React.useState(false);
23306
24431
  const [documentTheme, setDocumentThemeState] = React.useState(options.initialDocumentTheme ?? "light");
23307
24432
  const [showTrackedChanges, setShowTrackedChangesState] = React.useState(options.initialShowTrackedChanges ?? false);
23308
24433
  const [paginationInfo, setPaginationInfo] = React.useState({
@@ -23825,26 +24950,40 @@ function useDocxEditor(options = {}) {
23825
24950
  setStatus("Only .docx files are supported");
23826
24951
  return;
23827
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
+ });
23828
24964
  try {
23829
24965
  const buffer = await file.arrayBuffer();
23830
- const pkg = await parseDocx(buffer);
24966
+ const { pkg, model: nextModel } = await importDocxViaWorker(buffer);
23831
24967
  await loadEmbeddedFontsFromPackage(pkg);
23832
- const nextModel = buildDocModel(pkg);
23833
- setModel(nextModel);
23834
- setDocumentLoadNonce((current) => current + 1);
23835
- setHistory({ past: [], future: [] });
23836
- setHistoryRestoreRequest(void 0);
23837
- setBasePackage(pkg);
23838
- setFileName(file.name);
23839
- setSelection({ kind: "paragraph", nodeIndex: 0 });
23840
- setActiveTextRangeState(void 0);
23841
- setPendingRunStyle(void 0);
23842
- 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
+ });
23843
24980
  setStatus(`Loaded ${file.name}`);
23844
24981
  } catch (error) {
23845
24982
  setStatus(
23846
24983
  `Failed to load file: ${error instanceof Error ? error.message : "Unknown error"}`
23847
24984
  );
24985
+ } finally {
24986
+ setIsImporting(false);
23848
24987
  }
23849
24988
  },
23850
24989
  [loadEmbeddedFontsFromPackage]
@@ -26769,6 +27908,7 @@ function useDocxEditor(options = {}) {
26769
27908
  documentLoadNonce,
26770
27909
  fileName,
26771
27910
  status,
27911
+ isImporting,
26772
27912
  documentTheme,
26773
27913
  trackedChanges,
26774
27914
  showTrackedChanges,
@@ -27006,8 +28146,15 @@ async function rasterizeDocxViewerPageSurfaceToCanvas(params) {
27006
28146
  function resolveDocxPageThumbnailResolution(options) {
27007
28147
  const safeSourceWidthPx = Math.max(1, Math.round(options.sourceWidthPx));
27008
28148
  const safeSourceHeightPx = Math.max(1, Math.round(options.sourceHeightPx));
27009
- const widthBoundPx = Number.isFinite(options.maxWidthPx) ? Math.max(1, Math.round(options.maxWidthPx)) : 180;
27010
- const heightBoundPx = Number.isFinite(options.maxHeightPx) ? Math.max(1, Math.round(options.maxHeightPx)) : Number.POSITIVE_INFINITY;
28149
+ const resolutionBounds = typeof options.resolution === "number" && Number.isFinite(options.resolution) && options.resolution > 0 ? {
28150
+ maxWidthPx: Number(options.resolution),
28151
+ maxHeightPx: Number(options.resolution)
28152
+ } : typeof options.resolution === "object" && options.resolution ? {
28153
+ maxWidthPx: Number.isFinite(options.resolution.maxWidth) && Number(options.resolution.maxWidth) > 0 ? Number(options.resolution.maxWidth) : void 0,
28154
+ maxHeightPx: Number.isFinite(options.resolution.maxHeight) && Number(options.resolution.maxHeight) > 0 ? Number(options.resolution.maxHeight) : void 0
28155
+ } : void 0;
28156
+ const widthBoundPx = Number.isFinite(options.maxWidthPx) ? Math.max(1, Math.round(options.maxWidthPx)) : Number.isFinite(resolutionBounds?.maxWidthPx) ? Math.max(1, Math.round(resolutionBounds?.maxWidthPx)) : 180;
28157
+ const heightBoundPx = Number.isFinite(options.maxHeightPx) ? Math.max(1, Math.round(options.maxHeightPx)) : Number.isFinite(resolutionBounds?.maxHeightPx) ? Math.max(1, Math.round(resolutionBounds?.maxHeightPx)) : Number.POSITIVE_INFINITY;
27011
28158
  const scale = Math.min(
27012
28159
  1,
27013
28160
  widthBoundPx / safeSourceWidthPx,
@@ -27046,12 +28193,9 @@ function useDocxPageThumbnails(editor, options = {}) {
27046
28193
  [pageSurfaceRegistryEditor]
27047
28194
  );
27048
28195
  React.useEffect(
27049
- () => subscribeDocxViewerPageSurfaces(
27050
- pageSurfaceRegistryEditor,
27051
- () => {
27052
- setPageSurfaceEpoch((current) => current + 1);
27053
- }
27054
- ),
28196
+ () => subscribeDocxViewerPageSurfaces(pageSurfaceRegistryEditor, () => {
28197
+ setPageSurfaceEpoch((current) => current + 1);
28198
+ }),
27055
28199
  [pageSurfaceRegistryEditor]
27056
28200
  );
27057
28201
  const mountedPageElements = React.useMemo(
@@ -27094,6 +28238,7 @@ function useDocxPageThumbnails(editor, options = {}) {
27094
28238
  const resolution = resolveDocxPageThumbnailResolution({
27095
28239
  sourceWidthPx: sourceSize.widthPx,
27096
28240
  sourceHeightPx: sourceSize.heightPx,
28241
+ resolution: options.resolution,
27097
28242
  maxWidthPx: options.maxWidthPx,
27098
28243
  maxHeightPx: options.maxHeightPx,
27099
28244
  pixelRatio: options.pixelRatio
@@ -27124,6 +28269,7 @@ function useDocxPageThumbnails(editor, options = {}) {
27124
28269
  fallbackLayout.pageWidthPx,
27125
28270
  mountedPageElements,
27126
28271
  options.disabled,
28272
+ options.resolution,
27127
28273
  options.maxHeightPx,
27128
28274
  options.maxWidthPx,
27129
28275
  options.pixelRatio,
@@ -27136,7 +28282,9 @@ function useDocxPageThumbnails(editor, options = {}) {
27136
28282
  );
27137
28283
  await Promise.all(tasks);
27138
28284
  }, [renderPageThumbnailToCanvas]);
27139
- const renderPageThumbnailToCanvasRef = React.useRef(renderPageThumbnailToCanvas);
28285
+ const renderPageThumbnailToCanvasRef = React.useRef(
28286
+ renderPageThumbnailToCanvas
28287
+ );
27140
28288
  React.useEffect(() => {
27141
28289
  renderPageThumbnailToCanvasRef.current = renderPageThumbnailToCanvas;
27142
28290
  }, [renderPageThumbnailToCanvas]);
@@ -27152,6 +28300,7 @@ function useDocxPageThumbnails(editor, options = {}) {
27152
28300
  editor.model,
27153
28301
  mountedPageElements,
27154
28302
  options.disabled,
28303
+ options.resolution,
27155
28304
  options.maxHeightPx,
27156
28305
  options.maxWidthPx,
27157
28306
  options.pixelRatio,
@@ -27169,6 +28318,7 @@ function useDocxPageThumbnails(editor, options = {}) {
27169
28318
  const resolution = resolveDocxPageThumbnailResolution({
27170
28319
  sourceWidthPx: sourceSize.widthPx,
27171
28320
  sourceHeightPx: sourceSize.heightPx,
28321
+ resolution: options.resolution,
27172
28322
  maxWidthPx: options.maxWidthPx,
27173
28323
  maxHeightPx: options.maxHeightPx,
27174
28324
  pixelRatio: options.pixelRatio
@@ -27182,6 +28332,13 @@ function useDocxPageThumbnails(editor, options = {}) {
27182
28332
  isMounted: Boolean(pageElement && pageElement.isConnected),
27183
28333
  status: state?.status ?? (pageElement ? "idle" : "unavailable"),
27184
28334
  error: state?.error,
28335
+ paint: (canvas) => {
28336
+ if (!canvas || options.disabled) {
28337
+ return false;
28338
+ }
28339
+ void renderPageThumbnailToCanvasRef.current(pageIndex, canvas);
28340
+ return true;
28341
+ },
27185
28342
  canvasRef: canvasRefCallbacksRef.current.get(pageIndex) ?? (() => {
27186
28343
  const nextCanvasRef = (canvas) => {
27187
28344
  if (canvas) {
@@ -27204,6 +28361,11 @@ function useDocxPageThumbnails(editor, options = {}) {
27204
28361
  );
27205
28362
  return nextRenderToCanvas;
27206
28363
  })(),
28364
+ aspectRatio: sourceSize.widthPx / Math.max(1, sourceSize.heightPx),
28365
+ contentWidth: sourceSize.widthPx,
28366
+ contentHeight: sourceSize.heightPx,
28367
+ width: resolution.widthPx,
28368
+ height: resolution.heightPx,
27207
28369
  ...resolution
27208
28370
  };
27209
28371
  });
@@ -27212,19 +28374,36 @@ function useDocxPageThumbnails(editor, options = {}) {
27212
28374
  fallbackLayout.pageHeightPx,
27213
28375
  fallbackLayout.pageWidthPx,
27214
28376
  mountedPageElements,
28377
+ options.disabled,
28378
+ options.resolution,
27215
28379
  options.maxHeightPx,
27216
28380
  options.maxWidthPx,
27217
28381
  options.pixelRatio,
27218
28382
  pageThumbnailStates
27219
28383
  ]);
28384
+ const paintThumbnail = React.useCallback(
28385
+ (pageIndex, canvas) => {
28386
+ if (!canvas || options.disabled) {
28387
+ return false;
28388
+ }
28389
+ const thumbnail = thumbnails[pageIndex];
28390
+ if (!thumbnail) {
28391
+ return false;
28392
+ }
28393
+ return thumbnail.paint(canvas);
28394
+ },
28395
+ [options.disabled, thumbnails]
28396
+ );
27220
28397
  return React.useMemo(
27221
28398
  () => ({
28399
+ paintThumbnail,
27222
28400
  thumbnails,
27223
28401
  rerenderAttachedThumbnails
27224
28402
  }),
27225
- [rerenderAttachedThumbnails, thumbnails]
28403
+ [paintThumbnail, rerenderAttachedThumbnails, thumbnails]
27226
28404
  );
27227
28405
  }
28406
+ var useDocxViewerThumbnails = useDocxPageThumbnails;
27228
28407
  function useDocxDocumentTheme(editor) {
27229
28408
  const setDocumentTheme = React.useCallback(
27230
28409
  (theme) => {
@@ -27740,7 +28919,11 @@ function renderHeaderNode(node, keyPrefix, documentTheme, numberingDefinitions,
27740
28919
  return normalizeColumnWidthsPx(widthsPx, columnCount, tableWidthPx, 1);
27741
28920
  })();
27742
28921
  const rawResolvedTableWidthPx = tableWidthPx ?? rawTableColumnWidthsPx.reduce((sum, widthPx) => sum + widthPx, 0);
27743
- 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;
27744
28927
  const resolvedTableWidthPx = clampTableWidthPx(
27745
28928
  rawResolvedTableWidthPx,
27746
28929
  maxTableWidthPx
@@ -27853,6 +29036,7 @@ function renderHeaderNode(node, keyPrefix, documentTheme, numberingDefinitions,
27853
29036
  "span",
27854
29037
  {
27855
29038
  contentEditable: false,
29039
+ "data-docx-pagination-ignore": "true",
27856
29040
  style: {
27857
29041
  position: "absolute",
27858
29042
  top: -TABLE_HANDLE_SAFEZONE_TOP_PX,
@@ -27870,6 +29054,7 @@ function renderHeaderNode(node, keyPrefix, documentTheme, numberingDefinitions,
27870
29054
  "span",
27871
29055
  {
27872
29056
  contentEditable: false,
29057
+ "data-docx-pagination-ignore": "true",
27873
29058
  style: {
27874
29059
  position: "absolute",
27875
29060
  right: -TABLE_HANDLE_SAFEZONE_RIGHT_PX,
@@ -28481,6 +29666,11 @@ function DocxEditorViewer({
28481
29666
  measuredPageContentIdentityKeysByIndex,
28482
29667
  setMeasuredPageContentIdentityKeysByIndex
28483
29668
  ] = React.useState([]);
29669
+ const [hasMeasuredBodyFooterOverlap, setHasMeasuredBodyFooterOverlap] = React.useState(false);
29670
+ const measuredBodyFooterOverlapCandidateRef = React.useRef({
29671
+ signature: void 0,
29672
+ consecutivePasses: 0
29673
+ });
28484
29674
  const [, setRenderableImageSourceRevision] = React.useState(0);
28485
29675
  const [activeEditableParagraphSegment, setActiveEditableParagraphSegment] = React.useState(void 0);
28486
29676
  const wrappedParagraphTextareaRef = React.useRef(
@@ -28490,6 +29680,10 @@ function DocxEditorViewer({
28490
29680
  const wrappedParagraphSelectionDragRef = React.useRef(void 0);
28491
29681
  const wrappedParagraphSurfaceRegistryRef = React.useRef(/* @__PURE__ */ new Map());
28492
29682
  const [isInitialPaginationSettled, setIsInitialPaginationSettled] = React.useState(!deferInitialPaginationPaint);
29683
+ const [
29684
+ initialPaginationBackgroundRefinementUnlocked,
29685
+ setInitialPaginationBackgroundRefinementUnlocked
29686
+ ] = React.useState(!deferInitialPaginationPaint);
28493
29687
  const [postImportPaginationUnlocked, setPostImportPaginationUnlocked] = React.useState(false);
28494
29688
  const [
28495
29689
  initialPaginationReservedLayoutState,
@@ -28531,6 +29725,11 @@ function DocxEditorViewer({
28531
29725
  React.useEffect(() => {
28532
29726
  setMeasuredPageContentHeightByIndex([]);
28533
29727
  setMeasuredPageContentIdentityKeysByIndex([]);
29728
+ setHasMeasuredBodyFooterOverlap(false);
29729
+ measuredBodyFooterOverlapCandidateRef.current = {
29730
+ signature: void 0,
29731
+ consecutivePasses: 0
29732
+ };
28534
29733
  setTableMeasuredRowHeights({});
28535
29734
  setTableRowHeights({});
28536
29735
  setTableColumnWidths({});
@@ -28574,6 +29773,9 @@ function DocxEditorViewer({
28574
29773
  }
28575
29774
  initialPaginationRevealFrameRef.current = null;
28576
29775
  setIsInitialPaginationSettled(!deferInitialPaginationPaint);
29776
+ setInitialPaginationBackgroundRefinementUnlocked(
29777
+ !deferInitialPaginationPaint
29778
+ );
28577
29779
  }, [deferInitialPaginationPaint, editor.documentLoadNonce]);
28578
29780
  const [activeRowResize, setActiveRowResize] = React.useState();
28579
29781
  const [activeEmbeddedRowResize, setActiveEmbeddedRowResize] = React.useState();
@@ -28862,6 +30064,28 @@ function DocxEditorViewer({
28862
30064
  }
28863
30065
  return widthByNodeIndex;
28864
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]);
28865
30089
  const sectionColumnsBySectionIndex = React.useMemo(
28866
30090
  () => documentSections.map(
28867
30091
  (section) => parseSectionColumns(section.sectionPropertiesXml)
@@ -28911,6 +30135,7 @@ function DocxEditorViewer({
28911
30135
  activeDraftKeys,
28912
30136
  numberingDefinitions: editor.model.metadata.numberingDefinitions,
28913
30137
  pageContentWidthPxByNodeIndex,
30138
+ pageContentHeightPxByNodeIndex,
28914
30139
  docGridLinePitchPxByNodeIndex
28915
30140
  }
28916
30141
  );
@@ -28920,6 +30145,7 @@ function DocxEditorViewer({
28920
30145
  editor.canUndo,
28921
30146
  editor.model.metadata.numberingDefinitions,
28922
30147
  editor.model.nodes,
30148
+ pageContentHeightPxByNodeIndex,
28923
30149
  pageContentWidthPxByNodeIndex,
28924
30150
  disableMeasuredImportPagination,
28925
30151
  tableDraftLayoutEpoch,
@@ -28977,17 +30203,43 @@ function DocxEditorViewer({
28977
30203
  (count, node) => count + (node.type === "paragraph" && paragraphHasLastRenderedPageBreak(node) ? 1 : 0),
28978
30204
  0
28979
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
+ );
28980
30219
  const minimumPageCount = Math.max(1, hardBreakCount + 1);
28981
30220
  const targetPageCount = Number.isFinite(storedDocumentPageCount2) && storedDocumentPageCount2 > 0 ? Math.max(
28982
30221
  minimumPageCount,
28983
30222
  Math.round(storedDocumentPageCount2)
28984
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
+ }
28985
30239
  const pureEstimatedPages = buildEstimatedPages(
28986
30240
  tableMeasuredRowHeightsForPagination,
28987
30241
  null
28988
30242
  );
28989
- let estimatedPages = buildEstimatedPages(tableMeasuredRowHeightsForPagination);
28990
- let estimatedPagesUseMeasuredPageContentHeightsForRender = canUseMeasuredPageContentHeights;
28991
30243
  if (measuredPageContentHeightByIndex && measuredPageContentHeightByIndex.length > 0) {
28992
30244
  const measuredPagesAreOnlySplitParagraphs = estimatedPages.length > 0 && estimatedPages.every(
28993
30245
  (pageSegments) => documentPageContainsOnlySplitParagraphSegments(pageSegments)
@@ -28998,21 +30250,29 @@ function DocxEditorViewer({
28998
30250
  if (measuredPagesAreOnlySplitParagraphs && purePagesAreOnlySplitParagraphs && pureEstimatedPages.length < estimatedPages.length) {
28999
30251
  estimatedPages = pureEstimatedPages;
29000
30252
  estimatedPagesUseMeasuredPageContentHeightsForRender = false;
30253
+ estimatedRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30254
+ estimatedRenderPageContentHeightScale = void 0;
29001
30255
  }
29002
30256
  }
29003
- if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && tableMeasuredRowHeightsForPagination) {
30257
+ if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && tableMeasuredRowHeightsForPagination && !hasMultiColumnRenderedPageBreakHints) {
29004
30258
  const candidatePages = [
29005
30259
  {
29006
30260
  pages: estimatedPages,
29007
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30261
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30262
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30263
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
29008
30264
  },
29009
30265
  {
29010
30266
  pages: buildEstimatedPages(void 0),
29011
- useMeasuredPageContentHeightsForRender: canUseMeasuredPageContentHeights
30267
+ useMeasuredPageContentHeightsForRender: canUseMeasuredPageContentHeights,
30268
+ renderMeasuredPageContentHeightsPxByPageIndex: canUseMeasuredPageContentHeights ? measuredPageContentHeightByIndex : void 0,
30269
+ renderPageContentHeightScale: void 0
29012
30270
  },
29013
30271
  {
29014
30272
  pages: buildEstimatedPages(void 0, null),
29015
- useMeasuredPageContentHeightsForRender: false
30273
+ useMeasuredPageContentHeightsForRender: false,
30274
+ renderMeasuredPageContentHeightsPxByPageIndex: void 0,
30275
+ renderPageContentHeightScale: void 0
29016
30276
  }
29017
30277
  ];
29018
30278
  const bestCandidate = candidatePages.reduce((best, candidate) => {
@@ -29024,11 +30284,15 @@ function DocxEditorViewer({
29024
30284
  });
29025
30285
  estimatedPages = bestCandidate.pages;
29026
30286
  estimatedPagesUseMeasuredPageContentHeightsForRender = bestCandidate.useMeasuredPageContentHeightsForRender;
29027
- } 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) {
29028
30290
  const pureEstimatedPages2 = buildEstimatedPages(void 0, null);
29029
30291
  if (Math.abs(pureEstimatedPages2.length - targetPageCount) < Math.abs(estimatedPages.length - targetPageCount)) {
29030
30292
  estimatedPages = pureEstimatedPages2;
29031
30293
  estimatedPagesUseMeasuredPageContentHeightsForRender = false;
30294
+ estimatedRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30295
+ estimatedRenderPageContentHeightScale = void 0;
29032
30296
  }
29033
30297
  }
29034
30298
  const measuredPageHeightOverridesReduceContent = !editor.canUndo && !editor.canRedo && !floatingMovePreview && !dropCapMovePreview && estimatedPages.some((segments, pageIndex) => {
@@ -29055,7 +30319,9 @@ function DocxEditorViewer({
29055
30319
  if (!Number.isFinite(storedDocumentPageCount2) || storedDocumentPageCount2 <= 0) {
29056
30320
  return {
29057
30321
  pages: estimatedPages,
29058
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30322
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30323
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30324
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
29059
30325
  };
29060
30326
  }
29061
30327
  const resolvedTargetPageCount = targetPageCount ?? minimumPageCount;
@@ -29065,22 +30331,26 @@ function DocxEditorViewer({
29065
30331
  )
29066
30332
  );
29067
30333
  const allowMeasuredReductionOverPaginationReconciliation = measuredPageHeightOverridesReduceContent && estimatedPages.length > resolvedTargetPageCount;
29068
- const allowStoredPageCountReconciliation = !editor.canUndo && !editor.canRedo && !hasPageAnchoredFloatingFooterContent && shouldAllowStoredPageCountReduction({
30334
+ const allowStoredPageCountReconciliation = !editor.canUndo && !editor.canRedo && !hasPageAnchoredFloatingFooterContent && !hasMultiColumnRenderedPageBreakHints && shouldAllowStoredPageCountReduction({
29069
30335
  estimatedPageCount: estimatedPages.length,
29070
30336
  targetPageCount: resolvedTargetPageCount,
29071
30337
  hasLastRenderedPageBreakHints,
29072
- renderedBreakHintPageCount
30338
+ renderedBreakHintPageCount,
30339
+ hasMeasuredBodyFooterOverlap
29073
30340
  }) && (!measuredPageHeightOverridesReduceContent || allowMeasuredReductionOverPaginationReconciliation);
29074
30341
  if (!allowStoredPageCountReconciliation) {
29075
30342
  return {
29076
30343
  pages: estimatedPages,
29077
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30344
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30345
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex,
30346
+ renderPageContentHeightScale: estimatedRenderPageContentHeightScale
29078
30347
  };
29079
30348
  }
29080
30349
  if (estimatedPages.length === resolvedTargetPageCount) {
29081
30350
  return {
29082
30351
  pages: estimatedPages,
29083
- useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender
30352
+ useMeasuredPageContentHeightsForRender: estimatedPagesUseMeasuredPageContentHeightsForRender,
30353
+ renderMeasuredPageContentHeightsPxByPageIndex: estimatedRenderMeasuredPageContentHeightsPxByPageIndex
29084
30354
  };
29085
30355
  }
29086
30356
  const reconciliationScales = allowMeasuredReductionOverPaginationReconciliation ? [
@@ -29100,7 +30370,7 @@ function DocxEditorViewer({
29100
30370
  1.28,
29101
30371
  1.3
29102
30372
  ] : void 0;
29103
- const reconcileCandidatePages = (initialPages, measuredTableRowHeightsByNodeIndex, measuredPageContentHeightsOverride) => reconcilePagesToTargetCountByScalingHeight({
30373
+ const reconcileCandidatePages = (initialPages, measuredTableRowHeightsByNodeIndex, measuredPageContentHeightsOverride) => reconcilePageCountCandidateToTargetCountByScalingHeight({
29104
30374
  initialPages,
29105
30375
  targetPageCount: resolvedTargetPageCount,
29106
30376
  maxDifference: hasTableInternalPageBreaks ? 2 : 3,
@@ -29126,27 +30396,38 @@ function DocxEditorViewer({
29126
30396
  }
29127
30397
  )
29128
30398
  });
29129
- let reconciledPages = reconcileCandidatePages(
30399
+ let reconciledCandidate = reconcileCandidatePages(
29130
30400
  estimatedPages,
29131
30401
  tableMeasuredRowHeightsForPagination,
29132
30402
  estimatedPagesUseMeasuredPageContentHeightsForRender ? measuredPageContentHeightByIndex : null
29133
30403
  );
30404
+ let reconciledPages = reconciledCandidate.pages;
29134
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;
29135
30411
  if (!editor.canUndo && !editor.canRedo) {
29136
30412
  const pureEstimatedPages2 = buildEstimatedPages(void 0, null);
29137
- const pureReconciledPages = reconcileCandidatePages(
30413
+ const pureReconciledCandidate = reconcileCandidatePages(
29138
30414
  pureEstimatedPages2,
29139
30415
  void 0,
29140
30416
  null
29141
30417
  );
30418
+ const pureReconciledPages = pureReconciledCandidate.pages;
29142
30419
  if (Math.abs(pureReconciledPages.length - resolvedTargetPageCount) < Math.abs(reconciledPages.length - resolvedTargetPageCount)) {
29143
30420
  reconciledPages = pureReconciledPages;
29144
30421
  reconciledPagesUseMeasuredPageContentHeightsForRender = false;
30422
+ reconciledRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30423
+ reconciledRenderPageContentHeightScale = pureReconciledCandidate.scale;
29145
30424
  }
29146
30425
  }
29147
30426
  return {
29148
30427
  pages: reconciledPages,
29149
- useMeasuredPageContentHeightsForRender: reconciledPagesUseMeasuredPageContentHeightsForRender
30428
+ useMeasuredPageContentHeightsForRender: reconciledPagesUseMeasuredPageContentHeightsForRender,
30429
+ renderMeasuredPageContentHeightsPxByPageIndex: reconciledRenderMeasuredPageContentHeightsPxByPageIndex,
30430
+ renderPageContentHeightScale: reconciledRenderPageContentHeightScale
29150
30431
  };
29151
30432
  }, [
29152
30433
  editor.canRedo,
@@ -29165,12 +30446,17 @@ function DocxEditorViewer({
29165
30446
  isReadOnly,
29166
30447
  floatingMovePreview,
29167
30448
  dropCapMovePreview,
30449
+ deferInitialPaginationPaint,
29168
30450
  disableMeasuredImportPagination,
30451
+ hasMeasuredBodyFooterOverlap,
30452
+ initialPaginationBackgroundRefinementUnlocked,
29169
30453
  measuredPageContentHeightByIndex,
29170
30454
  tableMeasuredRowHeightsForPagination
29171
30455
  ]);
29172
30456
  const pageNodeSegmentsByPage = pageSegmentationPlan.pages;
29173
30457
  const useMeasuredPageContentHeightsForRender = pageSegmentationPlan.useMeasuredPageContentHeightsForRender;
30458
+ const renderMeasuredPageContentHeightsPxByPageIndex = pageSegmentationPlan.renderMeasuredPageContentHeightsPxByPageIndex;
30459
+ const renderPageContentHeightScale = pageSegmentationPlan.renderPageContentHeightScale;
29174
30460
  const pageNodeSegmentIdentityKeysByPage = React.useMemo(
29175
30461
  () => pageNodeSegmentsByPage.map(
29176
30462
  (pageSegments) => documentPageNodeSegmentsIdentityKey(pageSegments)
@@ -29386,6 +30672,32 @@ function DocxEditorViewer({
29386
30672
  };
29387
30673
  }, [editor.model.nodes, pageNodeSegmentsByPage]);
29388
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]);
29389
30701
  const hideDocumentUntilPaginationSettled = deferInitialPaginationPaint && !isInitialPaginationSettled;
29390
30702
  const estimateDocumentStackHeightPx = React.useCallback(
29391
30703
  (count) => {
@@ -29457,28 +30769,34 @@ function DocxEditorViewer({
29457
30769
  const hasExternalVisiblePageRange = Number.isFinite(Number(visiblePageRange?.startPageIndex)) || Number.isFinite(Number(visiblePageRange?.endPageIndex));
29458
30770
  const [deferInternalPageVirtualization, setDeferInternalPageVirtualization] = React.useState(false);
29459
30771
  const [internalVirtualScrollElement, setInternalVirtualScrollElement] = React.useState(null);
30772
+ const [observedVisiblePageRange, setObservedVisiblePageRange] = React.useState(void 0);
29460
30773
  const pageVirtualizationSettleDelayMs = Math.max(
29461
30774
  0,
29462
30775
  Math.round(
29463
30776
  Number.isFinite(pageVirtualization?.settleDelayMs) ? pageVirtualization?.settleDelayMs : DEFAULT_PAGE_VIRTUALIZATION_SETTLE_DELAY_MS
29464
30777
  )
29465
30778
  );
29466
- const pageVirtualizationOverscan = Math.max(
30779
+ const rawPageVirtualizationOverscan = Math.max(
29467
30780
  0,
29468
30781
  Math.round(
29469
30782
  Number.isFinite(pageVirtualization?.overscan) ? pageVirtualization?.overscan : DEFAULT_PAGE_VIRTUALIZATION_OVERSCAN
29470
30783
  )
29471
30784
  );
30785
+ const pageVirtualizationOverscan = hasLargeTableLayoutSurface && !Number.isFinite(pageVirtualization?.overscan) ? 0 : rawPageVirtualizationOverscan;
29472
30786
  const webdriverActive = typeof navigator !== "undefined" && navigator.webdriver === true;
29473
30787
  const internalPageVirtualizationRequested = pageVirtualization?.enabled !== false && !hasExternalVisiblePageRange && !hideDocumentUntilPaginationSettled && isInitialPaginationSettled && !deferInternalPageVirtualization && !webdriverActive && pageCount > 1;
29474
30788
  React.useEffect(() => {
29475
- setDeferInternalPageVirtualization(true);
29476
- }, [editor.documentLoadNonce]);
30789
+ setDeferInternalPageVirtualization(!hasLargeTableLayoutSurface);
30790
+ }, [editor.documentLoadNonce, hasLargeTableLayoutSurface]);
29477
30791
  React.useEffect(() => {
29478
30792
  if (typeof window === "undefined" || webdriverActive || pageCount <= 1) {
29479
30793
  setDeferInternalPageVirtualization(true);
29480
30794
  return;
29481
30795
  }
30796
+ if (hasLargeTableLayoutSurface) {
30797
+ setDeferInternalPageVirtualization(false);
30798
+ return;
30799
+ }
29482
30800
  const timeoutId = window.setTimeout(() => {
29483
30801
  setDeferInternalPageVirtualization(false);
29484
30802
  }, pageVirtualizationSettleDelayMs);
@@ -29487,6 +30805,7 @@ function DocxEditorViewer({
29487
30805
  };
29488
30806
  }, [
29489
30807
  editor.documentLoadNonce,
30808
+ hasLargeTableLayoutSurface,
29490
30809
  pageCount,
29491
30810
  pageVirtualizationSettleDelayMs,
29492
30811
  webdriverActive
@@ -29500,15 +30819,30 @@ function DocxEditorViewer({
29500
30819
  );
29501
30820
  }, [editor.documentLoadNonce, pageCount, trackedChangesEnabled]);
29502
30821
  const internalPageVirtualizationEnabled = internalPageVirtualizationRequested && internalVirtualScrollElement !== null;
29503
- const internalPageVirtualizer = (0, import_react_virtual.useVirtualizer)({
29504
- count: Math.max(1, pageCount),
29505
- getScrollElement: () => internalPageVirtualizationEnabled ? internalVirtualScrollElement : null,
29506
- 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) => {
29507
30828
  const pageLayout = pageSectionInfoByIndex[pageIndex]?.layout ?? documentLayout;
29508
30829
  return Math.max(1, pageLayout.pageHeightPx + DOC_PAGE_BREAK_GAP);
29509
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,
29510
30843
  overscan: pageVirtualizationOverscan
29511
30844
  });
30845
+ const internalPageVirtualizer = internalVirtualScrollUsesWindow ? internalWindowPageVirtualizer : internalElementPageVirtualizer;
29512
30846
  const internalVirtualItems = internalPageVirtualizer.getVirtualItems();
29513
30847
  const internalVisiblePageRange = React.useMemo(() => {
29514
30848
  if (!internalPageVirtualizationEnabled) {
@@ -29543,7 +30877,134 @@ function DocxEditorViewer({
29543
30877
  endPageIndex
29544
30878
  };
29545
30879
  }, [internalPageVirtualizationEnabled, internalVirtualItems, pageCount]);
29546
- 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);
29547
31008
  const normalizedVisiblePageRange = React.useMemo(() => {
29548
31009
  if (pageCount <= 0) {
29549
31010
  return {
@@ -29571,7 +31032,8 @@ function DocxEditorViewer({
29571
31032
  pageCount
29572
31033
  ]);
29573
31034
  const initialPremeasureStartPageIndex = hasExternalVisiblePageRange ? normalizedVisiblePageRange.startPageIndex : 0;
29574
- 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);
29575
31037
  const measureAllPagesBeforeInitialReveal = hideDocumentUntilPaginationSettled && pageCount > 0 && initialPremeasureStartPageIndex === 0 && initialPremeasureEndPageIndex >= pageCount - 1;
29576
31038
  const visiblePageStartIndex = measureAllPagesBeforeInitialReveal ? 0 : hideDocumentUntilPaginationSettled ? initialPremeasureStartPageIndex : normalizedVisiblePageRange.startPageIndex;
29577
31039
  const visiblePageEndIndex = measureAllPagesBeforeInitialReveal ? pageCount - 1 : hideDocumentUntilPaginationSettled ? initialPremeasureEndPageIndex : normalizedVisiblePageRange.endPageIndex;
@@ -29585,20 +31047,64 @@ function DocxEditorViewer({
29585
31047
  }
29586
31048
  return indexes;
29587
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]);
29588
31087
  const paginationMeasurementEnabled = hideDocumentUntilPaginationSettled || postImportPaginationUnlocked;
29589
31088
  const visiblePagesHavePendingPaginationMeasurements = React.useMemo(() => {
29590
31089
  if (pageCount === 0) {
29591
31090
  return false;
29592
31091
  }
29593
31092
  for (const pageIndex of visiblePageIndexes) {
29594
- 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)) {
29595
31098
  return true;
29596
31099
  }
29597
- for (const segment of pageNodeSegmentsByPage[pageIndex] ?? []) {
31100
+ for (const segment of pageSegments) {
29598
31101
  const tableNode = editor.model.nodes[segment.nodeIndex];
29599
31102
  if (!tableNode || tableNode.type !== "table") {
29600
31103
  continue;
29601
31104
  }
31105
+ if (segment.tableRowSlice) {
31106
+ continue;
31107
+ }
29602
31108
  const measuredHeights = tableMeasuredRowHeights[segment.nodeIndex];
29603
31109
  if (!measuredHeights || measuredHeights.length !== tableNode.rows.length) {
29604
31110
  return true;
@@ -29608,6 +31114,7 @@ function DocxEditorViewer({
29608
31114
  return false;
29609
31115
  }, [
29610
31116
  editor.model.nodes,
31117
+ hasLargeTableLayoutSurface,
29611
31118
  measuredPageContentHeightByIndex,
29612
31119
  pageCount,
29613
31120
  pageNodeSegmentsByPage,
@@ -30244,7 +31751,9 @@ function DocxEditorViewer({
30244
31751
  const footerElement = pageFooterElementsRef.current.get(pageIndex);
30245
31752
  const headerHeightPx = headerElement ? Math.max(
30246
31753
  0,
30247
- Math.round(headerElement.getBoundingClientRect().height / zoomScale)
31754
+ Math.round(
31755
+ headerElement.getBoundingClientRect().height / zoomScale
31756
+ )
30248
31757
  ) : 0;
30249
31758
  const docxFooterTopPx = resolveFooterNodesFloatingBoundaryTopPx(
30250
31759
  pageHeaderAndFooterNodes[pageIndex]?.footerNodes ?? [],
@@ -30310,7 +31819,9 @@ function DocxEditorViewer({
30310
31819
  bottomPx: rect.bottom,
30311
31820
  widthPx: rect.width,
30312
31821
  heightPx: rect.height,
30313
- 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(
30314
31825
  element.closest(
30315
31826
  `[${PAGE_CONTENT_MEASUREMENT_IGNORE_ATTRIBUTE}="true"]`
30316
31827
  )
@@ -30340,7 +31851,31 @@ function DocxEditorViewer({
30340
31851
  const nextMeasuredHeights = nextMeasuredPageDiagnostics.map(
30341
31852
  (diagnostics) => diagnostics.heightPx
30342
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
+ };
30343
31875
  const frameId = window.requestAnimationFrame(() => {
31876
+ if (nextMeasuredBodyFooterOverlapLatchState.shouldLatch) {
31877
+ setHasMeasuredBodyFooterOverlap(true);
31878
+ }
30344
31879
  setMeasuredPageContentHeightByIndex((current) => {
30345
31880
  const stabilizedHeights = stabilizeMeasuredPageContentHeights(
30346
31881
  current,
@@ -30393,6 +31928,7 @@ function DocxEditorViewer({
30393
31928
  paginationMeasurementEnabled,
30394
31929
  paginationMeasurementEpoch,
30395
31930
  pageCount,
31931
+ editor.model.metadata.documentPageCount,
30396
31932
  pageNodeSegmentsByPage,
30397
31933
  pageNodeSegmentIdentityKeysByPage,
30398
31934
  pageSectionInfoByIndex,
@@ -30425,6 +31961,27 @@ function DocxEditorViewer({
30425
31961
  isInitialPaginationSettled,
30426
31962
  pageCount
30427
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
+ ]);
30428
31985
  React.useEffect(() => {
30429
31986
  if (!deferInitialPaginationPaint || isInitialPaginationSettled) {
30430
31987
  return;
@@ -34643,10 +36200,14 @@ function DocxEditorViewer({
34643
36200
  if (node.type !== "table") {
34644
36201
  return;
34645
36202
  }
36203
+ const visibleRowIndexes = visibleTableRowIndexesByNodeIndex.get(nodeIndex);
36204
+ if (!visibleRowIndexes || visibleRowIndexes.size === 0) {
36205
+ return;
36206
+ }
34646
36207
  const measuredByRowIndex = /* @__PURE__ */ new Map();
34647
36208
  const recordMeasuredRow = (rowIndex, rowHeightPx) => {
34648
36209
  const normalizedRowIndex = Math.max(0, Math.round(rowIndex));
34649
- if (normalizedRowIndex >= node.rows.length) {
36210
+ if (normalizedRowIndex >= node.rows.length || !visibleRowIndexes.has(normalizedRowIndex)) {
34650
36211
  return;
34651
36212
  }
34652
36213
  const normalizedHeight = normalizeMeasuredTableRowHeightPx(rowHeightPx);
@@ -34679,7 +36240,8 @@ function DocxEditorViewer({
34679
36240
  );
34680
36241
  });
34681
36242
  }
34682
- const rowCells = document.querySelectorAll(
36243
+ const measurementRoot = viewerRootRef.current ?? document;
36244
+ const rowCells = measurementRoot.querySelectorAll(
34683
36245
  `[data-docx-table-cell='true'][data-docx-table-index='${nodeIndex}'][data-docx-row-index]`
34684
36246
  );
34685
36247
  rowCells.forEach((cellElement) => {
@@ -34710,7 +36272,8 @@ function DocxEditorViewer({
34710
36272
  node,
34711
36273
  pageContentWidthPxByNodeIndex.get(nodeIndex),
34712
36274
  editor.model.metadata.numberingDefinitions,
34713
- docGridLinePitchPxByNodeIndex.get(nodeIndex)
36275
+ docGridLinePitchPxByNodeIndex.get(nodeIndex),
36276
+ pageContentHeightPxByNodeIndex.get(nodeIndex)
34714
36277
  );
34715
36278
  const previousMeasuredRowHeights = tableMeasuredRowHeights[nodeIndex];
34716
36279
  const measuredHeights = node.rows.map((_, rowIndex) => {
@@ -34776,8 +36339,7 @@ function DocxEditorViewer({
34776
36339
  tableColumnWidths,
34777
36340
  tableRowHeights,
34778
36341
  tableDraftLayoutEpoch,
34779
- visiblePageEndIndex,
34780
- visiblePageStartIndex
36342
+ visibleTableRowIndexesByNodeIndex
34781
36343
  ]);
34782
36344
  const normalizeResizableHeights = React.useCallback(
34783
36345
  (rowHeights) => {
@@ -36237,6 +37799,29 @@ function DocxEditorViewer({
36237
37799
  `${keyPrefix}-fragment-image-${lineIndex}-${run.key}-${overlapStart}`
36238
37800
  );
36239
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
+ }
36240
37825
  const slice = run.text.slice(
36241
37826
  overlapStart - run.startOffset,
36242
37827
  overlapEnd - run.startOffset
@@ -39072,6 +40657,488 @@ function DocxEditorViewer({
39072
40657
  boxSizing: "border-box",
39073
40658
  overflow: floatingMovePreview || dropCapMovePreview ? "visible" : "clip"
39074
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
+ };
39075
41142
  const renderDocumentNode = (node, nodeIndex, tableRowRange, tableRowSlice, paragraphLineRange, options) => {
39076
41143
  const nodeDocGridLinePitchPx = docGridLinePitchPxByNodeIndex.get(nodeIndex);
39077
41144
  const nodeContentWidthPx = Math.max(
@@ -39109,7 +41176,7 @@ function DocxEditorViewer({
39109
41176
  paragraphLineRange
39110
41177
  );
39111
41178
  const paragraphHasActiveEditableSegment = activeEditableParagraphSegment?.nodeIndex === nodeIndex;
39112
- const shouldTrackParagraphElement = !hasPartialLineRange || paragraphSegmentIsActiveEditable || !paragraphHasActiveEditableSegment && paragraphSegmentStartLine === 0;
41179
+ const shouldTrackParagraphElement = options?.suppressParagraphElementTracking === true ? false : !hasPartialLineRange || paragraphSegmentIsActiveEditable || !paragraphHasActiveEditableSegment && paragraphSegmentStartLine === 0;
39113
41180
  const isManualPageBreakParagraph = paragraphIsOnlyExplicitPageBreak2(node);
39114
41181
  const paragraphContentWidthPx = nodeContentWidthPx;
39115
41182
  const paragraphRenderTextWidthPx = paragraphAvailableTextWidthPx(
@@ -39118,7 +41185,8 @@ function DocxEditorViewer({
39118
41185
  editor.model.metadata.numberingDefinitions
39119
41186
  );
39120
41187
  const pretextParagraphSource = hasPartialLineRange ? buildParagraphPretextLayoutSource(node, {
39121
- allowExplicitLineBreakText: true
41188
+ allowExplicitLineBreakText: true,
41189
+ expandTabsForLayout: true
39122
41190
  }) : void 0;
39123
41191
  const pretextParagraphLayout = hasPartialLineRange && pretextParagraphSource ? layoutParagraphPretextSource(
39124
41192
  node,
@@ -39213,7 +41281,13 @@ function DocxEditorViewer({
39213
41281
  },
39214
41282
  `node-${nodeIndex}-numbering-marker-${paragraphSegmentStartLine}`
39215
41283
  ) : void 0;
39216
- 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;
39217
41291
  const resolvedPageLayout = options?.pageLayout ?? documentLayout;
39218
41292
  const paragraphContainsLikelyFullPageCoverImage = node.children.some(
39219
41293
  (child) => child.type === "image" && shouldRenderAbsoluteFloatingImage(child) && likelyFullPageCoverImageRelativeToContentBox(
@@ -39283,8 +41357,11 @@ function DocxEditorViewer({
39283
41357
  const paragraphStyle = {
39284
41358
  ...baseParagraphStyle,
39285
41359
  ...hasPartialLineRange ? {
39286
- marginTop: paragraphSegmentStartLine === 0 ? beforeSpacingPx : 0,
39287
- 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
39288
41365
  } : void 0,
39289
41366
  ...letterheadStyleAdjustments ?? void 0,
39290
41367
  ...options?.suppressLetterheadColumnLayout && options?.isFirstInLetterheadColumn ? { marginTop: 0 } : void 0,
@@ -39323,7 +41400,8 @@ function DocxEditorViewer({
39323
41400
  {
39324
41401
  style: {
39325
41402
  minHeight: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
39326
- marginBottom: -(paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx),
41403
+ marginTop: -paragraphSegmentClipBleedTopPx,
41404
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
39327
41405
  paddingTop: paragraphSegmentClipBleedTopPx,
39328
41406
  paddingBottom: paragraphSegmentClipBleedBottomPx,
39329
41407
  overflow: "visible"
@@ -39347,7 +41425,8 @@ function DocxEditorViewer({
39347
41425
  {
39348
41426
  style: {
39349
41427
  height: paragraphSegmentVisibleHeightPx + paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx,
39350
- marginBottom: -(paragraphSegmentClipBleedTopPx + paragraphSegmentClipBleedBottomPx),
41428
+ marginTop: -paragraphSegmentClipBleedTopPx,
41429
+ marginBottom: -paragraphSegmentClipBleedBottomPx,
39351
41430
  overflow: "hidden"
39352
41431
  },
39353
41432
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -39933,7 +42012,7 @@ ${currentText.slice(end)}`;
39933
42012
  },
39934
42013
  children: !editable ? renderedInteractiveParagraphContent : null
39935
42014
  },
39936
- 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}` : ""}`
39937
42016
  );
39938
42017
  }
39939
42018
  const tableRowSliceOffsetPxForWrapper = tableRowSlice ? Math.max(0, Math.round(tableRowSlice.startOffsetPx)) : 0;
@@ -39966,7 +42045,7 @@ ${currentText.slice(end)}`;
39966
42045
  paddingTop: tableRowSliceTopBleedPxForWrapper,
39967
42046
  paddingBottom: tableRowSliceBottomBleedPxForWrapper,
39968
42047
  boxSizing: "border-box",
39969
- overflow: "clip"
42048
+ overflow: "visible"
39970
42049
  } : void 0
39971
42050
  },
39972
42051
  onPointerEnter: () => {
@@ -39999,11 +42078,12 @@ ${currentText.slice(end)}`;
39999
42078
  },
40000
42079
  children: (() => {
40001
42080
  const tableIndentPx = twipsToSignedPixels(node.style?.indentTwips) ?? 0;
42081
+ const columnCount = tableColumnCount(node);
42082
+ const collapsedHorizontalBorderBleedPx = resolveCollapsedTableHorizontalOuterBleedPx(node, columnCount);
40002
42083
  const maxTableWidthPx = Math.max(
40003
42084
  120,
40004
- nodeContentWidthPx - tableIndentPx
42085
+ nodeContentWidthPx - tableIndentPx - collapsedHorizontalBorderBleedPx
40005
42086
  );
40006
- const columnCount = tableColumnCount(node);
40007
42087
  const tableWidthPx = twipsToPixels(node.style?.widthTwips);
40008
42088
  const hasStoredColumnWidths = (tableColumnWidths[nodeIndex]?.length ?? 0) === columnCount;
40009
42089
  const rawColumnWidthsPx = resolveTableColumnWidths(
@@ -40096,6 +42176,7 @@ ${currentText.slice(end)}`;
40096
42176
  "span",
40097
42177
  {
40098
42178
  contentEditable: false,
42179
+ "data-docx-pagination-ignore": "true",
40099
42180
  style: {
40100
42181
  position: "absolute",
40101
42182
  top: -TABLE_HANDLE_SAFEZONE_TOP_PX,
@@ -40113,6 +42194,7 @@ ${currentText.slice(end)}`;
40113
42194
  "span",
40114
42195
  {
40115
42196
  contentEditable: false,
42197
+ "data-docx-pagination-ignore": "true",
40116
42198
  style: {
40117
42199
  position: "absolute",
40118
42200
  right: -TABLE_HANDLE_SAFEZONE_RIGHT_PX,
@@ -40202,10 +42284,7 @@ ${currentText.slice(end)}`;
40202
42284
  style: {
40203
42285
  width: resolvedTableWidthPx > 0 ? `${resolvedTableWidthPx}px` : "100%",
40204
42286
  ...tableElementBorderStyle(node, tableBorderSpacingPx),
40205
- tableLayout: node.style?.layout === "autofit" ? "auto" : "fixed",
40206
- ...hasTableRowSlice && tableRowSliceOffsetPx > 0 ? {
40207
- transform: `translateY(-${tableRowSliceOffsetPx - tableRowSliceTopBleedPx}px)`
40208
- } : void 0
42287
+ tableLayout: node.style?.layout === "autofit" ? "auto" : "fixed"
40209
42288
  },
40210
42289
  children: [
40211
42290
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("colgroup", { children: columnWidthsPx.map((widthPx, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -40253,7 +42332,7 @@ ${currentText.slice(end)}`;
40253
42332
  );
40254
42333
  const recursiveCellParagraphs = tableCellParagraphsRecursively(cell.nodes);
40255
42334
  const cellHasImage = tableCellHasImage(cell.nodes);
40256
- const editableCell = selectedByAnchor && !isMultiCellSelectionActive && !cellHasImage && !isReadOnly && cellParagraphs.length > 0;
42335
+ const editableCell = selectedByAnchor && !isSlicedRow && !isMultiCellSelectionActive && !cellHasImage && !isReadOnly && cellParagraphs.length > 0;
40257
42336
  const nestedParagraphIndexesByNode = /* @__PURE__ */ new Map();
40258
42337
  recursiveCellParagraphs.forEach(
40259
42338
  (paragraph, paragraphIndex) => {
@@ -40263,7 +42342,7 @@ ${currentText.slice(end)}`;
40263
42342
  );
40264
42343
  }
40265
42344
  );
40266
- const tableCellEditScope = recursiveCellParagraphs.length > 0 && !isReadOnly && !isMultiCellSelectionActive && !cellHasImage ? {
42345
+ const tableCellEditScope = recursiveCellParagraphs.length > 0 && !isReadOnly && !isSlicedRow && !isMultiCellSelectionActive && !cellHasImage ? {
40267
42346
  isEditable: true,
40268
42347
  draftKeyPrefix: `${nodeIndex}:${rowIndex}:${cellIndex}`,
40269
42348
  paragraphIndexesByNode: nestedParagraphIndexesByNode,
@@ -40304,6 +42383,38 @@ ${currentText.slice(end)}`;
40304
42383
  ).reduce((sum, widthPx) => sum + widthPx, 0);
40305
42384
  const cellBackgroundColor = cell.style?.backgroundColor ?? row.style?.backgroundColor;
40306
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;
40307
42418
  const renderedEditableCellContent = editableCell ? (() => {
40308
42419
  let paragraphCursor = 0;
40309
42420
  return cell.nodes.map(
@@ -40401,10 +42512,7 @@ ${currentText.slice(end)}`;
40401
42512
  cell.style?.borders
40402
42513
  ),
40403
42514
  ...tableSpacingPaddingStyle(
40404
- mergeTableSpacing(
40405
- tableCellMarginTwips,
40406
- cell.style?.marginTwips
40407
- )
42515
+ mergedCellMarginTwips
40408
42516
  ),
40409
42517
  backgroundColor: cellBackgroundColor,
40410
42518
  verticalAlign: cell.style?.verticalAlign ?? "top",
@@ -41225,6 +43333,45 @@ ${currentText.slice(end)}`;
41225
43333
  );
41226
43334
  }
41227
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
+ }
41228
43375
  ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "grid", gap: 4 }, children: (() => {
41229
43376
  let paragraphCursor = 0;
41230
43377
  return cell.nodes.map(
@@ -42716,10 +44863,11 @@ ${currentText.slice(end)}`;
42716
44863
  pageLayout.pageHeightPx - pageLayout.marginsPx.top - pageLayout.marginsPx.bottom
42717
44864
  ),
42718
44865
  metricsBySection: paginationSectionMetrics,
42719
- measuredPageContentHeightsPxByPageIndex: measuredPageContentHeightByIndex,
44866
+ measuredPageContentHeightsPxByPageIndex: renderMeasuredPageContentHeightsPxByPageIndex,
42720
44867
  measuredPageContentIdentityKeysByPageIndex: measuredPageContentIdentityKeysByIndex,
42721
44868
  pageIdentityKey: pageNodeSegmentIdentityKeysByPage[pageIndex],
42722
- useMeasuredPageContentHeights: useMeasuredPageContentHeightsForRender
44869
+ useMeasuredPageContentHeights: useMeasuredPageContentHeightsForRender,
44870
+ pageContentHeightScale: renderPageContentHeightScale
42723
44871
  });
42724
44872
  const headerFooterBodyDimmed = pageHeaderFooterEditActive;
42725
44873
  const documentPageBackgroundColor = editor.model.metadata.documentBackgroundColor;
@@ -43013,6 +45161,7 @@ ${currentText.slice(end)}`;
43013
45161
  display: "flex",
43014
45162
  flexDirection: "column",
43015
45163
  minHeight: pageBodyAvailableHeightPx,
45164
+ overflow: "visible",
43016
45165
  ...documentContentFilter ? { filter: documentContentFilter } : void 0
43017
45166
  },
43018
45167
  children: [
@@ -43080,6 +45229,44 @@ ${currentText.slice(end)}`;
43080
45229
  if (!columnNode) {
43081
45230
  return null;
43082
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
+ }
43083
45270
  const renderedNode = renderDocumentNode(
43084
45271
  columnNode,
43085
45272
  columnSegment.nodeIndex,
@@ -44751,6 +46938,9 @@ var DEFAULT_MIN_PARAGRAPH_LINE_HEIGHT_PX = 14;
44751
46938
  var PARAGRAPH_SEGMENT_TOP_BLEED_PX2 = 22;
44752
46939
  var PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX2 = 6;
44753
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;
44754
46944
  function paragraphSegmentHasPartialLineRange2(paragraphLineRange) {
44755
46945
  if (!paragraphLineRange) {
44756
46946
  return false;
@@ -44819,6 +47009,48 @@ function normalizedPositivePixelValue(value, fallback) {
44819
47009
  }
44820
47010
  return Math.max(1, Math.round(value));
44821
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
+ }
44822
47054
  function normalizedMeasuredTableRowHeights(measuredRowHeightsPx, expectedRowCount, minParagraphLineHeightPx) {
44823
47055
  if (!measuredRowHeightsPx || measuredRowHeightsPx.length !== expectedRowCount) {
44824
47056
  return void 0;
@@ -45011,6 +47243,12 @@ function collectDocxEstimatedOverflowBreakStartNodeIndexes(model, hardBreakStart
45011
47243
  paragraphBeforeSpacingPx2(nextChainNode)
45012
47244
  );
45013
47245
  requiredHeightPx += Math.max(1, nextRawHeightPx - collapsedChainMarginPx);
47246
+ requiredHeightPx += keepNextParagraphReservePx(
47247
+ currentChainNode,
47248
+ nextChainNode,
47249
+ callbacks,
47250
+ chainMetrics.docGridLinePitchPx
47251
+ );
45014
47252
  chainPreviousParagraphAfterPx = paragraphAfterSpacingPx2(nextChainNode);
45015
47253
  }
45016
47254
  }
@@ -45107,7 +47345,10 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
45107
47345
  nodeMetrics.pageContentHeightPx
45108
47346
  );
45109
47347
  }
45110
- if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak2(node) && currentPageSegments.length > 0) {
47348
+ if (preferLastRenderedParagraphStartBreaks && paragraphStartsWithLastRenderedPageBreak2(node) && shouldHonorParagraphStartLastRenderedPageBreak2({
47349
+ pageConsumedHeightPx,
47350
+ pageContentHeightPx: currentPageContentHeightPx
47351
+ }) && currentPageSegments.length > 0) {
45111
47352
  startNextPage();
45112
47353
  pageConsumedHeightPx = 0;
45113
47354
  previousParagraphAfterPx = 0;
@@ -45332,6 +47573,12 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
45332
47573
  paragraphBeforeSpacingPx2(nextChainNode)
45333
47574
  );
45334
47575
  requiredHeightPx += Math.max(1, nextRawHeightPx - collapsedChainMarginPx);
47576
+ requiredHeightPx += keepNextParagraphReservePx(
47577
+ currentChainNode,
47578
+ nextChainNode,
47579
+ callbacks,
47580
+ chainMetrics.docGridLinePitchPx
47581
+ );
45335
47582
  chainPreviousParagraphAfterPx = paragraphAfterSpacingPx2(nextChainNode);
45336
47583
  }
45337
47584
  }
@@ -46132,6 +48379,7 @@ function ReactDocxViewer({
46132
48379
  useDocxPagination,
46133
48380
  useDocxParagraphStyles,
46134
48381
  useDocxTrackChanges,
48382
+ useDocxViewerThumbnails,
46135
48383
  withPart
46136
48384
  });
46137
48385
  //# sourceMappingURL=index.cjs.map