@extend-ai/react-docx 0.6.1 → 0.6.2

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
@@ -3978,10 +3978,14 @@ function parseParagraphRuns(paragraphXml2, context) {
3978
3978
  }
3979
3979
  }
3980
3980
  });
3981
+ let hyperlinkRangeCursor = 0;
3981
3982
  return runRanges.map((range, runIndex) => {
3982
- const link = hyperlinkRanges.find(
3983
- (hyperlinkRange) => range.start >= hyperlinkRange.start && range.end <= hyperlinkRange.end && hyperlinkRange.href
3984
- )?.href ?? fieldLinksByRun.get(runIndex);
3983
+ while (hyperlinkRangeCursor < hyperlinkRanges.length && hyperlinkRanges[hyperlinkRangeCursor].end <= range.start) {
3984
+ hyperlinkRangeCursor += 1;
3985
+ }
3986
+ const currentHyperlinkRange = hyperlinkRanges[hyperlinkRangeCursor];
3987
+ const hyperlinkHref = currentHyperlinkRange && range.start >= currentHyperlinkRange.start && range.end <= currentHyperlinkRange.end ? currentHyperlinkRange.href : void 0;
3988
+ const link = hyperlinkHref ?? fieldLinksByRun.get(runIndex);
3985
3989
  return {
3986
3990
  xml: paragraphXml2.slice(range.start, range.end),
3987
3991
  start: range.start,
@@ -4577,9 +4581,14 @@ function parseParagraph(paragraphXml2, context) {
4577
4581
  runs
4578
4582
  );
4579
4583
  const contentTokens = [];
4584
+ let formFieldTokenCursor = 0;
4580
4585
  for (const run of runs) {
4581
- const insideFormField = formFieldTokens.some(
4582
- (formFieldToken) => run.start >= formFieldToken.start && run.end <= formFieldToken.end
4586
+ while (formFieldTokenCursor < formFieldTokens.length && formFieldTokens[formFieldTokenCursor].end <= run.start) {
4587
+ formFieldTokenCursor += 1;
4588
+ }
4589
+ const currentFormFieldToken = formFieldTokens[formFieldTokenCursor];
4590
+ const insideFormField = Boolean(
4591
+ currentFormFieldToken && run.start >= currentFormFieldToken.start && run.end <= currentFormFieldToken.end
4583
4592
  );
4584
4593
  if (insideFormField) {
4585
4594
  continue;
@@ -8994,6 +9003,9 @@ function paragraphHasExplicitPageBreak(paragraph) {
8994
9003
  return sourceXml.length > 0 && PAGE_BREAK_XML_PATTERN.test(sourceXml);
8995
9004
  }
8996
9005
  function paragraphHasPageBreakBefore(paragraph) {
9006
+ if (paragraph.style?.pageBreakBefore === true) {
9007
+ return true;
9008
+ }
8997
9009
  const sourceXml = paragraph.sourceXml ?? "";
8998
9010
  if (!sourceXml) {
8999
9011
  return false;
@@ -10379,6 +10391,8 @@ var LARGE_TABLE_PAGE_VIRTUALIZATION_OVERSCAN = 0;
10379
10391
  var LARGE_TABLE_PAGE_ADJACENT_RENDER_COUNT = 1;
10380
10392
  var DEFAULT_PAGE_VIRTUALIZATION_SETTLE_DELAY_MS = 350;
10381
10393
  var ENABLE_TABLE_ROW_SLICING = true;
10394
+ var MIN_TABLE_ROW_SLICE_REMAINING_HEIGHT_PX = MIN_PARAGRAPH_LINE_HEIGHT_PX * 2;
10395
+ var TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX = 2;
10382
10396
  var TOP_AND_BOTTOM_VERTICAL_DRAG_SNAP_PX = 10;
10383
10397
  var HEADER_FOOTER_INACTIVE_OPACITY = 0.5;
10384
10398
  var LETTERHEAD_INDENT_MIN_TWIPS = 900;
@@ -10414,6 +10428,10 @@ var paragraphDropCapBySourceXml = /* @__PURE__ */ new Map();
10414
10428
  var paragraphTrackedMarkupBySourceXml = /* @__PURE__ */ new Map();
10415
10429
  var paragraphMeasureCanvasContext;
10416
10430
  var textWidthByFontAndValue = /* @__PURE__ */ new Map();
10431
+ var estimatedTextAdvanceWidthByFontAndValue = /* @__PURE__ */ new Map();
10432
+ var pretextWordBreakModeByText = /* @__PURE__ */ new Map();
10433
+ var paragraphBaseFontSizePxByParagraph = /* @__PURE__ */ new WeakMap();
10434
+ var paragraphDominantFontFamilyByParagraph = /* @__PURE__ */ new WeakMap();
10417
10435
  function setCacheEntry(cache, key, value) {
10418
10436
  if (!cache.has(key) && cache.size >= XML_CACHE_MAX_ENTRIES) {
10419
10437
  const oldestKey = cache.keys().next().value;
@@ -11877,7 +11895,23 @@ function resolvePageContentHeightPxForPageSegments(pageSegments, pageIndex, defa
11877
11895
  );
11878
11896
  }
11879
11897
  function resolveRenderPageContentHeightPxForPageSegments(params) {
11880
- const resolvedHeightPx = resolvePageContentHeightPxForPageSegments(
11898
+ const firstNodeIndex = params.pageSegments[0]?.nodeIndex ?? 0;
11899
+ const metricsIndex = resolvePaginationSectionMetricsIndexForNodeIndex(
11900
+ params.metricsBySection,
11901
+ firstNodeIndex,
11902
+ 0
11903
+ );
11904
+ const sectionHeightMultiplier = Math.max(
11905
+ 1,
11906
+ Math.round(
11907
+ params.metricsBySection[metricsIndex]?.pageContentHeightMultiplier ?? 1
11908
+ )
11909
+ );
11910
+ const pageContainsOnlySplitParagraphSegments = documentPageContainsOnlySplitParagraphSegments(params.pageSegments);
11911
+ const measuredHeightPx = params.useMeasuredPageContentHeights === false ? void 0 : params.measuredPageContentHeightsPxByPageIndex?.[params.pageIndex];
11912
+ const measuredHeightMatchesCurrentPage = params.pageIdentityKey === void 0 || params.measuredPageContentIdentityKeysByPageIndex?.[params.pageIndex] === void 0 || params.measuredPageContentIdentityKeysByPageIndex?.[params.pageIndex] === params.pageIdentityKey;
11913
+ const usesMeasuredVisualHeight = Number.isFinite(measuredHeightPx) && measuredHeightMatchesCurrentPage && !pageContainsOnlySplitParagraphSegments;
11914
+ let resolvedHeightPx = resolvePageContentHeightPxForPageSegments(
11881
11915
  params.pageSegments,
11882
11916
  params.pageIndex,
11883
11917
  params.defaultPageContentHeightPx,
@@ -11887,12 +11921,15 @@ function resolveRenderPageContentHeightPxForPageSegments(params) {
11887
11921
  params.pageIdentityKey
11888
11922
  );
11889
11923
  if (params.useMeasuredPageContentHeights === false && Number.isFinite(params.pageContentHeightScale) && Math.abs(params.pageContentHeightScale - 1) >= 1e-3) {
11890
- return Math.max(
11924
+ resolvedHeightPx = Math.max(
11891
11925
  120,
11892
11926
  Math.round(resolvedHeightPx * params.pageContentHeightScale)
11893
11927
  );
11894
11928
  }
11895
- return resolvedHeightPx;
11929
+ if (usesMeasuredVisualHeight || sectionHeightMultiplier <= 1) {
11930
+ return resolvedHeightPx;
11931
+ }
11932
+ return Math.max(120, Math.round(resolvedHeightPx / sectionHeightMultiplier));
11896
11933
  }
11897
11934
  function documentPageContainsOnlySplitParagraphSegments(pageSegments) {
11898
11935
  return pageSegments.length > 0 && pageSegments.every(
@@ -12446,7 +12483,9 @@ function firstExplicitFontFamilyInNodeTree(nodes) {
12446
12483
  if (node.type === "table") {
12447
12484
  for (const row of node.rows) {
12448
12485
  for (const cell of row.cells) {
12449
- const nestedFontFamily = firstExplicitFontFamilyInNodeTree(cell.nodes);
12486
+ const nestedFontFamily = firstExplicitFontFamilyInNodeTree(
12487
+ cell.nodes
12488
+ );
12450
12489
  if (nestedFontFamily) {
12451
12490
  return nestedFontFamily;
12452
12491
  }
@@ -13352,11 +13391,19 @@ function buildParagraphPretextTabSpacerText(widthPx, style, paragraphBaseFontPx)
13352
13391
  while (measuredWidthPx + spacerAdvancePx * 0.5 < safeWidthPx && spacerCount < 64) {
13353
13392
  spacerCount += 1;
13354
13393
  spacerText = spacerCharacter.repeat(spacerCount);
13355
- measuredWidthPx = measureTextWidthPx2(spacerText, style, paragraphBaseFontPx);
13394
+ measuredWidthPx = measureTextWidthPx2(
13395
+ spacerText,
13396
+ style,
13397
+ paragraphBaseFontPx
13398
+ );
13356
13399
  }
13357
13400
  while (spacerCount > 1) {
13358
13401
  const nextText = spacerCharacter.repeat(spacerCount - 1);
13359
- const nextWidthPx = measureTextWidthPx2(nextText, style, paragraphBaseFontPx);
13402
+ const nextWidthPx = measureTextWidthPx2(
13403
+ nextText,
13404
+ style,
13405
+ paragraphBaseFontPx
13406
+ );
13360
13407
  if (Math.abs(nextWidthPx - safeWidthPx) >= Math.abs(measuredWidthPx - safeWidthPx)) {
13361
13408
  break;
13362
13409
  }
@@ -13647,7 +13694,20 @@ function buildSyntheticPretextLayoutSource(text, style) {
13647
13694
  };
13648
13695
  }
13649
13696
  function pretextWordBreakModeForText(text) {
13650
- return KEEP_ALL_SCRIPT_RE.test(text) ? "keep-all" : "normal";
13697
+ const cached = pretextWordBreakModeByText.get(text);
13698
+ if (cached) {
13699
+ return cached;
13700
+ }
13701
+ const mode = KEEP_ALL_SCRIPT_RE.test(text) ? "keep-all" : "normal";
13702
+ setCacheEntry(pretextWordBreakModeByText, text, mode);
13703
+ while (pretextWordBreakModeByText.size > TEXT_MEASURE_CACHE_MAX_ENTRIES) {
13704
+ const firstKey = pretextWordBreakModeByText.keys().next().value;
13705
+ if (!firstKey) {
13706
+ break;
13707
+ }
13708
+ pretextWordBreakModeByText.delete(firstKey);
13709
+ }
13710
+ return mode;
13651
13711
  }
13652
13712
  function sanitizeRenderedPretextFragmentText(text) {
13653
13713
  return text.replace(/\r\n?|\n/g, "");
@@ -14131,36 +14191,55 @@ function estimateTextAdvanceWidthPx(text, style) {
14131
14191
  if (!text) {
14132
14192
  return 0;
14133
14193
  }
14134
- const normalized = text.replace(/\u00a0/g, " ");
14135
14194
  const fontSizePx = runFontSizePx(style);
14195
+ const normalized = text.includes("\xA0") ? text.replace(/\u00a0/g, " ") : text;
14196
+ const cacheKey = `${fontSizePx}\0${normalized}`;
14197
+ const cached = estimatedTextAdvanceWidthByFontAndValue.get(cacheKey);
14198
+ if (cached !== void 0) {
14199
+ return cached;
14200
+ }
14136
14201
  let total = 0;
14137
- for (const char of normalized) {
14138
- if (char === "\n" || char === "\r") {
14202
+ for (let index = 0; index < normalized.length; index += 1) {
14203
+ const code = normalized.charCodeAt(index);
14204
+ if (code === 10 || code === 13) {
14139
14205
  continue;
14140
14206
  }
14141
- if (char === " ") {
14207
+ if (code === 9) {
14142
14208
  total += fontSizePx * 2;
14143
14209
  continue;
14144
14210
  }
14145
- if (char === " ") {
14211
+ if (code === 32) {
14146
14212
  total += fontSizePx * 0.33;
14147
14213
  continue;
14148
14214
  }
14149
- if (/[.,:;'"`!|ilI1]/.test(char)) {
14215
+ if (code === 33 || code === 39 || code === 44 || code === 46 || code === 49 || code === 58 || code === 59 || code === 73 || code === 96 || code === 105 || code === 108 || code === 124) {
14150
14216
  total += fontSizePx * 0.29;
14151
14217
  continue;
14152
14218
  }
14153
- if (/[A-Z0-9]/.test(char)) {
14219
+ if (code >= 65 && code <= 90 || code >= 48 && code <= 57) {
14154
14220
  total += fontSizePx * 0.6;
14155
14221
  continue;
14156
14222
  }
14157
- if (/[\u3000-\u9fff]/.test(char)) {
14223
+ if (code >= 12288 && code <= 40959) {
14158
14224
  total += fontSizePx * 0.95;
14159
14225
  continue;
14160
14226
  }
14161
14227
  total += fontSizePx * 0.54;
14162
14228
  }
14163
- return Math.max(0, Math.round(total));
14229
+ const estimatedWidthPx = Math.max(0, Math.round(total));
14230
+ setCacheEntry(
14231
+ estimatedTextAdvanceWidthByFontAndValue,
14232
+ cacheKey,
14233
+ estimatedWidthPx
14234
+ );
14235
+ while (estimatedTextAdvanceWidthByFontAndValue.size > TEXT_MEASURE_CACHE_MAX_ENTRIES) {
14236
+ const firstKey = estimatedTextAdvanceWidthByFontAndValue.keys().next().value;
14237
+ if (!firstKey) {
14238
+ break;
14239
+ }
14240
+ estimatedTextAdvanceWidthByFontAndValue.delete(firstKey);
14241
+ }
14242
+ return estimatedWidthPx;
14164
14243
  }
14165
14244
  function updateEstimatedLineWidthPxForText(currentLineWidthPx, text, style) {
14166
14245
  if (!text) {
@@ -14466,7 +14545,8 @@ function paragraphHasLastRenderedPageBreak(paragraph) {
14466
14545
  if (cached) {
14467
14546
  return cached.lastRenderedPageBreak;
14468
14547
  }
14469
- return paragraphHasExplicitPageBreak2(paragraph) ? paragraphBreakFlagsBySourceXml.get(xml)?.lastRenderedPageBreak ?? false : false;
14548
+ paragraphHasExplicitPageBreak2(paragraph);
14549
+ return paragraphBreakFlagsBySourceXml.get(xml)?.lastRenderedPageBreak ?? false;
14470
14550
  }
14471
14551
  function paragraphStartsWithLastRenderedPageBreak(paragraph) {
14472
14552
  const xml = paragraph.sourceXml ?? "";
@@ -14640,7 +14720,8 @@ function paragraphHasPageBreakBefore2(paragraph) {
14640
14720
  if (cached) {
14641
14721
  return cached.pageBreakBefore;
14642
14722
  }
14643
- return paragraphHasExplicitPageBreak2(paragraph) ? paragraphBreakFlagsBySourceXml.get(xml)?.pageBreakBefore ?? false : false;
14723
+ paragraphHasExplicitPageBreak2(paragraph);
14724
+ return paragraphBreakFlagsBySourceXml.get(xml)?.pageBreakBefore ?? false;
14644
14725
  }
14645
14726
  function sectionBreakAfterParagraphStartsNewPage(paragraph) {
14646
14727
  const xml = paragraph.sourceXml ?? "";
@@ -14820,9 +14901,15 @@ function paragraphDominantFontSizePt(paragraph) {
14820
14901
  return dominantFontSizePt;
14821
14902
  }
14822
14903
  function paragraphBaseFontSizePx(paragraph) {
14904
+ const cached = paragraphBaseFontSizePxByParagraph.get(paragraph);
14905
+ if (cached !== void 0) {
14906
+ return cached;
14907
+ }
14823
14908
  const dominantRunFontSizePt = paragraphDominantFontSizePt(paragraph);
14824
14909
  const fontSizePt = dominantRunFontSizePt && dominantRunFontSizePt > 0 ? dominantRunFontSizePt : Number.isFinite(paragraph.style?.headingLevel) ? DEFAULT_PARAGRAPH_FONT_SIZE_PT + Math.max(0, 6 - (paragraph.style?.headingLevel ?? 6)) : DEFAULT_PARAGRAPH_FONT_SIZE_PT;
14825
- return Math.max(10, Math.round(fontSizePt * 96 / 72));
14910
+ const baseFontSizePx = Math.max(10, Math.round(fontSizePt * 96 / 72));
14911
+ paragraphBaseFontSizePxByParagraph.set(paragraph, baseFontSizePx);
14912
+ return baseFontSizePx;
14826
14913
  }
14827
14914
  function paragraphMaxFontSizePx(paragraph) {
14828
14915
  const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
@@ -14847,6 +14934,10 @@ function normalizeFontFamilyToken(fontFamily) {
14847
14934
  return normalized || void 0;
14848
14935
  }
14849
14936
  function paragraphDominantFontFamily(paragraph) {
14937
+ const cached = paragraphDominantFontFamilyByParagraph.get(paragraph);
14938
+ if (cached !== void 0) {
14939
+ return cached ?? void 0;
14940
+ }
14850
14941
  const weightByFamily = /* @__PURE__ */ new Map();
14851
14942
  const addWeight = (fontFamily, weight) => {
14852
14943
  const normalizedFamily = normalizeFontFamilyToken(fontFamily);
@@ -14867,6 +14958,7 @@ function paragraphDominantFontFamily(paragraph) {
14867
14958
  addWeight(child.style?.fontFamily, text.length);
14868
14959
  });
14869
14960
  if (weightByFamily.size === 0) {
14961
+ paragraphDominantFontFamilyByParagraph.set(paragraph, null);
14870
14962
  return void 0;
14871
14963
  }
14872
14964
  let dominantFamily;
@@ -14877,6 +14969,7 @@ function paragraphDominantFontFamily(paragraph) {
14877
14969
  dominantWeight = weight;
14878
14970
  }
14879
14971
  }
14972
+ paragraphDominantFontFamilyByParagraph.set(paragraph, dominantFamily ?? null);
14880
14973
  return dominantFamily;
14881
14974
  }
14882
14975
  function singleLineAutoScaleForFontFamily(fontFamily) {
@@ -15966,6 +16059,11 @@ function rowHasDeepFlowContent(row) {
15966
16059
  }
15967
16060
  return nestedTableCount > 0 || blockNodeCount >= SPLITTABLE_TABLE_ROW_DEEP_CONTENT_NODE_THRESHOLD;
15968
16061
  }
16062
+ function rowHasNestedTableContent(row) {
16063
+ return row.cells.some(
16064
+ (cell) => cell.nodes.some((contentNode) => contentNode.type === "table")
16065
+ );
16066
+ }
15969
16067
  function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitHeightPx, pageContentHeightPx) {
15970
16068
  if (!rowAllowsPageSplit(row)) {
15971
16069
  return estimatedRowHeightPx;
@@ -16099,6 +16197,280 @@ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefiniti
16099
16197
  return Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, rowHeightPx);
16100
16198
  });
16101
16199
  }
16200
+ function uniqueSortedPixelBoundaries(values) {
16201
+ const sorted = values.filter((value) => Number.isFinite(value)).map((value) => Math.max(0, Math.round(value))).sort((left, right) => left - right);
16202
+ const unique = [];
16203
+ for (const value of sorted) {
16204
+ const previous = unique[unique.length - 1];
16205
+ if (previous === void 0 || Math.abs(previous - value) > TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX) {
16206
+ unique.push(value);
16207
+ }
16208
+ }
16209
+ return unique;
16210
+ }
16211
+ function estimateParagraphBoundaryOffsetsPx(paragraph, availableWidthPx, numberingDefinitions, applyWordTableDefaults, docGridLinePitchPx, paragraphIndex) {
16212
+ const paragraphForLayout = wordLikeTableCellParagraph(
16213
+ paragraph,
16214
+ applyWordTableDefaults
16215
+ );
16216
+ const disableDocGridSnap = paragraphDocGridSnapState(paragraph) === "disable";
16217
+ const paragraphHeightPx = estimateParagraphHeightPx(
16218
+ paragraphForLayout,
16219
+ availableWidthPx,
16220
+ numberingDefinitions,
16221
+ docGridLinePitchPx,
16222
+ disableDocGridSnap
16223
+ );
16224
+ const suppressTopSpacing = paragraphIndex === 0 && suppressFirstTableCellParagraphTopSpacing(paragraph);
16225
+ const beforeSpacingPx = suppressTopSpacing ? 0 : twipsToPixels(paragraphForLayout.style?.spacing?.beforeTwips) ?? 0;
16226
+ const afterSpacingPx = twipsToPixels(paragraphForLayout.style?.spacing?.afterTwips) ?? 0;
16227
+ const topBorderInsetPx = paragraphBorderInsetPx(
16228
+ paragraphForLayout.style?.borders?.top
16229
+ );
16230
+ const bottomBorderInsetPx = paragraphBorderInsetPx(
16231
+ paragraphForLayout.style?.borders?.bottom
16232
+ );
16233
+ const lineHeightPx = Math.max(
16234
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
16235
+ estimateParagraphLineHeightPx(
16236
+ paragraphForLayout,
16237
+ docGridLinePitchPx,
16238
+ disableDocGridSnap
16239
+ )
16240
+ );
16241
+ const pretextSource = buildParagraphPretextLayoutSource(paragraphForLayout, {
16242
+ allowExplicitLineBreakText: true,
16243
+ expandTabsForLayout: true
16244
+ });
16245
+ const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
16246
+ paragraphForLayout,
16247
+ availableWidthPx,
16248
+ numberingDefinitions
16249
+ );
16250
+ const pretextLayout = pretextSource ? layoutParagraphPretextSource(
16251
+ paragraphForLayout,
16252
+ pretextSource,
16253
+ paragraphTextWidthPx,
16254
+ lineHeightPx,
16255
+ []
16256
+ ) : void 0;
16257
+ const lineTopOffsetsPx = pretextLayout ? pretextLayout.lines.map((line) => Math.max(0, Math.round(line.y))) : Array.from(
16258
+ {
16259
+ length: Math.max(
16260
+ 1,
16261
+ paragraphLineCountWithinWidth(
16262
+ paragraphForLayout,
16263
+ availableWidthPx,
16264
+ numberingDefinitions
16265
+ )
16266
+ )
16267
+ },
16268
+ (_, lineIndex) => lineIndex * lineHeightPx
16269
+ );
16270
+ const textTopPx = beforeSpacingPx + topBorderInsetPx;
16271
+ const textHeightPx = pretextLayout ? wrappedPretextParagraphBlockHeightPx(pretextLayout) : lineTopOffsetsPx.length * lineHeightPx;
16272
+ const visualHeightPx = Math.max(
16273
+ 1,
16274
+ beforeSpacingPx + topBorderInsetPx + textHeightPx + bottomBorderInsetPx + afterSpacingPx
16275
+ );
16276
+ const heightPx = Math.max(1, paragraphHeightPx, visualHeightPx);
16277
+ const lineBoundariesPx = lineTopOffsetsPx.map(
16278
+ (lineTopPx) => textTopPx + lineTopPx + lineHeightPx
16279
+ );
16280
+ return {
16281
+ heightPx,
16282
+ safeBoundariesPx: uniqueSortedPixelBoundaries([
16283
+ ...lineBoundariesPx,
16284
+ heightPx
16285
+ ])
16286
+ };
16287
+ }
16288
+ function estimateNestedTableBoundaryOffsetsPx(table, availableWidthPx, numberingDefinitions, docGridLinePitchPx) {
16289
+ const rowHeightsPx = estimateTableRowHeightsPx(
16290
+ table,
16291
+ availableWidthPx,
16292
+ numberingDefinitions,
16293
+ docGridLinePitchPx
16294
+ );
16295
+ const boundariesPx = [];
16296
+ let cursorPx = 0;
16297
+ for (const rowHeightPx of rowHeightsPx) {
16298
+ cursorPx += Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, rowHeightPx);
16299
+ boundariesPx.push(cursorPx);
16300
+ }
16301
+ return {
16302
+ heightPx: Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, cursorPx),
16303
+ safeBoundariesPx: uniqueSortedPixelBoundaries(boundariesPx)
16304
+ };
16305
+ }
16306
+ function estimateTableCellSliceBoundaryLayoutPx(params) {
16307
+ const {
16308
+ cell,
16309
+ rowHeightPx,
16310
+ contentWidthPx,
16311
+ tableCellMarginTwips,
16312
+ numberingDefinitions,
16313
+ applyWordTableDefaults,
16314
+ docGridLinePitchPx
16315
+ } = params;
16316
+ const paddingPx = resolveTableSpacingPaddingPx(
16317
+ mergeTableSpacing(tableCellMarginTwips, cell.style?.marginTwips)
16318
+ );
16319
+ const localBoundariesPx = [0, paddingPx.top];
16320
+ let contentCursorPx = paddingPx.top;
16321
+ let paragraphIndex = 0;
16322
+ for (const contentNode of cell.nodes) {
16323
+ const layout = contentNode.type === "paragraph" ? estimateParagraphBoundaryOffsetsPx(
16324
+ contentNode,
16325
+ contentWidthPx,
16326
+ numberingDefinitions,
16327
+ applyWordTableDefaults,
16328
+ docGridLinePitchPx,
16329
+ paragraphIndex++
16330
+ ) : estimateNestedTableBoundaryOffsetsPx(
16331
+ contentNode,
16332
+ contentWidthPx,
16333
+ numberingDefinitions,
16334
+ docGridLinePitchPx
16335
+ );
16336
+ localBoundariesPx.push(
16337
+ ...layout.safeBoundariesPx.map(
16338
+ (boundaryPx) => contentCursorPx + boundaryPx
16339
+ )
16340
+ );
16341
+ contentCursorPx += layout.heightPx;
16342
+ }
16343
+ const contentBottomPx = contentCursorPx + paddingPx.bottom;
16344
+ const contentFlowHeightPx = Math.max(0, contentCursorPx - paddingPx.top);
16345
+ const availableContentHeightPx = Math.max(
16346
+ 0,
16347
+ rowHeightPx - paddingPx.top - paddingPx.bottom
16348
+ );
16349
+ const extraVerticalSpacePx = Math.max(
16350
+ 0,
16351
+ availableContentHeightPx - contentFlowHeightPx
16352
+ );
16353
+ const verticalOffsetPx = cell.style?.verticalAlign === "center" ? Math.round(extraVerticalSpacePx / 2) : cell.style?.verticalAlign === "bottom" ? extraVerticalSpacePx : 0;
16354
+ return {
16355
+ safeBoundariesPx: uniqueSortedPixelBoundaries(
16356
+ localBoundariesPx.map(
16357
+ (boundaryPx) => Math.min(rowHeightPx, boundaryPx + verticalOffsetPx)
16358
+ )
16359
+ ),
16360
+ contentBottomPx: Math.min(rowHeightPx, contentBottomPx + verticalOffsetPx)
16361
+ };
16362
+ }
16363
+ function tableCellSliceBoundaryIsSafe(layout, boundaryPx) {
16364
+ if (boundaryPx <= TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX) {
16365
+ return true;
16366
+ }
16367
+ if (boundaryPx >= layout.contentBottomPx - TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX) {
16368
+ return true;
16369
+ }
16370
+ return layout.safeBoundariesPx.some(
16371
+ (safeBoundaryPx) => Math.abs(safeBoundaryPx - boundaryPx) <= TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX
16372
+ );
16373
+ }
16374
+ function resolveTableRowSliceHeightOnSafeBoundaryPx(params) {
16375
+ const {
16376
+ table,
16377
+ rowIndex,
16378
+ rowHeightPx,
16379
+ rowSliceOffsetPx,
16380
+ preferredSliceHeightPx,
16381
+ maxAvailableWidthPx,
16382
+ numberingDefinitions,
16383
+ docGridLinePitchPx
16384
+ } = params;
16385
+ const row = table.rows[rowIndex];
16386
+ if (!row || !rowHasNestedTableContent(row)) {
16387
+ return preferredSliceHeightPx;
16388
+ }
16389
+ const sliceStartPx = Math.max(0, Math.round(rowSliceOffsetPx));
16390
+ const preferredSliceEndPx = Math.min(
16391
+ rowHeightPx,
16392
+ sliceStartPx + Math.max(0, Math.round(preferredSliceHeightPx))
16393
+ );
16394
+ if (preferredSliceEndPx >= rowHeightPx - TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX) {
16395
+ return Math.max(0, rowHeightPx - sliceStartPx);
16396
+ }
16397
+ const columnCount = tableColumnCount(table);
16398
+ const tableWidthPx = twipsToPixels(table.style?.widthTwips);
16399
+ const rawTableColumnWidthsPx = (() => {
16400
+ const definedWidthsTwips = columnWidthsFromTableDefinition(
16401
+ table,
16402
+ columnCount
16403
+ );
16404
+ if (!definedWidthsTwips || definedWidthsTwips.length === 0) {
16405
+ return defaultColumnWidthsPx(columnCount, tableWidthPx);
16406
+ }
16407
+ const widthsPx = definedWidthsTwips.map(
16408
+ (widthTwips) => twipsToPixels(widthTwips) ?? 0
16409
+ );
16410
+ return normalizeColumnWidthsPx(widthsPx, columnCount, tableWidthPx, 1);
16411
+ })();
16412
+ const rawResolvedTableWidthPx = tableWidthPx ?? rawTableColumnWidthsPx.reduce((sum, widthPx) => sum + widthPx, 0);
16413
+ const collapsedHorizontalBorderBleedPx = resolveCollapsedTableHorizontalOuterBleedPx(table, columnCount);
16414
+ const maxTableWidthPx = Number.isFinite(maxAvailableWidthPx) && maxAvailableWidthPx > 0 ? Math.max(
16415
+ 120,
16416
+ maxAvailableWidthPx - collapsedHorizontalBorderBleedPx
16417
+ ) : void 0;
16418
+ const resolvedTableWidthPx = clampTableWidthPx(
16419
+ rawResolvedTableWidthPx,
16420
+ maxTableWidthPx
16421
+ );
16422
+ const tableColumnWidthsPx = fitColumnWidthsToWidth(
16423
+ rawTableColumnWidthsPx,
16424
+ resolvedTableWidthPx
16425
+ );
16426
+ const applyWordTableDefaults = tableUsesWordLikeParagraphDefaults(table);
16427
+ const tableCellMarginTwips = table.style?.cellMarginTwips;
16428
+ const cellLayouts = [];
16429
+ const candidateBoundariesPx = [preferredSliceEndPx];
16430
+ let columnCursor = 0;
16431
+ for (const cell of row.cells) {
16432
+ const colSpanValue = cell.style?.gridSpan && cell.style.gridSpan > 1 ? cell.style.gridSpan : 1;
16433
+ const startColumnIndex = columnCursor;
16434
+ const endColumnIndex = Math.min(
16435
+ columnCount - 1,
16436
+ startColumnIndex + colSpanValue - 1
16437
+ );
16438
+ columnCursor += colSpanValue;
16439
+ const spannedWidthPx = tableColumnWidthsPx.slice(startColumnIndex, endColumnIndex + 1).reduce((sum, widthPx) => sum + widthPx, 0);
16440
+ const fallbackCellWidthPx = resolvedTableWidthPx / Math.max(1, columnCount) * colSpanValue;
16441
+ const cellRenderedWidthPx = twipsToPixels(cell.style?.widthTwips) ?? (spannedWidthPx > 0 ? spannedWidthPx : fallbackCellWidthPx);
16442
+ const cellPaddingPx = resolveTableSpacingPaddingPx(
16443
+ mergeTableSpacing(tableCellMarginTwips, cell.style?.marginTwips)
16444
+ );
16445
+ const cellContentWidthPx = Math.max(
16446
+ 1,
16447
+ cellRenderedWidthPx - cellPaddingPx.left - cellPaddingPx.right
16448
+ );
16449
+ const cellLayout = estimateTableCellSliceBoundaryLayoutPx({
16450
+ cell,
16451
+ rowHeightPx,
16452
+ contentWidthPx: cellContentWidthPx,
16453
+ tableCellMarginTwips,
16454
+ numberingDefinitions,
16455
+ applyWordTableDefaults,
16456
+ docGridLinePitchPx
16457
+ });
16458
+ cellLayouts.push(cellLayout);
16459
+ candidateBoundariesPx.push(...cellLayout.safeBoundariesPx);
16460
+ }
16461
+ const minimumSliceEndPx = sliceStartPx + Math.max(1, MIN_TABLE_ROW_SLICE_REMAINING_HEIGHT_PX);
16462
+ const candidatesPx = uniqueSortedPixelBoundaries(candidateBoundariesPx).filter(
16463
+ (boundaryPx) => boundaryPx >= minimumSliceEndPx && boundaryPx <= preferredSliceEndPx + TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX
16464
+ ).sort((left, right) => right - left);
16465
+ for (const candidatePx of candidatesPx) {
16466
+ if (cellLayouts.every(
16467
+ (layout) => tableCellSliceBoundaryIsSafe(layout, candidatePx)
16468
+ )) {
16469
+ return Math.max(0, candidatePx - sliceStartPx);
16470
+ }
16471
+ }
16472
+ return void 0;
16473
+ }
16102
16474
  function estimateTableHeightPx(table, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx) {
16103
16475
  const sourceXml = table.sourceXml;
16104
16476
  const widthKey = heightEstimateCacheKeyPx(
@@ -16387,6 +16759,234 @@ function estimateRenderedPageSegmentHeightPx(node, segment, model, availableWidt
16387
16759
  )
16388
16760
  );
16389
16761
  }
16762
+ function resolveParagraphColumnRenderLineRange(paragraph, segment, availableWidthPx, numberingDefinitions, docGridLinePitchPx) {
16763
+ const lineHeightPx = Math.max(
16764
+ 1,
16765
+ segment.paragraphLineRange?.lineHeightPx ?? estimateParagraphLineHeightPx(paragraph, docGridLinePitchPx)
16766
+ );
16767
+ if (segment.paragraphLineRange) {
16768
+ return {
16769
+ ...segment.paragraphLineRange,
16770
+ lineHeightPx
16771
+ };
16772
+ }
16773
+ const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
16774
+ paragraph,
16775
+ availableWidthPx,
16776
+ numberingDefinitions
16777
+ );
16778
+ const pretextSource = buildParagraphPretextLayoutSource(paragraph, {
16779
+ allowExplicitLineBreakText: true,
16780
+ expandTabsForLayout: true
16781
+ });
16782
+ const pretextLayout = pretextSource ? layoutParagraphPretextSource(
16783
+ paragraph,
16784
+ pretextSource,
16785
+ paragraphTextWidthPx,
16786
+ lineHeightPx,
16787
+ []
16788
+ ) : void 0;
16789
+ const totalLineCount = pretextLayout && pretextLayout.lineCount > 0 ? pretextLayout.lineCount : paragraphLineCountWithinWidth(
16790
+ paragraph,
16791
+ availableWidthPx,
16792
+ numberingDefinitions
16793
+ );
16794
+ return {
16795
+ startLineIndex: 0,
16796
+ endLineIndex: Math.max(1, totalLineCount),
16797
+ totalLineCount: Math.max(1, totalLineCount),
16798
+ lineHeightPx
16799
+ };
16800
+ }
16801
+ function splitParagraphSegmentForColumnRender(params) {
16802
+ const {
16803
+ paragraph,
16804
+ segment,
16805
+ model,
16806
+ availableWidthPx,
16807
+ availableHeightPx,
16808
+ numberingDefinitions,
16809
+ docGridLinePitchPx
16810
+ } = params;
16811
+ if (segment.tableRowRange || segment.tableRowSlice || paragraphHasExplicitColumnBreak(paragraph)) {
16812
+ return void 0;
16813
+ }
16814
+ const fullLineRange = resolveParagraphColumnRenderLineRange(
16815
+ paragraph,
16816
+ segment,
16817
+ availableWidthPx,
16818
+ numberingDefinitions,
16819
+ docGridLinePitchPx
16820
+ );
16821
+ const startLineIndex = Math.max(0, fullLineRange.startLineIndex);
16822
+ const endLineIndex = Math.max(startLineIndex, fullLineRange.endLineIndex);
16823
+ if (endLineIndex - startLineIndex < 2 || !paragraphCanSplitAcrossPages(paragraph, fullLineRange.totalLineCount)) {
16824
+ return void 0;
16825
+ }
16826
+ const safeAvailableHeightPx = Math.max(0, Math.round(availableHeightPx));
16827
+ let bestSegment;
16828
+ let bestHeightPx = 0;
16829
+ for (let candidateEndLineIndex = startLineIndex + 1; candidateEndLineIndex < endLineIndex; candidateEndLineIndex += 1) {
16830
+ const candidateSegment = {
16831
+ ...segment,
16832
+ paragraphLineRange: {
16833
+ startLineIndex,
16834
+ endLineIndex: candidateEndLineIndex,
16835
+ totalLineCount: fullLineRange.totalLineCount,
16836
+ lineHeightPx: fullLineRange.lineHeightPx
16837
+ }
16838
+ };
16839
+ const candidateHeightPx = estimateRenderedPageSegmentHeightPx(
16840
+ paragraph,
16841
+ candidateSegment,
16842
+ model,
16843
+ availableWidthPx,
16844
+ numberingDefinitions,
16845
+ docGridLinePitchPx
16846
+ );
16847
+ if (candidateHeightPx > safeAvailableHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
16848
+ break;
16849
+ }
16850
+ bestSegment = candidateSegment;
16851
+ bestHeightPx = candidateHeightPx;
16852
+ }
16853
+ if (!bestSegment?.paragraphLineRange) {
16854
+ return void 0;
16855
+ }
16856
+ return {
16857
+ currentSegment: bestSegment,
16858
+ currentHeightPx: bestHeightPx,
16859
+ remainderSegment: {
16860
+ ...segment,
16861
+ paragraphLineRange: {
16862
+ startLineIndex: bestSegment.paragraphLineRange.endLineIndex,
16863
+ endLineIndex,
16864
+ totalLineCount: fullLineRange.totalLineCount,
16865
+ lineHeightPx: fullLineRange.lineHeightPx
16866
+ }
16867
+ }
16868
+ };
16869
+ }
16870
+ function buildRenderColumnSegmentsForPageSection(model, flowSegments, columnWidthsPx, columnHeightPx, numberingDefinitions, docGridLinePitchPxByNodeIndex, measuredParagraphOuterHeightsPxByNodeIndex, balanceColumns = false) {
16871
+ const columnCount = Math.max(1, columnWidthsPx.length);
16872
+ const columns = Array.from(
16873
+ { length: columnCount },
16874
+ () => []
16875
+ );
16876
+ const maxColumnHeightPx = Math.max(120, Math.round(columnHeightPx));
16877
+ const resolveSegmentHeightPx = (segment, columnWidthPx) => {
16878
+ const segmentNode = model.nodes[segment.nodeIndex];
16879
+ if (!segmentNode) {
16880
+ return MIN_PARAGRAPH_LINE_HEIGHT_PX;
16881
+ }
16882
+ const docGridLinePitchPx = docGridLinePitchPxByNodeIndex?.get(
16883
+ segment.nodeIndex
16884
+ );
16885
+ const measuredSegmentHeightPx = segmentNode.type === "paragraph" && !segment.paragraphLineRange && !segment.tableRowRange && !segment.tableRowSlice ? measuredParagraphOuterHeightsPxByNodeIndex?.get(segment.nodeIndex) : void 0;
16886
+ return Number.isFinite(measuredSegmentHeightPx) && measuredSegmentHeightPx > 0 ? Math.max(1, Math.round(measuredSegmentHeightPx)) : estimateRenderedPageSegmentHeightPx(
16887
+ segmentNode,
16888
+ segment,
16889
+ model,
16890
+ columnWidthPx,
16891
+ numberingDefinitions,
16892
+ docGridLinePitchPx
16893
+ );
16894
+ };
16895
+ const safeColumnHeightPx = balanceColumns && columnCount > 1 ? Math.min(
16896
+ maxColumnHeightPx,
16897
+ Math.max(
16898
+ MIN_PARAGRAPH_LINE_HEIGHT_PX * 4,
16899
+ Math.ceil(
16900
+ flowSegments.reduce((totalHeightPx, segment) => {
16901
+ const columnWidthPx = Math.max(
16902
+ 120,
16903
+ Math.round(columnWidthsPx[0] ?? 120)
16904
+ );
16905
+ return totalHeightPx + resolveSegmentHeightPx(segment, columnWidthPx);
16906
+ }, 0) / columnCount
16907
+ ) + PAGE_OVERFLOW_TOLERANCE_PX
16908
+ )
16909
+ ) : maxColumnHeightPx;
16910
+ let columnIndex = 0;
16911
+ let consumedHeightPx = 0;
16912
+ const moveToNextColumn = () => {
16913
+ if (columnIndex + 1 >= columnCount) {
16914
+ return false;
16915
+ }
16916
+ columnIndex += 1;
16917
+ consumedHeightPx = 0;
16918
+ return true;
16919
+ };
16920
+ const pushSegment = (segment, heightPx) => {
16921
+ columns[columnIndex]?.push(segment);
16922
+ consumedHeightPx += Math.max(1, Math.round(heightPx));
16923
+ };
16924
+ for (const flowSegment of flowSegments) {
16925
+ let pendingSegment = flowSegment;
16926
+ let splitGuard = 0;
16927
+ while (pendingSegment && splitGuard < 256) {
16928
+ splitGuard += 1;
16929
+ const currentSegment = pendingSegment;
16930
+ const segmentNode = model.nodes[currentSegment.nodeIndex];
16931
+ if (!segmentNode) {
16932
+ columns[columnIndex]?.push(currentSegment);
16933
+ break;
16934
+ }
16935
+ const columnWidthPx = Math.max(
16936
+ 120,
16937
+ Math.round(columnWidthsPx[columnIndex] ?? columnWidthsPx[0] ?? 120)
16938
+ );
16939
+ const docGridLinePitchPx = docGridLinePitchPxByNodeIndex?.get(
16940
+ currentSegment.nodeIndex
16941
+ );
16942
+ const segmentHeightPx = resolveSegmentHeightPx(
16943
+ currentSegment,
16944
+ columnWidthPx
16945
+ );
16946
+ const remainingHeightPx = Math.max(
16947
+ 0,
16948
+ safeColumnHeightPx - consumedHeightPx
16949
+ );
16950
+ if (segmentHeightPx <= remainingHeightPx + PAGE_OVERFLOW_TOLERANCE_PX || columnIndex + 1 >= columnCount) {
16951
+ pushSegment(currentSegment, segmentHeightPx);
16952
+ pendingSegment = void 0;
16953
+ break;
16954
+ }
16955
+ const splitSegment = segmentNode.type === "paragraph" ? splitParagraphSegmentForColumnRender({
16956
+ paragraph: segmentNode,
16957
+ segment: currentSegment,
16958
+ model,
16959
+ availableWidthPx: columnWidthPx,
16960
+ availableHeightPx: remainingHeightPx,
16961
+ numberingDefinitions,
16962
+ docGridLinePitchPx
16963
+ }) : void 0;
16964
+ if (splitSegment) {
16965
+ pushSegment(splitSegment.currentSegment, splitSegment.currentHeightPx);
16966
+ pendingSegment = splitSegment.remainderSegment;
16967
+ if (!moveToNextColumn()) {
16968
+ const remainderSegment = splitSegment.remainderSegment;
16969
+ const remainderHeightPx = estimateRenderedPageSegmentHeightPx(
16970
+ segmentNode,
16971
+ remainderSegment,
16972
+ model,
16973
+ columnWidthPx,
16974
+ numberingDefinitions,
16975
+ docGridLinePitchPx
16976
+ );
16977
+ pushSegment(remainderSegment, remainderHeightPx);
16978
+ pendingSegment = void 0;
16979
+ }
16980
+ continue;
16981
+ }
16982
+ if (!moveToNextColumn()) {
16983
+ pushSegment(currentSegment, segmentHeightPx);
16984
+ pendingSegment = void 0;
16985
+ }
16986
+ }
16987
+ }
16988
+ return columns;
16989
+ }
16390
16990
  function sumEstimatedTableRowHeightsPx(rowHeightsPx, startRowIndex, endRowIndex) {
16391
16991
  let total = 0;
16392
16992
  const clampedStart = Math.max(0, startRowIndex);
@@ -16860,16 +17460,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16860
17460
  const exactSegmentEndLineIndex = resolveMaxPretextLineRangeEndIndexThatFits(
16861
17461
  pretextLayoutForSegmentSplitting,
16862
17462
  lineCursor,
16863
- Math.min(
16864
- resolvedParagraphLineCount,
16865
- lineCursor + linesThatFit
16866
- ),
17463
+ Math.min(resolvedParagraphLineCount, lineCursor + linesThatFit),
16867
17464
  availableForLinesPx
16868
17465
  );
16869
- linesThatFit = Math.max(
16870
- 0,
16871
- exactSegmentEndLineIndex - lineCursor
16872
- );
17466
+ linesThatFit = Math.max(0, exactSegmentEndLineIndex - lineCursor);
16873
17467
  }
16874
17468
  if (linesThatFit < minLinesPerSegment) {
16875
17469
  if (currentPageSegments.length > 0) {
@@ -16906,10 +17500,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16906
17500
  lineCursor,
16907
17501
  segmentEndLineIndex
16908
17502
  );
16909
- if (topSpacingPx + resolveSegmentContentHeightPx(
16910
- lineCursor,
16911
- segmentEndLineIndex
16912
- ) + segmentReservePx <= remainingHeightPx2) {
17503
+ if (topSpacingPx + resolveSegmentContentHeightPx(lineCursor, segmentEndLineIndex) + segmentReservePx <= remainingHeightPx2) {
16913
17504
  break;
16914
17505
  }
16915
17506
  linesThatFit -= 1;
@@ -17110,6 +17701,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
17110
17701
  let rowStartIndex = 0;
17111
17702
  let rowSliceOffsetPx = 0;
17112
17703
  let repeatedHeaderHeightPxOnThisPage = 0;
17704
+ let tableBreakStartRowCursor = 0;
17113
17705
  while (rowStartIndex < estimatedRowHeightsPx.length) {
17114
17706
  if (currentPageSegments.length === 0) {
17115
17707
  repeatedHeaderHeightPxOnThisPage = 0;
@@ -17144,9 +17736,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
17144
17736
  currentPageContentHeightPx - repeatedHeaderHeightPxOnThisPage
17145
17737
  );
17146
17738
  const rowExceedsFreshPageHeightPx = currentRowTotalHeightPx > freshPageAvailableHeightPx + PAGE_OVERFLOW_TOLERANCE_PX;
17739
+ const hasUsableCurrentPageSliceSpace = pageConsumedHeightPx > 0 && remainingHeightPx >= MIN_TABLE_ROW_SLICE_REMAINING_HEIGHT_PX;
17147
17740
  const canSplitCurrentRow = rowSliceOffsetPx > 0 || rowAllowsPageSplit(currentRow) || rowExceedsFreshPageHeightPx;
17148
17741
  const shouldContinueExistingRowSlice = rowSliceOffsetPx > 0;
17149
- const rowNeedsSliceOnThisPage = ENABLE_TABLE_ROW_SLICING && canSplitCurrentRow && currentRowRemainingHeightPx > remainingHeightPx + PAGE_OVERFLOW_TOLERANCE_PX && (shouldContinueExistingRowSlice || rowExceedsFreshPageHeightPx);
17742
+ const rowNeedsSliceOnThisPage = ENABLE_TABLE_ROW_SLICING && canSplitCurrentRow && currentRowRemainingHeightPx > remainingHeightPx + PAGE_OVERFLOW_TOLERANCE_PX && (shouldContinueExistingRowSlice || rowExceedsFreshPageHeightPx || hasUsableCurrentPageSliceSpace);
17150
17743
  if (canSplitCurrentRow && currentRowRemainingHeightPx > remainingHeightPx + PAGE_OVERFLOW_TOLERANCE_PX && !rowNeedsSliceOnThisPage && currentPageSegments.length > 0) {
17151
17744
  startNextPage();
17152
17745
  pageConsumedHeightPx = 0;
@@ -17174,10 +17767,38 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
17174
17767
  MIN_PARAGRAPH_LINE_HEIGHT_PX,
17175
17768
  Math.round(remainingHeightPx)
17176
17769
  );
17177
- const sliceHeightPx = Math.max(
17770
+ const preferredSliceHeightPx = Math.max(
17178
17771
  MIN_PARAGRAPH_LINE_HEIGHT_PX,
17179
17772
  Math.min(currentRowRemainingHeightPx, availableSliceHeightPx)
17180
17773
  );
17774
+ const safeSliceHeightPx = resolveTableRowSliceHeightOnSafeBoundaryPx({
17775
+ table: node,
17776
+ rowIndex: rowStartIndex,
17777
+ rowHeightPx: currentRowTotalHeightPx,
17778
+ rowSliceOffsetPx,
17779
+ preferredSliceHeightPx,
17780
+ maxAvailableWidthPx: nodeMetrics.pageContentWidthPx,
17781
+ numberingDefinitions,
17782
+ docGridLinePitchPx: nodeMetrics.docGridLinePitchPx
17783
+ });
17784
+ if (safeSliceHeightPx === void 0 && pageConsumedHeightPx > 0 && currentPageSegments.length > 0) {
17785
+ startNextPage();
17786
+ pageConsumedHeightPx = 0;
17787
+ previousParagraphAfterPx = 0;
17788
+ currentSectionPageFlowOriginPx = 0;
17789
+ currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
17790
+ currentPageIndex,
17791
+ nodeMetrics
17792
+ );
17793
+ continue;
17794
+ }
17795
+ const sliceHeightPx = Math.max(
17796
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
17797
+ Math.min(
17798
+ currentRowRemainingHeightPx,
17799
+ safeSliceHeightPx ?? preferredSliceHeightPx
17800
+ )
17801
+ );
17181
17802
  currentPageSegments.push({
17182
17803
  nodeIndex,
17183
17804
  tableRowRange: {
@@ -17243,9 +17864,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
17243
17864
  pageConsumedHeightPx <= 0
17244
17865
  );
17245
17866
  let rowEndIndex = fittedRowEndIndex;
17246
- const forcedBreakRowIndex = tableBreakStartRows.find(
17247
- (breakRowIndex) => breakRowIndex > rowStartIndex
17248
- );
17867
+ while (tableBreakStartRowCursor < tableBreakStartRows.length && tableBreakStartRows[tableBreakStartRowCursor] <= rowStartIndex) {
17868
+ tableBreakStartRowCursor += 1;
17869
+ }
17870
+ const forcedBreakRowIndex = tableBreakStartRows[tableBreakStartRowCursor];
17249
17871
  if (forcedBreakRowIndex !== void 0) {
17250
17872
  rowEndIndex = Math.min(rowEndIndex, forcedBreakRowIndex);
17251
17873
  }
@@ -17311,6 +17933,19 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
17311
17933
  rowStartIndex = rowEndIndex;
17312
17934
  rowSliceOffsetPx = 0;
17313
17935
  if (rowStartIndex < estimatedRowHeightsPx.length) {
17936
+ const nextRow = node.rows[rowStartIndex];
17937
+ const nextRowHeightPx = Math.max(
17938
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
17939
+ estimatedRowHeightsPx[rowStartIndex] ?? MIN_PARAGRAPH_LINE_HEIGHT_PX
17940
+ );
17941
+ const remainingHeightAfterSegmentPx = Math.max(
17942
+ 0,
17943
+ currentPageContentHeightPx - pageConsumedHeightPx
17944
+ );
17945
+ const canSliceNextRowOnCurrentPage = ENABLE_TABLE_ROW_SLICING && nextRow !== void 0 && rowAllowsPageSplit(nextRow) && !tableBreakStartRows.includes(rowStartIndex) && remainingHeightAfterSegmentPx >= MIN_TABLE_ROW_SLICE_REMAINING_HEIGHT_PX && nextRowHeightPx > remainingHeightAfterSegmentPx + PAGE_OVERFLOW_TOLERANCE_PX;
17946
+ if (canSliceNextRowOnCurrentPage) {
17947
+ continue;
17948
+ }
17314
17949
  startNextPage();
17315
17950
  pageConsumedHeightPx = 0;
17316
17951
  previousParagraphAfterPx = 0;
@@ -24363,7 +24998,7 @@ function useDocxEditor(options = {}) {
24363
24998
  const [status, setStatus] = React.useState(
24364
24999
  options.initialStatus ?? "Ready"
24365
25000
  );
24366
- const isImporting = false;
25001
+ const [isImporting, setIsImporting] = React.useState(false);
24367
25002
  const [documentTheme, setDocumentThemeState] = React.useState(options.initialDocumentTheme ?? "light");
24368
25003
  const [showTrackedChanges, setShowTrackedChangesState] = React.useState(options.initialShowTrackedChanges ?? false);
24369
25004
  const [paginationInfo, setPaginationInfo] = React.useState({
@@ -24886,6 +25521,8 @@ function useDocxEditor(options = {}) {
24886
25521
  setStatus("Only .docx files are supported");
24887
25522
  return;
24888
25523
  }
25524
+ setIsImporting(true);
25525
+ setStatus(`Loading ${file.name}...`);
24889
25526
  try {
24890
25527
  const buffer = await file.arrayBuffer();
24891
25528
  const pkg = await parseDocx(buffer);
@@ -24906,6 +25543,8 @@ function useDocxEditor(options = {}) {
24906
25543
  setStatus(
24907
25544
  `Failed to load file: ${error instanceof Error ? error.message : "Unknown error"}`
24908
25545
  );
25546
+ } finally {
25547
+ setIsImporting(false);
24909
25548
  }
24910
25549
  },
24911
25550
  [loadEmbeddedFontsFromPackage]
@@ -29395,7 +30034,7 @@ function DocxEditorViewer({
29395
30034
  style,
29396
30035
  pageBackgroundColor,
29397
30036
  pageGapBackgroundColor,
29398
- deferInitialPaginationPaint = true,
30037
+ deferInitialPaginationPaint = false,
29399
30038
  loadingState,
29400
30039
  pageVirtualization,
29401
30040
  visiblePageRange,
@@ -29456,6 +30095,10 @@ function DocxEditorViewer({
29456
30095
  const paragraphElementsRef = React.useRef(
29457
30096
  /* @__PURE__ */ new Map()
29458
30097
  );
30098
+ const [
30099
+ measuredParagraphOuterHeightsPxByNodeIndex,
30100
+ setMeasuredParagraphOuterHeightsPxByNodeIndex
30101
+ ] = React.useState(() => /* @__PURE__ */ new Map());
29459
30102
  const tableCellEditorElementsRef = React.useRef(
29460
30103
  /* @__PURE__ */ new Map()
29461
30104
  );
@@ -29730,6 +30373,9 @@ function DocxEditorViewer({
29730
30373
  const paginationMeasurementResumeTimeoutRef = React.useRef(
29731
30374
  null
29732
30375
  );
30376
+ React.useLayoutEffect(() => {
30377
+ setMeasuredParagraphOuterHeightsPxByNodeIndex(/* @__PURE__ */ new Map());
30378
+ }, [editor.documentLoadNonce, paragraphStructureEpoch]);
29733
30379
  const schedulePaginationMeasurementResume = React.useCallback(
29734
30380
  (delayMs) => {
29735
30381
  if (typeof window === "undefined") {
@@ -29942,10 +30588,20 @@ function DocxEditorViewer({
29942
30588
  () => buildPaginationSectionMetrics(documentSections, documentLayout),
29943
30589
  [documentLayout, documentSections]
29944
30590
  );
29945
- const docGridLinePitchPxByNodeIndex = React.useMemo(() => {
30591
+ const {
30592
+ docGridLinePitchPxByNodeIndex,
30593
+ pageContentWidthPxByNodeIndex,
30594
+ pageContentHeightPxByNodeIndex
30595
+ } = React.useMemo(() => {
29946
30596
  const pitchByNodeIndex = /* @__PURE__ */ new Map();
30597
+ const widthByNodeIndex = /* @__PURE__ */ new Map();
30598
+ const heightByNodeIndex = /* @__PURE__ */ new Map();
29947
30599
  if (editor.model.nodes.length === 0 || paginationSectionMetrics.length === 0) {
29948
- return pitchByNodeIndex;
30600
+ return {
30601
+ docGridLinePitchPxByNodeIndex: pitchByNodeIndex,
30602
+ pageContentWidthPxByNodeIndex: widthByNodeIndex,
30603
+ pageContentHeightPxByNodeIndex: heightByNodeIndex
30604
+ };
29949
30605
  }
29950
30606
  let currentMetricsIndex = 0;
29951
30607
  for (let nodeIndex = 0; nodeIndex < editor.model.nodes.length; nodeIndex += 1) {
@@ -29954,51 +30610,22 @@ function DocxEditorViewer({
29954
30610
  nodeIndex,
29955
30611
  currentMetricsIndex
29956
30612
  );
29957
- const docGridLinePitchPx = paginationSectionMetrics[currentMetricsIndex]?.docGridLinePitchPx;
30613
+ const nodeMetrics = paginationSectionMetrics[currentMetricsIndex];
30614
+ const docGridLinePitchPx = nodeMetrics?.docGridLinePitchPx;
29958
30615
  if (Number.isFinite(docGridLinePitchPx) && docGridLinePitchPx > 0) {
29959
30616
  pitchByNodeIndex.set(
29960
30617
  nodeIndex,
29961
30618
  Math.round(docGridLinePitchPx)
29962
30619
  );
29963
30620
  }
29964
- }
29965
- return pitchByNodeIndex;
29966
- }, [editor.model.nodes, paginationSectionMetrics]);
29967
- const pageContentWidthPxByNodeIndex = React.useMemo(() => {
29968
- const widthByNodeIndex = /* @__PURE__ */ new Map();
29969
- if (editor.model.nodes.length === 0 || paginationSectionMetrics.length === 0) {
29970
- return widthByNodeIndex;
29971
- }
29972
- let currentMetricsIndex = 0;
29973
- for (let nodeIndex = 0; nodeIndex < editor.model.nodes.length; nodeIndex += 1) {
29974
- currentMetricsIndex = resolvePaginationSectionMetricsIndexForNodeIndex(
29975
- paginationSectionMetrics,
29976
- nodeIndex,
29977
- currentMetricsIndex
29978
- );
29979
- const pageContentWidthPx = paginationSectionMetrics[currentMetricsIndex]?.pageContentWidthPx;
30621
+ const pageContentWidthPx = nodeMetrics?.pageContentWidthPx;
29980
30622
  if (Number.isFinite(pageContentWidthPx) && pageContentWidthPx > 0) {
29981
30623
  widthByNodeIndex.set(
29982
30624
  nodeIndex,
29983
30625
  Math.round(pageContentWidthPx)
29984
30626
  );
29985
30627
  }
29986
- }
29987
- return widthByNodeIndex;
29988
- }, [editor.model.nodes, paginationSectionMetrics]);
29989
- const pageContentHeightPxByNodeIndex = React.useMemo(() => {
29990
- const heightByNodeIndex = /* @__PURE__ */ new Map();
29991
- if (editor.model.nodes.length === 0 || paginationSectionMetrics.length === 0) {
29992
- return heightByNodeIndex;
29993
- }
29994
- let currentMetricsIndex = 0;
29995
- for (let nodeIndex = 0; nodeIndex < editor.model.nodes.length; nodeIndex += 1) {
29996
- currentMetricsIndex = resolvePaginationSectionMetricsIndexForNodeIndex(
29997
- paginationSectionMetrics,
29998
- nodeIndex,
29999
- currentMetricsIndex
30000
- );
30001
- const pageContentHeightPx = paginationSectionMetrics[currentMetricsIndex]?.pageContentHeightPx;
30628
+ const pageContentHeightPx = nodeMetrics?.pageContentHeightPx;
30002
30629
  if (Number.isFinite(pageContentHeightPx) && pageContentHeightPx > 0) {
30003
30630
  heightByNodeIndex.set(
30004
30631
  nodeIndex,
@@ -30006,7 +30633,11 @@ function DocxEditorViewer({
30006
30633
  );
30007
30634
  }
30008
30635
  }
30009
- return heightByNodeIndex;
30636
+ return {
30637
+ docGridLinePitchPxByNodeIndex: pitchByNodeIndex,
30638
+ pageContentWidthPxByNodeIndex: widthByNodeIndex,
30639
+ pageContentHeightPxByNodeIndex: heightByNodeIndex
30640
+ };
30010
30641
  }, [editor.model.nodes, paginationSectionMetrics]);
30011
30642
  const sectionColumnsBySectionIndex = React.useMemo(
30012
30643
  () => documentSections.map(
@@ -30158,11 +30789,11 @@ function DocxEditorViewer({
30158
30789
  renderPageContentHeightScale: estimatedRenderPageContentHeightScale
30159
30790
  };
30160
30791
  }
30161
- const pureEstimatedPages = buildEstimatedPages(
30162
- tableMeasuredRowHeightsForPagination,
30163
- null
30164
- );
30165
30792
  if (measuredPageContentHeightByIndex && measuredPageContentHeightByIndex.length > 0) {
30793
+ const pureEstimatedPages = buildEstimatedPages(
30794
+ tableMeasuredRowHeightsForPagination,
30795
+ null
30796
+ );
30166
30797
  const measuredPagesAreOnlySplitParagraphs = estimatedPages.length > 0 && estimatedPages.every(
30167
30798
  (pageSegments) => documentPageContainsOnlySplitParagraphSegments(pageSegments)
30168
30799
  );
@@ -30209,9 +30840,9 @@ function DocxEditorViewer({
30209
30840
  estimatedRenderMeasuredPageContentHeightsPxByPageIndex = bestCandidate.renderMeasuredPageContentHeightsPxByPageIndex;
30210
30841
  estimatedRenderPageContentHeightScale = bestCandidate.renderPageContentHeightScale;
30211
30842
  } else if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && !hasMultiColumnRenderedPageBreakHints) {
30212
- const pureEstimatedPages2 = buildEstimatedPages(void 0, null);
30213
- if (Math.abs(pureEstimatedPages2.length - targetPageCount) < Math.abs(estimatedPages.length - targetPageCount)) {
30214
- estimatedPages = pureEstimatedPages2;
30843
+ const pureEstimatedPages = buildEstimatedPages(void 0, null);
30844
+ if (Math.abs(pureEstimatedPages.length - targetPageCount) < Math.abs(estimatedPages.length - targetPageCount)) {
30845
+ estimatedPages = pureEstimatedPages;
30215
30846
  estimatedPagesUseMeasuredPageContentHeightsForRender = false;
30216
30847
  estimatedRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30217
30848
  estimatedRenderPageContentHeightScale = void 0;
@@ -30331,9 +30962,9 @@ function DocxEditorViewer({
30331
30962
  ) : void 0;
30332
30963
  let reconciledRenderPageContentHeightScale = reconciledPagesUseMeasuredPageContentHeightsForRender ? void 0 : reconciledCandidate.scale;
30333
30964
  if (!editor.canUndo && !editor.canRedo) {
30334
- const pureEstimatedPages2 = buildEstimatedPages(void 0, null);
30965
+ const pureEstimatedPages = buildEstimatedPages(void 0, null);
30335
30966
  const pureReconciledCandidate = reconcileCandidatePages(
30336
- pureEstimatedPages2,
30967
+ pureEstimatedPages,
30337
30968
  void 0,
30338
30969
  null
30339
30970
  );
@@ -30830,8 +31461,9 @@ function DocxEditorViewer({
30830
31461
  pageCount,
30831
31462
  pageVirtualization?.overscan
30832
31463
  ]);
31464
+ const shouldObserveVisiblePageRange = hasLargeTableLayoutSurface || internalVirtualItems.length === 0;
30833
31465
  React.useLayoutEffect(() => {
30834
- if (!internalPageVirtualizationEnabled || !internalVirtualScrollElement || internalVirtualItems.length > 0 || typeof window === "undefined") {
31466
+ if (!internalPageVirtualizationEnabled || !internalVirtualScrollElement || !shouldObserveVisiblePageRange || typeof window === "undefined") {
30835
31467
  setObservedVisiblePageRange(
30836
31468
  (current) => current === void 0 ? current : void 0
30837
31469
  );
@@ -30845,6 +31477,15 @@ function DocxEditorViewer({
30845
31477
  return;
30846
31478
  }
30847
31479
  let frameId = null;
31480
+ const commitObservedVisiblePageRange = (updater) => {
31481
+ if (hasLargeTableLayoutSurface) {
31482
+ (0, import_react_dom.flushSync)(() => {
31483
+ setObservedVisiblePageRange(updater);
31484
+ });
31485
+ return;
31486
+ }
31487
+ setObservedVisiblePageRange(updater);
31488
+ };
30848
31489
  const syncVisiblePageRange = () => {
30849
31490
  frameId = null;
30850
31491
  const viewportRect = internalVirtualScrollUsesWindow ? {
@@ -30878,7 +31519,7 @@ function DocxEditorViewer({
30878
31519
  lastVisiblePageIndex = pageIndex;
30879
31520
  }
30880
31521
  if (firstVisiblePageIndex === void 0 || lastVisiblePageIndex === void 0) {
30881
- setObservedVisiblePageRange(
31522
+ commitObservedVisiblePageRange(
30882
31523
  (current) => current === void 0 ? current : void 0
30883
31524
  );
30884
31525
  return;
@@ -30893,7 +31534,7 @@ function DocxEditorViewer({
30893
31534
  startPageIndex,
30894
31535
  pageCount - 1
30895
31536
  );
30896
- setObservedVisiblePageRange((current) => {
31537
+ commitObservedVisiblePageRange((current) => {
30897
31538
  if (current?.startPageIndex === startPageIndex && current?.endPageIndex === endPageIndex) {
30898
31539
  return current;
30899
31540
  }
@@ -30945,14 +31586,42 @@ function DocxEditorViewer({
30945
31586
  }
30946
31587
  };
30947
31588
  }, [
31589
+ hasLargeTableLayoutSurface,
30948
31590
  internalPageVirtualizationEnabled,
30949
31591
  internalVirtualItems.length,
30950
31592
  internalVirtualScrollElement,
30951
31593
  internalVirtualScrollUsesWindow,
30952
31594
  pageCount,
30953
- pageVirtualizationOverscan
31595
+ pageVirtualizationOverscan,
31596
+ shouldObserveVisiblePageRange
31597
+ ]);
31598
+ const internalEffectiveRenderVisiblePageRange = React.useMemo(() => {
31599
+ if (!internalRenderVisiblePageRange) {
31600
+ return observedVisiblePageRange;
31601
+ }
31602
+ if (!observedVisiblePageRange || !hasLargeTableLayoutSurface) {
31603
+ return internalRenderVisiblePageRange;
31604
+ }
31605
+ const rangesAreAdjacentOrOverlapping = observedVisiblePageRange.startPageIndex <= internalRenderVisiblePageRange.endPageIndex + 2 && internalRenderVisiblePageRange.startPageIndex <= observedVisiblePageRange.endPageIndex + 2;
31606
+ if (!rangesAreAdjacentOrOverlapping) {
31607
+ return internalRenderVisiblePageRange;
31608
+ }
31609
+ return {
31610
+ startPageIndex: Math.min(
31611
+ internalRenderVisiblePageRange.startPageIndex,
31612
+ observedVisiblePageRange.startPageIndex
31613
+ ),
31614
+ endPageIndex: Math.max(
31615
+ internalRenderVisiblePageRange.endPageIndex,
31616
+ observedVisiblePageRange.endPageIndex
31617
+ )
31618
+ };
31619
+ }, [
31620
+ hasLargeTableLayoutSurface,
31621
+ internalRenderVisiblePageRange,
31622
+ observedVisiblePageRange
30954
31623
  ]);
30955
- const effectiveVisiblePageRange = visiblePageRange ?? internalRenderVisiblePageRange ?? observedVisiblePageRange ?? (internalPageVirtualizationPending ? {
31624
+ const effectiveVisiblePageRange = visiblePageRange ?? internalEffectiveRenderVisiblePageRange ?? observedVisiblePageRange ?? (internalPageVirtualizationPending ? {
30956
31625
  startPageIndex: 0,
30957
31626
  endPageIndex: Math.min(
30958
31627
  pageCount - 1,
@@ -31001,6 +31670,43 @@ function DocxEditorViewer({
31001
31670
  }
31002
31671
  return indexes;
31003
31672
  }, [pageCount, visiblePageEndIndex, visiblePageStartIndex]);
31673
+ React.useLayoutEffect(() => {
31674
+ if (typeof window === "undefined") {
31675
+ return;
31676
+ }
31677
+ setMeasuredParagraphOuterHeightsPxByNodeIndex((current) => {
31678
+ const next = new Map(current);
31679
+ let changed = false;
31680
+ paragraphElementsRef.current.forEach((element, nodeIndex) => {
31681
+ if (!element.isConnected || element.dataset.docxParagraphPartialLineRange === "true" || element.closest('[data-docx-header-footer-region="footer"]') || element.closest('[data-docx-header-footer-region="header"]')) {
31682
+ return;
31683
+ }
31684
+ const rect = element.getBoundingClientRect();
31685
+ if (rect.width <= 0 && rect.height <= 0) {
31686
+ return;
31687
+ }
31688
+ const style2 = window.getComputedStyle(element);
31689
+ const marginTop = Number.parseFloat(style2.marginTop || "0");
31690
+ const marginBottom = Number.parseFloat(style2.marginBottom || "0");
31691
+ const outerHeightPx = Math.max(
31692
+ 1,
31693
+ Math.round(
31694
+ rect.height + (Number.isFinite(marginTop) ? marginTop : 0) + (Number.isFinite(marginBottom) ? marginBottom : 0)
31695
+ )
31696
+ );
31697
+ if (next.get(nodeIndex) !== outerHeightPx) {
31698
+ next.set(nodeIndex, outerHeightPx);
31699
+ changed = true;
31700
+ }
31701
+ });
31702
+ return changed ? next : current;
31703
+ });
31704
+ }, [
31705
+ editor.documentLoadNonce,
31706
+ pageNodeSegmentIdentityKeysByPage,
31707
+ visiblePageEndIndex,
31708
+ visiblePageStartIndex
31709
+ ]);
31004
31710
  const visibleTableRowIndexesByNodeIndex = React.useMemo(() => {
31005
31711
  const rowsByNodeIndex = /* @__PURE__ */ new Map();
31006
31712
  const addRowIndex = (nodeIndex, rowIndex) => {
@@ -31075,7 +31781,8 @@ function DocxEditorViewer({
31075
31781
  tableMeasuredRowHeights,
31076
31782
  visiblePageIndexes
31077
31783
  ]);
31078
- const visiblePagesNeedMeasurementUnlock = !hideDocumentUntilPaginationSettled && visiblePagesHavePendingPaginationMeasurements;
31784
+ const allowPostImportPaginationMeasurement = !hasLargeTableLayoutSurface || !internalPageVirtualizationEnabled;
31785
+ const visiblePagesNeedMeasurementUnlock = !hideDocumentUntilPaginationSettled && allowPostImportPaginationMeasurement && visiblePagesHavePendingPaginationMeasurements;
31079
31786
  React.useEffect(() => {
31080
31787
  if (!visiblePagesNeedMeasurementUnlock) {
31081
31788
  return;
@@ -41047,11 +41754,17 @@ function DocxEditorViewer({
41047
41754
  } : void 0,
41048
41755
  outline: "none"
41049
41756
  };
41050
- const fallbackParagraphRuns = renderInteractiveParagraphRuns(
41051
- paragraph,
41052
- `body-cell-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
41053
- location
41054
- );
41757
+ let fallbackParagraphRuns;
41758
+ const getFallbackParagraphRuns = () => {
41759
+ if (fallbackParagraphRuns === void 0) {
41760
+ fallbackParagraphRuns = renderInteractiveParagraphRuns(
41761
+ paragraph,
41762
+ `body-cell-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
41763
+ location
41764
+ );
41765
+ }
41766
+ return fallbackParagraphRuns;
41767
+ };
41055
41768
  const renderedInteractiveParagraphContent = shouldRenderParagraphSegmentWithPretext ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41056
41769
  "div",
41057
41770
  {
@@ -41089,11 +41802,11 @@ function DocxEditorViewer({
41089
41802
  style: {
41090
41803
  transform: `translateY(-${paragraphSegmentTranslateYPx - paragraphSegmentClipBleedTopPx}px)`
41091
41804
  },
41092
- children: fallbackParagraphRuns
41805
+ children: getFallbackParagraphRuns()
41093
41806
  }
41094
41807
  )
41095
41808
  }
41096
- ) : fallbackParagraphRuns;
41809
+ ) : getFallbackParagraphRuns();
41097
41810
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41098
41811
  "div",
41099
41812
  {
@@ -41335,6 +42048,7 @@ function DocxEditorViewer({
41335
42048
  ...resolvedAfterSpacingPx !== void 0 ? { marginBottom: resolvedAfterSpacingPx } : void 0
41336
42049
  } : void 0,
41337
42050
  ...letterheadStyleAdjustments ?? void 0,
42051
+ ...options?.normalizeParagraphHostFontSize ? { fontSize: `${paragraphBaseFontSizePx(node)}px` } : void 0,
41338
42052
  ...options?.suppressLetterheadColumnLayout && options?.isFirstInLetterheadColumn ? { marginTop: 0 } : void 0,
41339
42053
  ...pageAbsoluteAnchorOnlyParagraph ? {
41340
42054
  position: "relative",
@@ -41353,19 +42067,25 @@ function DocxEditorViewer({
41353
42067
  } : void 0,
41354
42068
  outline: "none"
41355
42069
  };
41356
- const fallbackParagraphRuns = renderInteractiveParagraphRuns(
41357
- node,
41358
- `node-${nodeIndex}`,
41359
- {
41360
- kind: "paragraph",
41361
- nodeIndex
41362
- },
41363
- {
41364
- pageFlowTopPx: paragraphPageFlowTopPx,
41365
- pageLayout: resolvedPageLayout,
41366
- suppressLikelyFullPageCoverImageKeys: options?.suppressLikelyFullPageCoverImageKeys
42070
+ let fallbackParagraphRuns;
42071
+ const getFallbackParagraphRuns = () => {
42072
+ if (fallbackParagraphRuns === void 0) {
42073
+ fallbackParagraphRuns = renderInteractiveParagraphRuns(
42074
+ node,
42075
+ `node-${nodeIndex}`,
42076
+ {
42077
+ kind: "paragraph",
42078
+ nodeIndex
42079
+ },
42080
+ {
42081
+ pageFlowTopPx: paragraphPageFlowTopPx,
42082
+ pageLayout: resolvedPageLayout,
42083
+ suppressLikelyFullPageCoverImageKeys: options?.suppressLikelyFullPageCoverImageKeys
42084
+ }
42085
+ );
41367
42086
  }
41368
- );
42087
+ return fallbackParagraphRuns;
42088
+ };
41369
42089
  const renderedInteractiveParagraphContent = shouldRenderParagraphSegmentWithPretext ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41370
42090
  "div",
41371
42091
  {
@@ -41406,11 +42126,11 @@ function DocxEditorViewer({
41406
42126
  style: {
41407
42127
  transform: `translateY(-${paragraphSegmentTranslateYPx - paragraphSegmentClipBleedTopPx}px)`
41408
42128
  },
41409
- children: fallbackParagraphRuns
42129
+ children: getFallbackParagraphRuns()
41410
42130
  }
41411
42131
  )
41412
42132
  }
41413
- ) : fallbackParagraphRuns;
42133
+ ) : getFallbackParagraphRuns();
41414
42134
  const paragraphDraftHtml = paragraphDraftsRef.current.get(nodeIndex);
41415
42135
  const renderedEditableParagraphHtml = typeof paragraphDraftHtml === "string" ? paragraphDraftHtml : renderStaticHtml(renderedInteractiveParagraphContent);
41416
42136
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -41421,6 +42141,7 @@ function DocxEditorViewer({
41421
42141
  "data-docx-paragraph-node-index": nodeIndex,
41422
42142
  "data-docx-paragraph-start-line": paragraphSegmentStartLine,
41423
42143
  "data-docx-paragraph-end-line": paragraphSegmentEndLine,
42144
+ "data-docx-paragraph-partial-line-range": hasPartialLineRange ? "true" : void 0,
41424
42145
  style: paragraphStyle,
41425
42146
  dangerouslySetInnerHTML: editable ? {
41426
42147
  __html: renderedEditableParagraphHtml
@@ -42458,6 +43179,68 @@ ${currentText.slice(end)}`;
42458
43179
  })() : void 0;
42459
43180
  const tableCellDraftHtml = tableCellDraftsRef.current.get(cellDraftKey);
42460
43181
  const renderedEditableCellHtml = editableCell ? typeof tableCellDraftHtml === "string" ? tableCellDraftHtml : renderStaticHtml(renderedEditableCellContent) : void 0;
43182
+ const renderStaticCellContent = () => {
43183
+ let paragraphCursor = 0;
43184
+ return cell.nodes.map(
43185
+ (cellContent, contentIndex) => {
43186
+ if (cellContent.type === "paragraph") {
43187
+ const paragraphIndex = paragraphCursor;
43188
+ paragraphCursor += 1;
43189
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43190
+ "div",
43191
+ {
43192
+ "data-docx-paragraph-host": "true",
43193
+ "data-docx-paragraph-kind": "table-cell",
43194
+ "data-docx-table-index": nodeIndex,
43195
+ "data-docx-row-index": rowIndex,
43196
+ "data-docx-cell-index": cellIndex,
43197
+ "data-docx-paragraph-index": paragraphIndex,
43198
+ "data-docx-table-paragraph-index": paragraphIndex,
43199
+ style: tableCellParagraphBlockStyle(
43200
+ cellContent,
43201
+ editor.model.metadata.numberingDefinitions,
43202
+ headingStyles,
43203
+ paragraphIndex,
43204
+ applyWordTableDefaults,
43205
+ nodeDocGridLinePitchPx
43206
+ ),
43207
+ children: renderInteractiveParagraphRuns(
43208
+ cellContent,
43209
+ `body-cell-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
43210
+ {
43211
+ kind: "table-cell",
43212
+ tableIndex: nodeIndex,
43213
+ rowIndex,
43214
+ cellIndex,
43215
+ paragraphIndex
43216
+ }
43217
+ )
43218
+ },
43219
+ `body-cell-p-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`
43220
+ );
43221
+ }
43222
+ return renderHeaderNode(
43223
+ cellContent,
43224
+ `body-cell-nested-table-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
43225
+ documentContentTheme,
43226
+ editor.model.metadata.numberingDefinitions,
43227
+ headingStyles,
43228
+ spannedWidthPx > 0 ? spannedWidthPx : void 0,
43229
+ scrollToBookmark,
43230
+ void 0,
43231
+ void 0,
43232
+ void 0,
43233
+ void 0,
43234
+ paragraphRunRenderOptions,
43235
+ void 0,
43236
+ void 0,
43237
+ tableCellEditScope,
43238
+ void 0,
43239
+ embeddedTableResizeController
43240
+ );
43241
+ }
43242
+ );
43243
+ };
42461
43244
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
42462
43245
  "td",
42463
43246
  {
@@ -43343,68 +44126,27 @@ ${currentText.slice(end)}`;
43343
44126
  );
43344
44127
  })
43345
44128
  }
43346
- ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "grid", gap: 4 }, children: (() => {
43347
- let paragraphCursor = 0;
43348
- return cell.nodes.map(
43349
- (cellContent, contentIndex) => {
43350
- if (cellContent.type === "paragraph") {
43351
- const paragraphIndex = paragraphCursor;
43352
- paragraphCursor += 1;
43353
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43354
- "div",
43355
- {
43356
- "data-docx-paragraph-host": "true",
43357
- "data-docx-paragraph-kind": "table-cell",
43358
- "data-docx-table-index": nodeIndex,
43359
- "data-docx-row-index": rowIndex,
43360
- "data-docx-cell-index": cellIndex,
43361
- "data-docx-paragraph-index": paragraphIndex,
43362
- "data-docx-table-paragraph-index": paragraphIndex,
43363
- style: tableCellParagraphBlockStyle(
43364
- cellContent,
43365
- editor.model.metadata.numberingDefinitions,
43366
- headingStyles,
43367
- paragraphIndex,
43368
- applyWordTableDefaults,
43369
- nodeDocGridLinePitchPx
43370
- ),
43371
- children: renderInteractiveParagraphRuns(
43372
- cellContent,
43373
- `body-cell-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
43374
- {
43375
- kind: "table-cell",
43376
- tableIndex: nodeIndex,
43377
- rowIndex,
43378
- cellIndex,
43379
- paragraphIndex
43380
- }
43381
- )
43382
- },
43383
- `body-cell-p-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`
43384
- );
44129
+ ) : isSlicedRow && slicedCellViewportHeightPx ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
44130
+ "div",
44131
+ {
44132
+ style: {
44133
+ height: slicedCellViewportHeightPx,
44134
+ overflow: "hidden",
44135
+ position: "relative"
44136
+ },
44137
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
44138
+ "div",
44139
+ {
44140
+ style: {
44141
+ display: "grid",
44142
+ gap: 0,
44143
+ transform: `translateY(-${tableRowSliceOffsetPx}px)`
44144
+ },
44145
+ children: renderStaticCellContent()
43385
44146
  }
43386
- return renderHeaderNode(
43387
- cellContent,
43388
- `body-cell-nested-table-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
43389
- documentContentTheme,
43390
- editor.model.metadata.numberingDefinitions,
43391
- headingStyles,
43392
- spannedWidthPx > 0 ? spannedWidthPx : void 0,
43393
- scrollToBookmark,
43394
- void 0,
43395
- void 0,
43396
- void 0,
43397
- void 0,
43398
- paragraphRunRenderOptions,
43399
- void 0,
43400
- void 0,
43401
- tableCellEditScope,
43402
- void 0,
43403
- embeddedTableResizeController
43404
- );
43405
- }
43406
- );
43407
- })() })
44147
+ )
44148
+ }
44149
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "grid", gap: 0 }, children: renderStaticCellContent() })
43408
44150
  },
43409
44151
  `cell-${nodeIndex}-${rowIndex}-${cellIndex}`
43410
44152
  );
@@ -44463,8 +45205,11 @@ ${currentText.slice(end)}`;
44463
45205
  () => new Map(endnotes.map((note) => [note.id, note])),
44464
45206
  [endnotes]
44465
45207
  );
44466
- const pageFootnotesByIndex = React.useMemo(
44467
- () => pageNodeSegmentsByPage.map((nodeSegments) => {
45208
+ const pageFootnotesByIndex = React.useMemo(() => {
45209
+ if (footnotes.length === 0) {
45210
+ return pageNodeSegmentsByPage.map(() => []);
45211
+ }
45212
+ return pageNodeSegmentsByPage.map((nodeSegments) => {
44468
45213
  const referencedIds = [];
44469
45214
  const seen = /* @__PURE__ */ new Set();
44470
45215
  nodeSegments.forEach((segment) => {
@@ -44486,10 +45231,17 @@ ${currentText.slice(end)}`;
44486
45231
  });
44487
45232
  });
44488
45233
  return referencedIds.map((referenceId) => footnotesById.get(referenceId)).filter((note) => Boolean(note));
44489
- }),
44490
- [editor.model.nodes, footnotesById, pageNodeSegmentsByPage]
44491
- );
45234
+ });
45235
+ }, [
45236
+ editor.model.nodes,
45237
+ footnotes.length,
45238
+ footnotesById,
45239
+ pageNodeSegmentsByPage
45240
+ ]);
44492
45241
  const referencedEndnotes = React.useMemo(() => {
45242
+ if (endnotes.length === 0) {
45243
+ return endnotes;
45244
+ }
44493
45245
  const referencedIds = [];
44494
45246
  const seen = /* @__PURE__ */ new Set();
44495
45247
  editor.model.nodes.forEach((node) => {
@@ -44719,6 +45471,7 @@ ${currentText.slice(end)}`;
44719
45471
  const pageVisible = isPageVisible(pageIndex);
44720
45472
  const pageWrapperWidthPx = showTrackedChangeGutter ? pageLayout.pageWidthPx + TRACKED_CHANGE_GUTTER_WIDTH_PX : pageLayout.pageWidthPx;
44721
45473
  if (!pageVisible) {
45474
+ const placeholderBackgroundColor = pageBackgroundColor ?? editor.model.metadata.documentBackgroundColor ?? pageSurfaceBaseStyle.backgroundColor;
44722
45475
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
44723
45476
  "div",
44724
45477
  {
@@ -44736,8 +45489,12 @@ ${currentText.slice(end)}`;
44736
45489
  "data-docx-page-placeholder": "true",
44737
45490
  ref: pagePlaceholderRefForIndex(pageIndex),
44738
45491
  style: {
45492
+ ...pageSurfaceBaseStyle,
44739
45493
  height: pageLayout.pageHeightPx,
44740
- width: pageLayout.pageWidthPx
45494
+ minHeight: pageLayout.pageHeightPx,
45495
+ width: pageLayout.pageWidthPx,
45496
+ backgroundColor: placeholderBackgroundColor,
45497
+ pointerEvents: "none"
44741
45498
  }
44742
45499
  }
44743
45500
  )
@@ -45195,6 +45952,14 @@ ${currentText.slice(end)}`;
45195
45952
  }
45196
45953
  );
45197
45954
  const explicitColumnWidthsPx = sectionColumns && sectionColumns.widthsPx?.length === sectionColumns.count ? sectionColumns.widthsPx : void 0;
45955
+ const flowSegmentsHaveExplicitColumnBreak = flowSegments.some((segment) => {
45956
+ if (segment.tableRowRange) {
45957
+ return false;
45958
+ }
45959
+ const segmentNode = editor.model.nodes[segment.nodeIndex];
45960
+ return segmentNode?.type === "paragraph" && paragraphHasExplicitColumnBreak(segmentNode);
45961
+ });
45962
+ const canUseColumnLineSplitRender = flowSegments.length > 0 && !flowSegmentsHaveExplicitColumnBreak;
45198
45963
  const renderSegmentInColumn = (columnSegment, columnContentWidthPx) => {
45199
45964
  const columnNode = editor.model.nodes[columnSegment.nodeIndex];
45200
45965
  if (!columnNode) {
@@ -45226,7 +45991,8 @@ ${currentText.slice(end)}`;
45226
45991
  suppressParagraphElementTracking: segmentIndex > 0,
45227
45992
  syntheticKeySuffix: `column-break-${segmentIndex}`,
45228
45993
  overrideBeforeSpacingPx: segmentIndex === 0 ? void 0 : 0,
45229
- overrideAfterSpacingPx: isLastSegment ? void 0 : 0
45994
+ overrideAfterSpacingPx: isLastSegment ? void 0 : 0,
45995
+ normalizeParagraphHostFontSize: true
45230
45996
  }
45231
45997
  )
45232
45998
  },
@@ -45247,7 +46013,8 @@ ${currentText.slice(end)}`;
45247
46013
  {
45248
46014
  pageLayout,
45249
46015
  contentWidthPxOverride: columnContentWidthPx,
45250
- suppressLikelyFullPageCoverImageKeys: suppressedLikelyFullPageCoverImageKeys
46016
+ suppressLikelyFullPageCoverImageKeys: suppressedLikelyFullPageCoverImageKeys,
46017
+ normalizeParagraphHostFontSize: true
45251
46018
  }
45252
46019
  );
45253
46020
  const segmentKeySuffix = columnSegment.tableRowRange ? `rows-${columnSegment.tableRowRange.startRowIndex}-${columnSegment.tableRowRange.endRowIndex}${columnSegment.tableRowSlice ? `-slice-${Math.max(
@@ -45286,7 +46053,91 @@ ${currentText.slice(end)}`;
45286
46053
  "div",
45287
46054
  {
45288
46055
  style: { position: "relative" },
45289
- children: explicitColumnWidthsPx && explicitColumnWidthsPx.length === 2 && flowSegments.length > 0 ? (() => {
46056
+ children: canUseColumnLineSplitRender ? (() => {
46057
+ const columnWidthsPx = explicitColumnWidthsPx && explicitColumnWidthsPx.length === sectionColumns.count ? explicitColumnWidthsPx : (() => {
46058
+ const inferredColumnWidthPx = Math.max(
46059
+ 120,
46060
+ Math.round(
46061
+ (pageContentWidthPx - sectionColumns.gapPx * Math.max(
46062
+ 0,
46063
+ sectionColumns.count - 1
46064
+ )) / Math.max(1, sectionColumns.count)
46065
+ )
46066
+ );
46067
+ return Array.from(
46068
+ { length: sectionColumns.count },
46069
+ () => inferredColumnWidthPx
46070
+ );
46071
+ })();
46072
+ const columnSegments = buildRenderColumnSegmentsForPageSection(
46073
+ editor.model,
46074
+ flowSegments,
46075
+ columnWidthsPx,
46076
+ pageBodyAvailableHeightPx,
46077
+ editor.model.metadata.numberingDefinitions,
46078
+ docGridLinePitchPxByNodeIndex,
46079
+ measuredParagraphOuterHeightsPxByNodeIndex,
46080
+ isLastPage
46081
+ );
46082
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
46083
+ overlaySegments.map((overlaySegment) => {
46084
+ const overlayNode = editor.model.nodes[overlaySegment.nodeIndex];
46085
+ if (!overlayNode) {
46086
+ return null;
46087
+ }
46088
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
46089
+ React.Fragment,
46090
+ {
46091
+ children: renderDocumentNode(
46092
+ overlayNode,
46093
+ overlaySegment.nodeIndex,
46094
+ overlaySegment.tableRowRange,
46095
+ overlaySegment.tableRowSlice,
46096
+ overlaySegment.paragraphLineRange,
46097
+ {
46098
+ pageLayout,
46099
+ suppressLikelyFullPageCoverImageKeys: suppressedLikelyFullPageCoverImageKeys
46100
+ }
46101
+ )
46102
+ },
46103
+ `column-layout-overlay-${pageIndex}-${overlaySegment.nodeIndex}-${segmentIdentityKey(
46104
+ overlaySegment
46105
+ )}`
46106
+ );
46107
+ }),
46108
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
46109
+ "div",
46110
+ {
46111
+ style: {
46112
+ display: "grid",
46113
+ gridTemplateColumns: columnWidthsPx.map((widthPx) => `${widthPx}px`).join(" "),
46114
+ columnGap: sectionColumns.gapPx,
46115
+ alignItems: "start",
46116
+ minHeight: pageBodyAvailableHeightPx,
46117
+ position: "relative",
46118
+ zIndex: 1
46119
+ },
46120
+ children: columnSegments.map(
46121
+ (segmentsForColumn, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
46122
+ "div",
46123
+ {
46124
+ style: {
46125
+ minHeight: pageBodyAvailableHeightPx
46126
+ },
46127
+ children: segmentsForColumn.map(
46128
+ (segment) => renderSegmentInColumn(
46129
+ segment,
46130
+ columnWidthsPx[columnIndex]
46131
+ )
46132
+ )
46133
+ },
46134
+ `column-layout-flow-${pageIndex}-${groupIndex}-${columnIndex}`
46135
+ )
46136
+ )
46137
+ }
46138
+ )
46139
+ ] });
46140
+ })() : explicitColumnWidthsPx && explicitColumnWidthsPx.length === 2 && flowSegments.length > 0 ? (() => {
45290
46141
  const [leftColumnWidthPx, rightColumnWidthPx] = explicitColumnWidthsPx;
45291
46142
  const prefixHeightsPx = new Array(
45292
46143
  flowSegments.length + 1
@@ -47600,6 +48451,7 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
47600
48451
  );
47601
48452
  }
47602
48453
  let rowStartIndex = 0;
48454
+ let tableBreakStartRowCursor = 0;
47603
48455
  while (rowStartIndex < estimatedRowHeightsPx.length) {
47604
48456
  const remainingHeightPx = Math.max(0, currentPageContentHeightPx - pageConsumedHeightPx);
47605
48457
  const fittedRowEndIndex = fitTableRowsWithinHeightPx2(
@@ -47611,9 +48463,10 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
47611
48463
  pageOverflowTolerancePx
47612
48464
  );
47613
48465
  let rowEndIndex = fittedRowEndIndex;
47614
- const forcedBreakRowIndex = tableBreakStartRows.find(
47615
- (breakRowIndex) => breakRowIndex > rowStartIndex
47616
- );
48466
+ while (tableBreakStartRowCursor < tableBreakStartRows.length && tableBreakStartRows[tableBreakStartRowCursor] <= rowStartIndex) {
48467
+ tableBreakStartRowCursor += 1;
48468
+ }
48469
+ const forcedBreakRowIndex = tableBreakStartRows[tableBreakStartRowCursor];
47617
48470
  if (forcedBreakRowIndex !== void 0) {
47618
48471
  rowEndIndex = Math.min(rowEndIndex, forcedBreakRowIndex);
47619
48472
  }