@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.js CHANGED
@@ -3864,10 +3864,14 @@ function parseParagraphRuns(paragraphXml2, context) {
3864
3864
  }
3865
3865
  }
3866
3866
  });
3867
+ let hyperlinkRangeCursor = 0;
3867
3868
  return runRanges.map((range, runIndex) => {
3868
- const link = hyperlinkRanges.find(
3869
- (hyperlinkRange) => range.start >= hyperlinkRange.start && range.end <= hyperlinkRange.end && hyperlinkRange.href
3870
- )?.href ?? fieldLinksByRun.get(runIndex);
3869
+ while (hyperlinkRangeCursor < hyperlinkRanges.length && hyperlinkRanges[hyperlinkRangeCursor].end <= range.start) {
3870
+ hyperlinkRangeCursor += 1;
3871
+ }
3872
+ const currentHyperlinkRange = hyperlinkRanges[hyperlinkRangeCursor];
3873
+ const hyperlinkHref = currentHyperlinkRange && range.start >= currentHyperlinkRange.start && range.end <= currentHyperlinkRange.end ? currentHyperlinkRange.href : void 0;
3874
+ const link = hyperlinkHref ?? fieldLinksByRun.get(runIndex);
3871
3875
  return {
3872
3876
  xml: paragraphXml2.slice(range.start, range.end),
3873
3877
  start: range.start,
@@ -4463,9 +4467,14 @@ function parseParagraph(paragraphXml2, context) {
4463
4467
  runs
4464
4468
  );
4465
4469
  const contentTokens = [];
4470
+ let formFieldTokenCursor = 0;
4466
4471
  for (const run of runs) {
4467
- const insideFormField = formFieldTokens.some(
4468
- (formFieldToken) => run.start >= formFieldToken.start && run.end <= formFieldToken.end
4472
+ while (formFieldTokenCursor < formFieldTokens.length && formFieldTokens[formFieldTokenCursor].end <= run.start) {
4473
+ formFieldTokenCursor += 1;
4474
+ }
4475
+ const currentFormFieldToken = formFieldTokens[formFieldTokenCursor];
4476
+ const insideFormField = Boolean(
4477
+ currentFormFieldToken && run.start >= currentFormFieldToken.start && run.end <= currentFormFieldToken.end
4469
4478
  );
4470
4479
  if (insideFormField) {
4471
4480
  continue;
@@ -8880,6 +8889,9 @@ function paragraphHasExplicitPageBreak(paragraph) {
8880
8889
  return sourceXml.length > 0 && PAGE_BREAK_XML_PATTERN.test(sourceXml);
8881
8890
  }
8882
8891
  function paragraphHasPageBreakBefore(paragraph) {
8892
+ if (paragraph.style?.pageBreakBefore === true) {
8893
+ return true;
8894
+ }
8883
8895
  const sourceXml = paragraph.sourceXml ?? "";
8884
8896
  if (!sourceXml) {
8885
8897
  return false;
@@ -10269,6 +10281,8 @@ var LARGE_TABLE_PAGE_VIRTUALIZATION_OVERSCAN = 0;
10269
10281
  var LARGE_TABLE_PAGE_ADJACENT_RENDER_COUNT = 1;
10270
10282
  var DEFAULT_PAGE_VIRTUALIZATION_SETTLE_DELAY_MS = 350;
10271
10283
  var ENABLE_TABLE_ROW_SLICING = true;
10284
+ var MIN_TABLE_ROW_SLICE_REMAINING_HEIGHT_PX = MIN_PARAGRAPH_LINE_HEIGHT_PX * 2;
10285
+ var TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX = 2;
10272
10286
  var TOP_AND_BOTTOM_VERTICAL_DRAG_SNAP_PX = 10;
10273
10287
  var HEADER_FOOTER_INACTIVE_OPACITY = 0.5;
10274
10288
  var LETTERHEAD_INDENT_MIN_TWIPS = 900;
@@ -10304,6 +10318,10 @@ var paragraphDropCapBySourceXml = /* @__PURE__ */ new Map();
10304
10318
  var paragraphTrackedMarkupBySourceXml = /* @__PURE__ */ new Map();
10305
10319
  var paragraphMeasureCanvasContext;
10306
10320
  var textWidthByFontAndValue = /* @__PURE__ */ new Map();
10321
+ var estimatedTextAdvanceWidthByFontAndValue = /* @__PURE__ */ new Map();
10322
+ var pretextWordBreakModeByText = /* @__PURE__ */ new Map();
10323
+ var paragraphBaseFontSizePxByParagraph = /* @__PURE__ */ new WeakMap();
10324
+ var paragraphDominantFontFamilyByParagraph = /* @__PURE__ */ new WeakMap();
10307
10325
  function setCacheEntry(cache, key, value) {
10308
10326
  if (!cache.has(key) && cache.size >= XML_CACHE_MAX_ENTRIES) {
10309
10327
  const oldestKey = cache.keys().next().value;
@@ -11767,7 +11785,23 @@ function resolvePageContentHeightPxForPageSegments(pageSegments, pageIndex, defa
11767
11785
  );
11768
11786
  }
11769
11787
  function resolveRenderPageContentHeightPxForPageSegments(params) {
11770
- const resolvedHeightPx = resolvePageContentHeightPxForPageSegments(
11788
+ const firstNodeIndex = params.pageSegments[0]?.nodeIndex ?? 0;
11789
+ const metricsIndex = resolvePaginationSectionMetricsIndexForNodeIndex(
11790
+ params.metricsBySection,
11791
+ firstNodeIndex,
11792
+ 0
11793
+ );
11794
+ const sectionHeightMultiplier = Math.max(
11795
+ 1,
11796
+ Math.round(
11797
+ params.metricsBySection[metricsIndex]?.pageContentHeightMultiplier ?? 1
11798
+ )
11799
+ );
11800
+ const pageContainsOnlySplitParagraphSegments = documentPageContainsOnlySplitParagraphSegments(params.pageSegments);
11801
+ const measuredHeightPx = params.useMeasuredPageContentHeights === false ? void 0 : params.measuredPageContentHeightsPxByPageIndex?.[params.pageIndex];
11802
+ const measuredHeightMatchesCurrentPage = params.pageIdentityKey === void 0 || params.measuredPageContentIdentityKeysByPageIndex?.[params.pageIndex] === void 0 || params.measuredPageContentIdentityKeysByPageIndex?.[params.pageIndex] === params.pageIdentityKey;
11803
+ const usesMeasuredVisualHeight = Number.isFinite(measuredHeightPx) && measuredHeightMatchesCurrentPage && !pageContainsOnlySplitParagraphSegments;
11804
+ let resolvedHeightPx = resolvePageContentHeightPxForPageSegments(
11771
11805
  params.pageSegments,
11772
11806
  params.pageIndex,
11773
11807
  params.defaultPageContentHeightPx,
@@ -11777,12 +11811,15 @@ function resolveRenderPageContentHeightPxForPageSegments(params) {
11777
11811
  params.pageIdentityKey
11778
11812
  );
11779
11813
  if (params.useMeasuredPageContentHeights === false && Number.isFinite(params.pageContentHeightScale) && Math.abs(params.pageContentHeightScale - 1) >= 1e-3) {
11780
- return Math.max(
11814
+ resolvedHeightPx = Math.max(
11781
11815
  120,
11782
11816
  Math.round(resolvedHeightPx * params.pageContentHeightScale)
11783
11817
  );
11784
11818
  }
11785
- return resolvedHeightPx;
11819
+ if (usesMeasuredVisualHeight || sectionHeightMultiplier <= 1) {
11820
+ return resolvedHeightPx;
11821
+ }
11822
+ return Math.max(120, Math.round(resolvedHeightPx / sectionHeightMultiplier));
11786
11823
  }
11787
11824
  function documentPageContainsOnlySplitParagraphSegments(pageSegments) {
11788
11825
  return pageSegments.length > 0 && pageSegments.every(
@@ -12336,7 +12373,9 @@ function firstExplicitFontFamilyInNodeTree(nodes) {
12336
12373
  if (node.type === "table") {
12337
12374
  for (const row of node.rows) {
12338
12375
  for (const cell of row.cells) {
12339
- const nestedFontFamily = firstExplicitFontFamilyInNodeTree(cell.nodes);
12376
+ const nestedFontFamily = firstExplicitFontFamilyInNodeTree(
12377
+ cell.nodes
12378
+ );
12340
12379
  if (nestedFontFamily) {
12341
12380
  return nestedFontFamily;
12342
12381
  }
@@ -13242,11 +13281,19 @@ function buildParagraphPretextTabSpacerText(widthPx, style, paragraphBaseFontPx)
13242
13281
  while (measuredWidthPx + spacerAdvancePx * 0.5 < safeWidthPx && spacerCount < 64) {
13243
13282
  spacerCount += 1;
13244
13283
  spacerText = spacerCharacter.repeat(spacerCount);
13245
- measuredWidthPx = measureTextWidthPx2(spacerText, style, paragraphBaseFontPx);
13284
+ measuredWidthPx = measureTextWidthPx2(
13285
+ spacerText,
13286
+ style,
13287
+ paragraphBaseFontPx
13288
+ );
13246
13289
  }
13247
13290
  while (spacerCount > 1) {
13248
13291
  const nextText = spacerCharacter.repeat(spacerCount - 1);
13249
- const nextWidthPx = measureTextWidthPx2(nextText, style, paragraphBaseFontPx);
13292
+ const nextWidthPx = measureTextWidthPx2(
13293
+ nextText,
13294
+ style,
13295
+ paragraphBaseFontPx
13296
+ );
13250
13297
  if (Math.abs(nextWidthPx - safeWidthPx) >= Math.abs(measuredWidthPx - safeWidthPx)) {
13251
13298
  break;
13252
13299
  }
@@ -13537,7 +13584,20 @@ function buildSyntheticPretextLayoutSource(text, style) {
13537
13584
  };
13538
13585
  }
13539
13586
  function pretextWordBreakModeForText(text) {
13540
- return KEEP_ALL_SCRIPT_RE.test(text) ? "keep-all" : "normal";
13587
+ const cached = pretextWordBreakModeByText.get(text);
13588
+ if (cached) {
13589
+ return cached;
13590
+ }
13591
+ const mode = KEEP_ALL_SCRIPT_RE.test(text) ? "keep-all" : "normal";
13592
+ setCacheEntry(pretextWordBreakModeByText, text, mode);
13593
+ while (pretextWordBreakModeByText.size > TEXT_MEASURE_CACHE_MAX_ENTRIES) {
13594
+ const firstKey = pretextWordBreakModeByText.keys().next().value;
13595
+ if (!firstKey) {
13596
+ break;
13597
+ }
13598
+ pretextWordBreakModeByText.delete(firstKey);
13599
+ }
13600
+ return mode;
13541
13601
  }
13542
13602
  function sanitizeRenderedPretextFragmentText(text) {
13543
13603
  return text.replace(/\r\n?|\n/g, "");
@@ -14021,36 +14081,55 @@ function estimateTextAdvanceWidthPx(text, style) {
14021
14081
  if (!text) {
14022
14082
  return 0;
14023
14083
  }
14024
- const normalized = text.replace(/\u00a0/g, " ");
14025
14084
  const fontSizePx = runFontSizePx(style);
14085
+ const normalized = text.includes("\xA0") ? text.replace(/\u00a0/g, " ") : text;
14086
+ const cacheKey = `${fontSizePx}\0${normalized}`;
14087
+ const cached = estimatedTextAdvanceWidthByFontAndValue.get(cacheKey);
14088
+ if (cached !== void 0) {
14089
+ return cached;
14090
+ }
14026
14091
  let total = 0;
14027
- for (const char of normalized) {
14028
- if (char === "\n" || char === "\r") {
14092
+ for (let index = 0; index < normalized.length; index += 1) {
14093
+ const code = normalized.charCodeAt(index);
14094
+ if (code === 10 || code === 13) {
14029
14095
  continue;
14030
14096
  }
14031
- if (char === " ") {
14097
+ if (code === 9) {
14032
14098
  total += fontSizePx * 2;
14033
14099
  continue;
14034
14100
  }
14035
- if (char === " ") {
14101
+ if (code === 32) {
14036
14102
  total += fontSizePx * 0.33;
14037
14103
  continue;
14038
14104
  }
14039
- if (/[.,:;'"`!|ilI1]/.test(char)) {
14105
+ 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) {
14040
14106
  total += fontSizePx * 0.29;
14041
14107
  continue;
14042
14108
  }
14043
- if (/[A-Z0-9]/.test(char)) {
14109
+ if (code >= 65 && code <= 90 || code >= 48 && code <= 57) {
14044
14110
  total += fontSizePx * 0.6;
14045
14111
  continue;
14046
14112
  }
14047
- if (/[\u3000-\u9fff]/.test(char)) {
14113
+ if (code >= 12288 && code <= 40959) {
14048
14114
  total += fontSizePx * 0.95;
14049
14115
  continue;
14050
14116
  }
14051
14117
  total += fontSizePx * 0.54;
14052
14118
  }
14053
- return Math.max(0, Math.round(total));
14119
+ const estimatedWidthPx = Math.max(0, Math.round(total));
14120
+ setCacheEntry(
14121
+ estimatedTextAdvanceWidthByFontAndValue,
14122
+ cacheKey,
14123
+ estimatedWidthPx
14124
+ );
14125
+ while (estimatedTextAdvanceWidthByFontAndValue.size > TEXT_MEASURE_CACHE_MAX_ENTRIES) {
14126
+ const firstKey = estimatedTextAdvanceWidthByFontAndValue.keys().next().value;
14127
+ if (!firstKey) {
14128
+ break;
14129
+ }
14130
+ estimatedTextAdvanceWidthByFontAndValue.delete(firstKey);
14131
+ }
14132
+ return estimatedWidthPx;
14054
14133
  }
14055
14134
  function updateEstimatedLineWidthPxForText(currentLineWidthPx, text, style) {
14056
14135
  if (!text) {
@@ -14356,7 +14435,8 @@ function paragraphHasLastRenderedPageBreak(paragraph) {
14356
14435
  if (cached) {
14357
14436
  return cached.lastRenderedPageBreak;
14358
14437
  }
14359
- return paragraphHasExplicitPageBreak2(paragraph) ? paragraphBreakFlagsBySourceXml.get(xml)?.lastRenderedPageBreak ?? false : false;
14438
+ paragraphHasExplicitPageBreak2(paragraph);
14439
+ return paragraphBreakFlagsBySourceXml.get(xml)?.lastRenderedPageBreak ?? false;
14360
14440
  }
14361
14441
  function paragraphStartsWithLastRenderedPageBreak(paragraph) {
14362
14442
  const xml = paragraph.sourceXml ?? "";
@@ -14530,7 +14610,8 @@ function paragraphHasPageBreakBefore2(paragraph) {
14530
14610
  if (cached) {
14531
14611
  return cached.pageBreakBefore;
14532
14612
  }
14533
- return paragraphHasExplicitPageBreak2(paragraph) ? paragraphBreakFlagsBySourceXml.get(xml)?.pageBreakBefore ?? false : false;
14613
+ paragraphHasExplicitPageBreak2(paragraph);
14614
+ return paragraphBreakFlagsBySourceXml.get(xml)?.pageBreakBefore ?? false;
14534
14615
  }
14535
14616
  function sectionBreakAfterParagraphStartsNewPage(paragraph) {
14536
14617
  const xml = paragraph.sourceXml ?? "";
@@ -14710,9 +14791,15 @@ function paragraphDominantFontSizePt(paragraph) {
14710
14791
  return dominantFontSizePt;
14711
14792
  }
14712
14793
  function paragraphBaseFontSizePx(paragraph) {
14794
+ const cached = paragraphBaseFontSizePxByParagraph.get(paragraph);
14795
+ if (cached !== void 0) {
14796
+ return cached;
14797
+ }
14713
14798
  const dominantRunFontSizePt = paragraphDominantFontSizePt(paragraph);
14714
14799
  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;
14715
- return Math.max(10, Math.round(fontSizePt * 96 / 72));
14800
+ const baseFontSizePx = Math.max(10, Math.round(fontSizePt * 96 / 72));
14801
+ paragraphBaseFontSizePxByParagraph.set(paragraph, baseFontSizePx);
14802
+ return baseFontSizePx;
14716
14803
  }
14717
14804
  function paragraphMaxFontSizePx(paragraph) {
14718
14805
  const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
@@ -14737,6 +14824,10 @@ function normalizeFontFamilyToken(fontFamily) {
14737
14824
  return normalized || void 0;
14738
14825
  }
14739
14826
  function paragraphDominantFontFamily(paragraph) {
14827
+ const cached = paragraphDominantFontFamilyByParagraph.get(paragraph);
14828
+ if (cached !== void 0) {
14829
+ return cached ?? void 0;
14830
+ }
14740
14831
  const weightByFamily = /* @__PURE__ */ new Map();
14741
14832
  const addWeight = (fontFamily, weight) => {
14742
14833
  const normalizedFamily = normalizeFontFamilyToken(fontFamily);
@@ -14757,6 +14848,7 @@ function paragraphDominantFontFamily(paragraph) {
14757
14848
  addWeight(child.style?.fontFamily, text.length);
14758
14849
  });
14759
14850
  if (weightByFamily.size === 0) {
14851
+ paragraphDominantFontFamilyByParagraph.set(paragraph, null);
14760
14852
  return void 0;
14761
14853
  }
14762
14854
  let dominantFamily;
@@ -14767,6 +14859,7 @@ function paragraphDominantFontFamily(paragraph) {
14767
14859
  dominantWeight = weight;
14768
14860
  }
14769
14861
  }
14862
+ paragraphDominantFontFamilyByParagraph.set(paragraph, dominantFamily ?? null);
14770
14863
  return dominantFamily;
14771
14864
  }
14772
14865
  function singleLineAutoScaleForFontFamily(fontFamily) {
@@ -15856,6 +15949,11 @@ function rowHasDeepFlowContent(row) {
15856
15949
  }
15857
15950
  return nestedTableCount > 0 || blockNodeCount >= SPLITTABLE_TABLE_ROW_DEEP_CONTENT_NODE_THRESHOLD;
15858
15951
  }
15952
+ function rowHasNestedTableContent(row) {
15953
+ return row.cells.some(
15954
+ (cell) => cell.nodes.some((contentNode) => contentNode.type === "table")
15955
+ );
15956
+ }
15859
15957
  function capSplitFriendlyTableRowEstimatePx(row, estimatedRowHeightPx, explicitHeightPx, pageContentHeightPx) {
15860
15958
  if (!rowAllowsPageSplit(row)) {
15861
15959
  return estimatedRowHeightPx;
@@ -15989,6 +16087,280 @@ function estimateTableRowHeightsPx(table, maxAvailableWidthPx, numberingDefiniti
15989
16087
  return Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, rowHeightPx);
15990
16088
  });
15991
16089
  }
16090
+ function uniqueSortedPixelBoundaries(values) {
16091
+ const sorted = values.filter((value) => Number.isFinite(value)).map((value) => Math.max(0, Math.round(value))).sort((left, right) => left - right);
16092
+ const unique = [];
16093
+ for (const value of sorted) {
16094
+ const previous = unique[unique.length - 1];
16095
+ if (previous === void 0 || Math.abs(previous - value) > TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX) {
16096
+ unique.push(value);
16097
+ }
16098
+ }
16099
+ return unique;
16100
+ }
16101
+ function estimateParagraphBoundaryOffsetsPx(paragraph, availableWidthPx, numberingDefinitions, applyWordTableDefaults, docGridLinePitchPx, paragraphIndex) {
16102
+ const paragraphForLayout = wordLikeTableCellParagraph(
16103
+ paragraph,
16104
+ applyWordTableDefaults
16105
+ );
16106
+ const disableDocGridSnap = paragraphDocGridSnapState(paragraph) === "disable";
16107
+ const paragraphHeightPx = estimateParagraphHeightPx(
16108
+ paragraphForLayout,
16109
+ availableWidthPx,
16110
+ numberingDefinitions,
16111
+ docGridLinePitchPx,
16112
+ disableDocGridSnap
16113
+ );
16114
+ const suppressTopSpacing = paragraphIndex === 0 && suppressFirstTableCellParagraphTopSpacing(paragraph);
16115
+ const beforeSpacingPx = suppressTopSpacing ? 0 : twipsToPixels(paragraphForLayout.style?.spacing?.beforeTwips) ?? 0;
16116
+ const afterSpacingPx = twipsToPixels(paragraphForLayout.style?.spacing?.afterTwips) ?? 0;
16117
+ const topBorderInsetPx = paragraphBorderInsetPx(
16118
+ paragraphForLayout.style?.borders?.top
16119
+ );
16120
+ const bottomBorderInsetPx = paragraphBorderInsetPx(
16121
+ paragraphForLayout.style?.borders?.bottom
16122
+ );
16123
+ const lineHeightPx = Math.max(
16124
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
16125
+ estimateParagraphLineHeightPx(
16126
+ paragraphForLayout,
16127
+ docGridLinePitchPx,
16128
+ disableDocGridSnap
16129
+ )
16130
+ );
16131
+ const pretextSource = buildParagraphPretextLayoutSource(paragraphForLayout, {
16132
+ allowExplicitLineBreakText: true,
16133
+ expandTabsForLayout: true
16134
+ });
16135
+ const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
16136
+ paragraphForLayout,
16137
+ availableWidthPx,
16138
+ numberingDefinitions
16139
+ );
16140
+ const pretextLayout = pretextSource ? layoutParagraphPretextSource(
16141
+ paragraphForLayout,
16142
+ pretextSource,
16143
+ paragraphTextWidthPx,
16144
+ lineHeightPx,
16145
+ []
16146
+ ) : void 0;
16147
+ const lineTopOffsetsPx = pretextLayout ? pretextLayout.lines.map((line) => Math.max(0, Math.round(line.y))) : Array.from(
16148
+ {
16149
+ length: Math.max(
16150
+ 1,
16151
+ paragraphLineCountWithinWidth(
16152
+ paragraphForLayout,
16153
+ availableWidthPx,
16154
+ numberingDefinitions
16155
+ )
16156
+ )
16157
+ },
16158
+ (_, lineIndex) => lineIndex * lineHeightPx
16159
+ );
16160
+ const textTopPx = beforeSpacingPx + topBorderInsetPx;
16161
+ const textHeightPx = pretextLayout ? wrappedPretextParagraphBlockHeightPx(pretextLayout) : lineTopOffsetsPx.length * lineHeightPx;
16162
+ const visualHeightPx = Math.max(
16163
+ 1,
16164
+ beforeSpacingPx + topBorderInsetPx + textHeightPx + bottomBorderInsetPx + afterSpacingPx
16165
+ );
16166
+ const heightPx = Math.max(1, paragraphHeightPx, visualHeightPx);
16167
+ const lineBoundariesPx = lineTopOffsetsPx.map(
16168
+ (lineTopPx) => textTopPx + lineTopPx + lineHeightPx
16169
+ );
16170
+ return {
16171
+ heightPx,
16172
+ safeBoundariesPx: uniqueSortedPixelBoundaries([
16173
+ ...lineBoundariesPx,
16174
+ heightPx
16175
+ ])
16176
+ };
16177
+ }
16178
+ function estimateNestedTableBoundaryOffsetsPx(table, availableWidthPx, numberingDefinitions, docGridLinePitchPx) {
16179
+ const rowHeightsPx = estimateTableRowHeightsPx(
16180
+ table,
16181
+ availableWidthPx,
16182
+ numberingDefinitions,
16183
+ docGridLinePitchPx
16184
+ );
16185
+ const boundariesPx = [];
16186
+ let cursorPx = 0;
16187
+ for (const rowHeightPx of rowHeightsPx) {
16188
+ cursorPx += Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, rowHeightPx);
16189
+ boundariesPx.push(cursorPx);
16190
+ }
16191
+ return {
16192
+ heightPx: Math.max(MIN_PARAGRAPH_LINE_HEIGHT_PX, cursorPx),
16193
+ safeBoundariesPx: uniqueSortedPixelBoundaries(boundariesPx)
16194
+ };
16195
+ }
16196
+ function estimateTableCellSliceBoundaryLayoutPx(params) {
16197
+ const {
16198
+ cell,
16199
+ rowHeightPx,
16200
+ contentWidthPx,
16201
+ tableCellMarginTwips,
16202
+ numberingDefinitions,
16203
+ applyWordTableDefaults,
16204
+ docGridLinePitchPx
16205
+ } = params;
16206
+ const paddingPx = resolveTableSpacingPaddingPx(
16207
+ mergeTableSpacing(tableCellMarginTwips, cell.style?.marginTwips)
16208
+ );
16209
+ const localBoundariesPx = [0, paddingPx.top];
16210
+ let contentCursorPx = paddingPx.top;
16211
+ let paragraphIndex = 0;
16212
+ for (const contentNode of cell.nodes) {
16213
+ const layout = contentNode.type === "paragraph" ? estimateParagraphBoundaryOffsetsPx(
16214
+ contentNode,
16215
+ contentWidthPx,
16216
+ numberingDefinitions,
16217
+ applyWordTableDefaults,
16218
+ docGridLinePitchPx,
16219
+ paragraphIndex++
16220
+ ) : estimateNestedTableBoundaryOffsetsPx(
16221
+ contentNode,
16222
+ contentWidthPx,
16223
+ numberingDefinitions,
16224
+ docGridLinePitchPx
16225
+ );
16226
+ localBoundariesPx.push(
16227
+ ...layout.safeBoundariesPx.map(
16228
+ (boundaryPx) => contentCursorPx + boundaryPx
16229
+ )
16230
+ );
16231
+ contentCursorPx += layout.heightPx;
16232
+ }
16233
+ const contentBottomPx = contentCursorPx + paddingPx.bottom;
16234
+ const contentFlowHeightPx = Math.max(0, contentCursorPx - paddingPx.top);
16235
+ const availableContentHeightPx = Math.max(
16236
+ 0,
16237
+ rowHeightPx - paddingPx.top - paddingPx.bottom
16238
+ );
16239
+ const extraVerticalSpacePx = Math.max(
16240
+ 0,
16241
+ availableContentHeightPx - contentFlowHeightPx
16242
+ );
16243
+ const verticalOffsetPx = cell.style?.verticalAlign === "center" ? Math.round(extraVerticalSpacePx / 2) : cell.style?.verticalAlign === "bottom" ? extraVerticalSpacePx : 0;
16244
+ return {
16245
+ safeBoundariesPx: uniqueSortedPixelBoundaries(
16246
+ localBoundariesPx.map(
16247
+ (boundaryPx) => Math.min(rowHeightPx, boundaryPx + verticalOffsetPx)
16248
+ )
16249
+ ),
16250
+ contentBottomPx: Math.min(rowHeightPx, contentBottomPx + verticalOffsetPx)
16251
+ };
16252
+ }
16253
+ function tableCellSliceBoundaryIsSafe(layout, boundaryPx) {
16254
+ if (boundaryPx <= TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX) {
16255
+ return true;
16256
+ }
16257
+ if (boundaryPx >= layout.contentBottomPx - TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX) {
16258
+ return true;
16259
+ }
16260
+ return layout.safeBoundariesPx.some(
16261
+ (safeBoundaryPx) => Math.abs(safeBoundaryPx - boundaryPx) <= TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX
16262
+ );
16263
+ }
16264
+ function resolveTableRowSliceHeightOnSafeBoundaryPx(params) {
16265
+ const {
16266
+ table,
16267
+ rowIndex,
16268
+ rowHeightPx,
16269
+ rowSliceOffsetPx,
16270
+ preferredSliceHeightPx,
16271
+ maxAvailableWidthPx,
16272
+ numberingDefinitions,
16273
+ docGridLinePitchPx
16274
+ } = params;
16275
+ const row = table.rows[rowIndex];
16276
+ if (!row || !rowHasNestedTableContent(row)) {
16277
+ return preferredSliceHeightPx;
16278
+ }
16279
+ const sliceStartPx = Math.max(0, Math.round(rowSliceOffsetPx));
16280
+ const preferredSliceEndPx = Math.min(
16281
+ rowHeightPx,
16282
+ sliceStartPx + Math.max(0, Math.round(preferredSliceHeightPx))
16283
+ );
16284
+ if (preferredSliceEndPx >= rowHeightPx - TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX) {
16285
+ return Math.max(0, rowHeightPx - sliceStartPx);
16286
+ }
16287
+ const columnCount = tableColumnCount(table);
16288
+ const tableWidthPx = twipsToPixels(table.style?.widthTwips);
16289
+ const rawTableColumnWidthsPx = (() => {
16290
+ const definedWidthsTwips = columnWidthsFromTableDefinition(
16291
+ table,
16292
+ columnCount
16293
+ );
16294
+ if (!definedWidthsTwips || definedWidthsTwips.length === 0) {
16295
+ return defaultColumnWidthsPx(columnCount, tableWidthPx);
16296
+ }
16297
+ const widthsPx = definedWidthsTwips.map(
16298
+ (widthTwips) => twipsToPixels(widthTwips) ?? 0
16299
+ );
16300
+ return normalizeColumnWidthsPx(widthsPx, columnCount, tableWidthPx, 1);
16301
+ })();
16302
+ const rawResolvedTableWidthPx = tableWidthPx ?? rawTableColumnWidthsPx.reduce((sum, widthPx) => sum + widthPx, 0);
16303
+ const collapsedHorizontalBorderBleedPx = resolveCollapsedTableHorizontalOuterBleedPx(table, columnCount);
16304
+ const maxTableWidthPx = Number.isFinite(maxAvailableWidthPx) && maxAvailableWidthPx > 0 ? Math.max(
16305
+ 120,
16306
+ maxAvailableWidthPx - collapsedHorizontalBorderBleedPx
16307
+ ) : void 0;
16308
+ const resolvedTableWidthPx = clampTableWidthPx(
16309
+ rawResolvedTableWidthPx,
16310
+ maxTableWidthPx
16311
+ );
16312
+ const tableColumnWidthsPx = fitColumnWidthsToWidth(
16313
+ rawTableColumnWidthsPx,
16314
+ resolvedTableWidthPx
16315
+ );
16316
+ const applyWordTableDefaults = tableUsesWordLikeParagraphDefaults(table);
16317
+ const tableCellMarginTwips = table.style?.cellMarginTwips;
16318
+ const cellLayouts = [];
16319
+ const candidateBoundariesPx = [preferredSliceEndPx];
16320
+ let columnCursor = 0;
16321
+ for (const cell of row.cells) {
16322
+ const colSpanValue = cell.style?.gridSpan && cell.style.gridSpan > 1 ? cell.style.gridSpan : 1;
16323
+ const startColumnIndex = columnCursor;
16324
+ const endColumnIndex = Math.min(
16325
+ columnCount - 1,
16326
+ startColumnIndex + colSpanValue - 1
16327
+ );
16328
+ columnCursor += colSpanValue;
16329
+ const spannedWidthPx = tableColumnWidthsPx.slice(startColumnIndex, endColumnIndex + 1).reduce((sum, widthPx) => sum + widthPx, 0);
16330
+ const fallbackCellWidthPx = resolvedTableWidthPx / Math.max(1, columnCount) * colSpanValue;
16331
+ const cellRenderedWidthPx = twipsToPixels(cell.style?.widthTwips) ?? (spannedWidthPx > 0 ? spannedWidthPx : fallbackCellWidthPx);
16332
+ const cellPaddingPx = resolveTableSpacingPaddingPx(
16333
+ mergeTableSpacing(tableCellMarginTwips, cell.style?.marginTwips)
16334
+ );
16335
+ const cellContentWidthPx = Math.max(
16336
+ 1,
16337
+ cellRenderedWidthPx - cellPaddingPx.left - cellPaddingPx.right
16338
+ );
16339
+ const cellLayout = estimateTableCellSliceBoundaryLayoutPx({
16340
+ cell,
16341
+ rowHeightPx,
16342
+ contentWidthPx: cellContentWidthPx,
16343
+ tableCellMarginTwips,
16344
+ numberingDefinitions,
16345
+ applyWordTableDefaults,
16346
+ docGridLinePitchPx
16347
+ });
16348
+ cellLayouts.push(cellLayout);
16349
+ candidateBoundariesPx.push(...cellLayout.safeBoundariesPx);
16350
+ }
16351
+ const minimumSliceEndPx = sliceStartPx + Math.max(1, MIN_TABLE_ROW_SLICE_REMAINING_HEIGHT_PX);
16352
+ const candidatesPx = uniqueSortedPixelBoundaries(candidateBoundariesPx).filter(
16353
+ (boundaryPx) => boundaryPx >= minimumSliceEndPx && boundaryPx <= preferredSliceEndPx + TABLE_ROW_SLICE_BOUNDARY_TOLERANCE_PX
16354
+ ).sort((left, right) => right - left);
16355
+ for (const candidatePx of candidatesPx) {
16356
+ if (cellLayouts.every(
16357
+ (layout) => tableCellSliceBoundaryIsSafe(layout, candidatePx)
16358
+ )) {
16359
+ return Math.max(0, candidatePx - sliceStartPx);
16360
+ }
16361
+ }
16362
+ return void 0;
16363
+ }
15992
16364
  function estimateTableHeightPx(table, maxAvailableWidthPx, numberingDefinitions, docGridLinePitchPx) {
15993
16365
  const sourceXml = table.sourceXml;
15994
16366
  const widthKey = heightEstimateCacheKeyPx(
@@ -16277,6 +16649,234 @@ function estimateRenderedPageSegmentHeightPx(node, segment, model, availableWidt
16277
16649
  )
16278
16650
  );
16279
16651
  }
16652
+ function resolveParagraphColumnRenderLineRange(paragraph, segment, availableWidthPx, numberingDefinitions, docGridLinePitchPx) {
16653
+ const lineHeightPx = Math.max(
16654
+ 1,
16655
+ segment.paragraphLineRange?.lineHeightPx ?? estimateParagraphLineHeightPx(paragraph, docGridLinePitchPx)
16656
+ );
16657
+ if (segment.paragraphLineRange) {
16658
+ return {
16659
+ ...segment.paragraphLineRange,
16660
+ lineHeightPx
16661
+ };
16662
+ }
16663
+ const paragraphTextWidthPx = paragraphAvailableTextWidthPx(
16664
+ paragraph,
16665
+ availableWidthPx,
16666
+ numberingDefinitions
16667
+ );
16668
+ const pretextSource = buildParagraphPretextLayoutSource(paragraph, {
16669
+ allowExplicitLineBreakText: true,
16670
+ expandTabsForLayout: true
16671
+ });
16672
+ const pretextLayout = pretextSource ? layoutParagraphPretextSource(
16673
+ paragraph,
16674
+ pretextSource,
16675
+ paragraphTextWidthPx,
16676
+ lineHeightPx,
16677
+ []
16678
+ ) : void 0;
16679
+ const totalLineCount = pretextLayout && pretextLayout.lineCount > 0 ? pretextLayout.lineCount : paragraphLineCountWithinWidth(
16680
+ paragraph,
16681
+ availableWidthPx,
16682
+ numberingDefinitions
16683
+ );
16684
+ return {
16685
+ startLineIndex: 0,
16686
+ endLineIndex: Math.max(1, totalLineCount),
16687
+ totalLineCount: Math.max(1, totalLineCount),
16688
+ lineHeightPx
16689
+ };
16690
+ }
16691
+ function splitParagraphSegmentForColumnRender(params) {
16692
+ const {
16693
+ paragraph,
16694
+ segment,
16695
+ model,
16696
+ availableWidthPx,
16697
+ availableHeightPx,
16698
+ numberingDefinitions,
16699
+ docGridLinePitchPx
16700
+ } = params;
16701
+ if (segment.tableRowRange || segment.tableRowSlice || paragraphHasExplicitColumnBreak(paragraph)) {
16702
+ return void 0;
16703
+ }
16704
+ const fullLineRange = resolveParagraphColumnRenderLineRange(
16705
+ paragraph,
16706
+ segment,
16707
+ availableWidthPx,
16708
+ numberingDefinitions,
16709
+ docGridLinePitchPx
16710
+ );
16711
+ const startLineIndex = Math.max(0, fullLineRange.startLineIndex);
16712
+ const endLineIndex = Math.max(startLineIndex, fullLineRange.endLineIndex);
16713
+ if (endLineIndex - startLineIndex < 2 || !paragraphCanSplitAcrossPages(paragraph, fullLineRange.totalLineCount)) {
16714
+ return void 0;
16715
+ }
16716
+ const safeAvailableHeightPx = Math.max(0, Math.round(availableHeightPx));
16717
+ let bestSegment;
16718
+ let bestHeightPx = 0;
16719
+ for (let candidateEndLineIndex = startLineIndex + 1; candidateEndLineIndex < endLineIndex; candidateEndLineIndex += 1) {
16720
+ const candidateSegment = {
16721
+ ...segment,
16722
+ paragraphLineRange: {
16723
+ startLineIndex,
16724
+ endLineIndex: candidateEndLineIndex,
16725
+ totalLineCount: fullLineRange.totalLineCount,
16726
+ lineHeightPx: fullLineRange.lineHeightPx
16727
+ }
16728
+ };
16729
+ const candidateHeightPx = estimateRenderedPageSegmentHeightPx(
16730
+ paragraph,
16731
+ candidateSegment,
16732
+ model,
16733
+ availableWidthPx,
16734
+ numberingDefinitions,
16735
+ docGridLinePitchPx
16736
+ );
16737
+ if (candidateHeightPx > safeAvailableHeightPx + PAGE_OVERFLOW_TOLERANCE_PX) {
16738
+ break;
16739
+ }
16740
+ bestSegment = candidateSegment;
16741
+ bestHeightPx = candidateHeightPx;
16742
+ }
16743
+ if (!bestSegment?.paragraphLineRange) {
16744
+ return void 0;
16745
+ }
16746
+ return {
16747
+ currentSegment: bestSegment,
16748
+ currentHeightPx: bestHeightPx,
16749
+ remainderSegment: {
16750
+ ...segment,
16751
+ paragraphLineRange: {
16752
+ startLineIndex: bestSegment.paragraphLineRange.endLineIndex,
16753
+ endLineIndex,
16754
+ totalLineCount: fullLineRange.totalLineCount,
16755
+ lineHeightPx: fullLineRange.lineHeightPx
16756
+ }
16757
+ }
16758
+ };
16759
+ }
16760
+ function buildRenderColumnSegmentsForPageSection(model, flowSegments, columnWidthsPx, columnHeightPx, numberingDefinitions, docGridLinePitchPxByNodeIndex, measuredParagraphOuterHeightsPxByNodeIndex, balanceColumns = false) {
16761
+ const columnCount = Math.max(1, columnWidthsPx.length);
16762
+ const columns = Array.from(
16763
+ { length: columnCount },
16764
+ () => []
16765
+ );
16766
+ const maxColumnHeightPx = Math.max(120, Math.round(columnHeightPx));
16767
+ const resolveSegmentHeightPx = (segment, columnWidthPx) => {
16768
+ const segmentNode = model.nodes[segment.nodeIndex];
16769
+ if (!segmentNode) {
16770
+ return MIN_PARAGRAPH_LINE_HEIGHT_PX;
16771
+ }
16772
+ const docGridLinePitchPx = docGridLinePitchPxByNodeIndex?.get(
16773
+ segment.nodeIndex
16774
+ );
16775
+ const measuredSegmentHeightPx = segmentNode.type === "paragraph" && !segment.paragraphLineRange && !segment.tableRowRange && !segment.tableRowSlice ? measuredParagraphOuterHeightsPxByNodeIndex?.get(segment.nodeIndex) : void 0;
16776
+ return Number.isFinite(measuredSegmentHeightPx) && measuredSegmentHeightPx > 0 ? Math.max(1, Math.round(measuredSegmentHeightPx)) : estimateRenderedPageSegmentHeightPx(
16777
+ segmentNode,
16778
+ segment,
16779
+ model,
16780
+ columnWidthPx,
16781
+ numberingDefinitions,
16782
+ docGridLinePitchPx
16783
+ );
16784
+ };
16785
+ const safeColumnHeightPx = balanceColumns && columnCount > 1 ? Math.min(
16786
+ maxColumnHeightPx,
16787
+ Math.max(
16788
+ MIN_PARAGRAPH_LINE_HEIGHT_PX * 4,
16789
+ Math.ceil(
16790
+ flowSegments.reduce((totalHeightPx, segment) => {
16791
+ const columnWidthPx = Math.max(
16792
+ 120,
16793
+ Math.round(columnWidthsPx[0] ?? 120)
16794
+ );
16795
+ return totalHeightPx + resolveSegmentHeightPx(segment, columnWidthPx);
16796
+ }, 0) / columnCount
16797
+ ) + PAGE_OVERFLOW_TOLERANCE_PX
16798
+ )
16799
+ ) : maxColumnHeightPx;
16800
+ let columnIndex = 0;
16801
+ let consumedHeightPx = 0;
16802
+ const moveToNextColumn = () => {
16803
+ if (columnIndex + 1 >= columnCount) {
16804
+ return false;
16805
+ }
16806
+ columnIndex += 1;
16807
+ consumedHeightPx = 0;
16808
+ return true;
16809
+ };
16810
+ const pushSegment = (segment, heightPx) => {
16811
+ columns[columnIndex]?.push(segment);
16812
+ consumedHeightPx += Math.max(1, Math.round(heightPx));
16813
+ };
16814
+ for (const flowSegment of flowSegments) {
16815
+ let pendingSegment = flowSegment;
16816
+ let splitGuard = 0;
16817
+ while (pendingSegment && splitGuard < 256) {
16818
+ splitGuard += 1;
16819
+ const currentSegment = pendingSegment;
16820
+ const segmentNode = model.nodes[currentSegment.nodeIndex];
16821
+ if (!segmentNode) {
16822
+ columns[columnIndex]?.push(currentSegment);
16823
+ break;
16824
+ }
16825
+ const columnWidthPx = Math.max(
16826
+ 120,
16827
+ Math.round(columnWidthsPx[columnIndex] ?? columnWidthsPx[0] ?? 120)
16828
+ );
16829
+ const docGridLinePitchPx = docGridLinePitchPxByNodeIndex?.get(
16830
+ currentSegment.nodeIndex
16831
+ );
16832
+ const segmentHeightPx = resolveSegmentHeightPx(
16833
+ currentSegment,
16834
+ columnWidthPx
16835
+ );
16836
+ const remainingHeightPx = Math.max(
16837
+ 0,
16838
+ safeColumnHeightPx - consumedHeightPx
16839
+ );
16840
+ if (segmentHeightPx <= remainingHeightPx + PAGE_OVERFLOW_TOLERANCE_PX || columnIndex + 1 >= columnCount) {
16841
+ pushSegment(currentSegment, segmentHeightPx);
16842
+ pendingSegment = void 0;
16843
+ break;
16844
+ }
16845
+ const splitSegment = segmentNode.type === "paragraph" ? splitParagraphSegmentForColumnRender({
16846
+ paragraph: segmentNode,
16847
+ segment: currentSegment,
16848
+ model,
16849
+ availableWidthPx: columnWidthPx,
16850
+ availableHeightPx: remainingHeightPx,
16851
+ numberingDefinitions,
16852
+ docGridLinePitchPx
16853
+ }) : void 0;
16854
+ if (splitSegment) {
16855
+ pushSegment(splitSegment.currentSegment, splitSegment.currentHeightPx);
16856
+ pendingSegment = splitSegment.remainderSegment;
16857
+ if (!moveToNextColumn()) {
16858
+ const remainderSegment = splitSegment.remainderSegment;
16859
+ const remainderHeightPx = estimateRenderedPageSegmentHeightPx(
16860
+ segmentNode,
16861
+ remainderSegment,
16862
+ model,
16863
+ columnWidthPx,
16864
+ numberingDefinitions,
16865
+ docGridLinePitchPx
16866
+ );
16867
+ pushSegment(remainderSegment, remainderHeightPx);
16868
+ pendingSegment = void 0;
16869
+ }
16870
+ continue;
16871
+ }
16872
+ if (!moveToNextColumn()) {
16873
+ pushSegment(currentSegment, segmentHeightPx);
16874
+ pendingSegment = void 0;
16875
+ }
16876
+ }
16877
+ }
16878
+ return columns;
16879
+ }
16280
16880
  function sumEstimatedTableRowHeightsPx(rowHeightsPx, startRowIndex, endRowIndex) {
16281
16881
  let total = 0;
16282
16882
  const clampedStart = Math.max(0, startRowIndex);
@@ -16750,16 +17350,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16750
17350
  const exactSegmentEndLineIndex = resolveMaxPretextLineRangeEndIndexThatFits(
16751
17351
  pretextLayoutForSegmentSplitting,
16752
17352
  lineCursor,
16753
- Math.min(
16754
- resolvedParagraphLineCount,
16755
- lineCursor + linesThatFit
16756
- ),
17353
+ Math.min(resolvedParagraphLineCount, lineCursor + linesThatFit),
16757
17354
  availableForLinesPx
16758
17355
  );
16759
- linesThatFit = Math.max(
16760
- 0,
16761
- exactSegmentEndLineIndex - lineCursor
16762
- );
17356
+ linesThatFit = Math.max(0, exactSegmentEndLineIndex - lineCursor);
16763
17357
  }
16764
17358
  if (linesThatFit < minLinesPerSegment) {
16765
17359
  if (currentPageSegments.length > 0) {
@@ -16796,10 +17390,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
16796
17390
  lineCursor,
16797
17391
  segmentEndLineIndex
16798
17392
  );
16799
- if (topSpacingPx + resolveSegmentContentHeightPx(
16800
- lineCursor,
16801
- segmentEndLineIndex
16802
- ) + segmentReservePx <= remainingHeightPx2) {
17393
+ if (topSpacingPx + resolveSegmentContentHeightPx(lineCursor, segmentEndLineIndex) + segmentReservePx <= remainingHeightPx2) {
16803
17394
  break;
16804
17395
  }
16805
17396
  linesThatFit -= 1;
@@ -17000,6 +17591,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
17000
17591
  let rowStartIndex = 0;
17001
17592
  let rowSliceOffsetPx = 0;
17002
17593
  let repeatedHeaderHeightPxOnThisPage = 0;
17594
+ let tableBreakStartRowCursor = 0;
17003
17595
  while (rowStartIndex < estimatedRowHeightsPx.length) {
17004
17596
  if (currentPageSegments.length === 0) {
17005
17597
  repeatedHeaderHeightPxOnThisPage = 0;
@@ -17034,9 +17626,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
17034
17626
  currentPageContentHeightPx - repeatedHeaderHeightPxOnThisPage
17035
17627
  );
17036
17628
  const rowExceedsFreshPageHeightPx = currentRowTotalHeightPx > freshPageAvailableHeightPx + PAGE_OVERFLOW_TOLERANCE_PX;
17629
+ const hasUsableCurrentPageSliceSpace = pageConsumedHeightPx > 0 && remainingHeightPx >= MIN_TABLE_ROW_SLICE_REMAINING_HEIGHT_PX;
17037
17630
  const canSplitCurrentRow = rowSliceOffsetPx > 0 || rowAllowsPageSplit(currentRow) || rowExceedsFreshPageHeightPx;
17038
17631
  const shouldContinueExistingRowSlice = rowSliceOffsetPx > 0;
17039
- const rowNeedsSliceOnThisPage = ENABLE_TABLE_ROW_SLICING && canSplitCurrentRow && currentRowRemainingHeightPx > remainingHeightPx + PAGE_OVERFLOW_TOLERANCE_PX && (shouldContinueExistingRowSlice || rowExceedsFreshPageHeightPx);
17632
+ const rowNeedsSliceOnThisPage = ENABLE_TABLE_ROW_SLICING && canSplitCurrentRow && currentRowRemainingHeightPx > remainingHeightPx + PAGE_OVERFLOW_TOLERANCE_PX && (shouldContinueExistingRowSlice || rowExceedsFreshPageHeightPx || hasUsableCurrentPageSliceSpace);
17040
17633
  if (canSplitCurrentRow && currentRowRemainingHeightPx > remainingHeightPx + PAGE_OVERFLOW_TOLERANCE_PX && !rowNeedsSliceOnThisPage && currentPageSegments.length > 0) {
17041
17634
  startNextPage();
17042
17635
  pageConsumedHeightPx = 0;
@@ -17064,10 +17657,38 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
17064
17657
  MIN_PARAGRAPH_LINE_HEIGHT_PX,
17065
17658
  Math.round(remainingHeightPx)
17066
17659
  );
17067
- const sliceHeightPx = Math.max(
17660
+ const preferredSliceHeightPx = Math.max(
17068
17661
  MIN_PARAGRAPH_LINE_HEIGHT_PX,
17069
17662
  Math.min(currentRowRemainingHeightPx, availableSliceHeightPx)
17070
17663
  );
17664
+ const safeSliceHeightPx = resolveTableRowSliceHeightOnSafeBoundaryPx({
17665
+ table: node,
17666
+ rowIndex: rowStartIndex,
17667
+ rowHeightPx: currentRowTotalHeightPx,
17668
+ rowSliceOffsetPx,
17669
+ preferredSliceHeightPx,
17670
+ maxAvailableWidthPx: nodeMetrics.pageContentWidthPx,
17671
+ numberingDefinitions,
17672
+ docGridLinePitchPx: nodeMetrics.docGridLinePitchPx
17673
+ });
17674
+ if (safeSliceHeightPx === void 0 && pageConsumedHeightPx > 0 && currentPageSegments.length > 0) {
17675
+ startNextPage();
17676
+ pageConsumedHeightPx = 0;
17677
+ previousParagraphAfterPx = 0;
17678
+ currentSectionPageFlowOriginPx = 0;
17679
+ currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
17680
+ currentPageIndex,
17681
+ nodeMetrics
17682
+ );
17683
+ continue;
17684
+ }
17685
+ const sliceHeightPx = Math.max(
17686
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
17687
+ Math.min(
17688
+ currentRowRemainingHeightPx,
17689
+ safeSliceHeightPx ?? preferredSliceHeightPx
17690
+ )
17691
+ );
17071
17692
  currentPageSegments.push({
17072
17693
  nodeIndex,
17073
17694
  tableRowRange: {
@@ -17133,9 +17754,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
17133
17754
  pageConsumedHeightPx <= 0
17134
17755
  );
17135
17756
  let rowEndIndex = fittedRowEndIndex;
17136
- const forcedBreakRowIndex = tableBreakStartRows.find(
17137
- (breakRowIndex) => breakRowIndex > rowStartIndex
17138
- );
17757
+ while (tableBreakStartRowCursor < tableBreakStartRows.length && tableBreakStartRows[tableBreakStartRowCursor] <= rowStartIndex) {
17758
+ tableBreakStartRowCursor += 1;
17759
+ }
17760
+ const forcedBreakRowIndex = tableBreakStartRows[tableBreakStartRowCursor];
17139
17761
  if (forcedBreakRowIndex !== void 0) {
17140
17762
  rowEndIndex = Math.min(rowEndIndex, forcedBreakRowIndex);
17141
17763
  }
@@ -17201,6 +17823,19 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
17201
17823
  rowStartIndex = rowEndIndex;
17202
17824
  rowSliceOffsetPx = 0;
17203
17825
  if (rowStartIndex < estimatedRowHeightsPx.length) {
17826
+ const nextRow = node.rows[rowStartIndex];
17827
+ const nextRowHeightPx = Math.max(
17828
+ MIN_PARAGRAPH_LINE_HEIGHT_PX,
17829
+ estimatedRowHeightsPx[rowStartIndex] ?? MIN_PARAGRAPH_LINE_HEIGHT_PX
17830
+ );
17831
+ const remainingHeightAfterSegmentPx = Math.max(
17832
+ 0,
17833
+ currentPageContentHeightPx - pageConsumedHeightPx
17834
+ );
17835
+ 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;
17836
+ if (canSliceNextRowOnCurrentPage) {
17837
+ continue;
17838
+ }
17204
17839
  startNextPage();
17205
17840
  pageConsumedHeightPx = 0;
17206
17841
  previousParagraphAfterPx = 0;
@@ -24253,7 +24888,7 @@ function useDocxEditor(options = {}) {
24253
24888
  const [status, setStatus] = React.useState(
24254
24889
  options.initialStatus ?? "Ready"
24255
24890
  );
24256
- const isImporting = false;
24891
+ const [isImporting, setIsImporting] = React.useState(false);
24257
24892
  const [documentTheme, setDocumentThemeState] = React.useState(options.initialDocumentTheme ?? "light");
24258
24893
  const [showTrackedChanges, setShowTrackedChangesState] = React.useState(options.initialShowTrackedChanges ?? false);
24259
24894
  const [paginationInfo, setPaginationInfo] = React.useState({
@@ -24776,6 +25411,8 @@ function useDocxEditor(options = {}) {
24776
25411
  setStatus("Only .docx files are supported");
24777
25412
  return;
24778
25413
  }
25414
+ setIsImporting(true);
25415
+ setStatus(`Loading ${file.name}...`);
24779
25416
  try {
24780
25417
  const buffer = await file.arrayBuffer();
24781
25418
  const pkg = await parseDocx(buffer);
@@ -24796,6 +25433,8 @@ function useDocxEditor(options = {}) {
24796
25433
  setStatus(
24797
25434
  `Failed to load file: ${error instanceof Error ? error.message : "Unknown error"}`
24798
25435
  );
25436
+ } finally {
25437
+ setIsImporting(false);
24799
25438
  }
24800
25439
  },
24801
25440
  [loadEmbeddedFontsFromPackage]
@@ -29285,7 +29924,7 @@ function DocxEditorViewer({
29285
29924
  style,
29286
29925
  pageBackgroundColor,
29287
29926
  pageGapBackgroundColor,
29288
- deferInitialPaginationPaint = true,
29927
+ deferInitialPaginationPaint = false,
29289
29928
  loadingState,
29290
29929
  pageVirtualization,
29291
29930
  visiblePageRange,
@@ -29346,6 +29985,10 @@ function DocxEditorViewer({
29346
29985
  const paragraphElementsRef = React.useRef(
29347
29986
  /* @__PURE__ */ new Map()
29348
29987
  );
29988
+ const [
29989
+ measuredParagraphOuterHeightsPxByNodeIndex,
29990
+ setMeasuredParagraphOuterHeightsPxByNodeIndex
29991
+ ] = React.useState(() => /* @__PURE__ */ new Map());
29349
29992
  const tableCellEditorElementsRef = React.useRef(
29350
29993
  /* @__PURE__ */ new Map()
29351
29994
  );
@@ -29620,6 +30263,9 @@ function DocxEditorViewer({
29620
30263
  const paginationMeasurementResumeTimeoutRef = React.useRef(
29621
30264
  null
29622
30265
  );
30266
+ React.useLayoutEffect(() => {
30267
+ setMeasuredParagraphOuterHeightsPxByNodeIndex(/* @__PURE__ */ new Map());
30268
+ }, [editor.documentLoadNonce, paragraphStructureEpoch]);
29623
30269
  const schedulePaginationMeasurementResume = React.useCallback(
29624
30270
  (delayMs) => {
29625
30271
  if (typeof window === "undefined") {
@@ -29832,10 +30478,20 @@ function DocxEditorViewer({
29832
30478
  () => buildPaginationSectionMetrics(documentSections, documentLayout),
29833
30479
  [documentLayout, documentSections]
29834
30480
  );
29835
- const docGridLinePitchPxByNodeIndex = React.useMemo(() => {
30481
+ const {
30482
+ docGridLinePitchPxByNodeIndex,
30483
+ pageContentWidthPxByNodeIndex,
30484
+ pageContentHeightPxByNodeIndex
30485
+ } = React.useMemo(() => {
29836
30486
  const pitchByNodeIndex = /* @__PURE__ */ new Map();
30487
+ const widthByNodeIndex = /* @__PURE__ */ new Map();
30488
+ const heightByNodeIndex = /* @__PURE__ */ new Map();
29837
30489
  if (editor.model.nodes.length === 0 || paginationSectionMetrics.length === 0) {
29838
- return pitchByNodeIndex;
30490
+ return {
30491
+ docGridLinePitchPxByNodeIndex: pitchByNodeIndex,
30492
+ pageContentWidthPxByNodeIndex: widthByNodeIndex,
30493
+ pageContentHeightPxByNodeIndex: heightByNodeIndex
30494
+ };
29839
30495
  }
29840
30496
  let currentMetricsIndex = 0;
29841
30497
  for (let nodeIndex = 0; nodeIndex < editor.model.nodes.length; nodeIndex += 1) {
@@ -29844,51 +30500,22 @@ function DocxEditorViewer({
29844
30500
  nodeIndex,
29845
30501
  currentMetricsIndex
29846
30502
  );
29847
- const docGridLinePitchPx = paginationSectionMetrics[currentMetricsIndex]?.docGridLinePitchPx;
30503
+ const nodeMetrics = paginationSectionMetrics[currentMetricsIndex];
30504
+ const docGridLinePitchPx = nodeMetrics?.docGridLinePitchPx;
29848
30505
  if (Number.isFinite(docGridLinePitchPx) && docGridLinePitchPx > 0) {
29849
30506
  pitchByNodeIndex.set(
29850
30507
  nodeIndex,
29851
30508
  Math.round(docGridLinePitchPx)
29852
30509
  );
29853
30510
  }
29854
- }
29855
- return pitchByNodeIndex;
29856
- }, [editor.model.nodes, paginationSectionMetrics]);
29857
- const pageContentWidthPxByNodeIndex = React.useMemo(() => {
29858
- const widthByNodeIndex = /* @__PURE__ */ new Map();
29859
- if (editor.model.nodes.length === 0 || paginationSectionMetrics.length === 0) {
29860
- return widthByNodeIndex;
29861
- }
29862
- let currentMetricsIndex = 0;
29863
- for (let nodeIndex = 0; nodeIndex < editor.model.nodes.length; nodeIndex += 1) {
29864
- currentMetricsIndex = resolvePaginationSectionMetricsIndexForNodeIndex(
29865
- paginationSectionMetrics,
29866
- nodeIndex,
29867
- currentMetricsIndex
29868
- );
29869
- const pageContentWidthPx = paginationSectionMetrics[currentMetricsIndex]?.pageContentWidthPx;
30511
+ const pageContentWidthPx = nodeMetrics?.pageContentWidthPx;
29870
30512
  if (Number.isFinite(pageContentWidthPx) && pageContentWidthPx > 0) {
29871
30513
  widthByNodeIndex.set(
29872
30514
  nodeIndex,
29873
30515
  Math.round(pageContentWidthPx)
29874
30516
  );
29875
30517
  }
29876
- }
29877
- return widthByNodeIndex;
29878
- }, [editor.model.nodes, paginationSectionMetrics]);
29879
- const pageContentHeightPxByNodeIndex = React.useMemo(() => {
29880
- const heightByNodeIndex = /* @__PURE__ */ new Map();
29881
- if (editor.model.nodes.length === 0 || paginationSectionMetrics.length === 0) {
29882
- return heightByNodeIndex;
29883
- }
29884
- let currentMetricsIndex = 0;
29885
- for (let nodeIndex = 0; nodeIndex < editor.model.nodes.length; nodeIndex += 1) {
29886
- currentMetricsIndex = resolvePaginationSectionMetricsIndexForNodeIndex(
29887
- paginationSectionMetrics,
29888
- nodeIndex,
29889
- currentMetricsIndex
29890
- );
29891
- const pageContentHeightPx = paginationSectionMetrics[currentMetricsIndex]?.pageContentHeightPx;
30518
+ const pageContentHeightPx = nodeMetrics?.pageContentHeightPx;
29892
30519
  if (Number.isFinite(pageContentHeightPx) && pageContentHeightPx > 0) {
29893
30520
  heightByNodeIndex.set(
29894
30521
  nodeIndex,
@@ -29896,7 +30523,11 @@ function DocxEditorViewer({
29896
30523
  );
29897
30524
  }
29898
30525
  }
29899
- return heightByNodeIndex;
30526
+ return {
30527
+ docGridLinePitchPxByNodeIndex: pitchByNodeIndex,
30528
+ pageContentWidthPxByNodeIndex: widthByNodeIndex,
30529
+ pageContentHeightPxByNodeIndex: heightByNodeIndex
30530
+ };
29900
30531
  }, [editor.model.nodes, paginationSectionMetrics]);
29901
30532
  const sectionColumnsBySectionIndex = React.useMemo(
29902
30533
  () => documentSections.map(
@@ -30048,11 +30679,11 @@ function DocxEditorViewer({
30048
30679
  renderPageContentHeightScale: estimatedRenderPageContentHeightScale
30049
30680
  };
30050
30681
  }
30051
- const pureEstimatedPages = buildEstimatedPages(
30052
- tableMeasuredRowHeightsForPagination,
30053
- null
30054
- );
30055
30682
  if (measuredPageContentHeightByIndex && measuredPageContentHeightByIndex.length > 0) {
30683
+ const pureEstimatedPages = buildEstimatedPages(
30684
+ tableMeasuredRowHeightsForPagination,
30685
+ null
30686
+ );
30056
30687
  const measuredPagesAreOnlySplitParagraphs = estimatedPages.length > 0 && estimatedPages.every(
30057
30688
  (pageSegments) => documentPageContainsOnlySplitParagraphSegments(pageSegments)
30058
30689
  );
@@ -30099,9 +30730,9 @@ function DocxEditorViewer({
30099
30730
  estimatedRenderMeasuredPageContentHeightsPxByPageIndex = bestCandidate.renderMeasuredPageContentHeightsPxByPageIndex;
30100
30731
  estimatedRenderPageContentHeightScale = bestCandidate.renderPageContentHeightScale;
30101
30732
  } else if (!editor.canUndo && !editor.canRedo && targetPageCount !== void 0 && !hasMultiColumnRenderedPageBreakHints) {
30102
- const pureEstimatedPages2 = buildEstimatedPages(void 0, null);
30103
- if (Math.abs(pureEstimatedPages2.length - targetPageCount) < Math.abs(estimatedPages.length - targetPageCount)) {
30104
- estimatedPages = pureEstimatedPages2;
30733
+ const pureEstimatedPages = buildEstimatedPages(void 0, null);
30734
+ if (Math.abs(pureEstimatedPages.length - targetPageCount) < Math.abs(estimatedPages.length - targetPageCount)) {
30735
+ estimatedPages = pureEstimatedPages;
30105
30736
  estimatedPagesUseMeasuredPageContentHeightsForRender = false;
30106
30737
  estimatedRenderMeasuredPageContentHeightsPxByPageIndex = void 0;
30107
30738
  estimatedRenderPageContentHeightScale = void 0;
@@ -30221,9 +30852,9 @@ function DocxEditorViewer({
30221
30852
  ) : void 0;
30222
30853
  let reconciledRenderPageContentHeightScale = reconciledPagesUseMeasuredPageContentHeightsForRender ? void 0 : reconciledCandidate.scale;
30223
30854
  if (!editor.canUndo && !editor.canRedo) {
30224
- const pureEstimatedPages2 = buildEstimatedPages(void 0, null);
30855
+ const pureEstimatedPages = buildEstimatedPages(void 0, null);
30225
30856
  const pureReconciledCandidate = reconcileCandidatePages(
30226
- pureEstimatedPages2,
30857
+ pureEstimatedPages,
30227
30858
  void 0,
30228
30859
  null
30229
30860
  );
@@ -30720,8 +31351,9 @@ function DocxEditorViewer({
30720
31351
  pageCount,
30721
31352
  pageVirtualization?.overscan
30722
31353
  ]);
31354
+ const shouldObserveVisiblePageRange = hasLargeTableLayoutSurface || internalVirtualItems.length === 0;
30723
31355
  React.useLayoutEffect(() => {
30724
- if (!internalPageVirtualizationEnabled || !internalVirtualScrollElement || internalVirtualItems.length > 0 || typeof window === "undefined") {
31356
+ if (!internalPageVirtualizationEnabled || !internalVirtualScrollElement || !shouldObserveVisiblePageRange || typeof window === "undefined") {
30725
31357
  setObservedVisiblePageRange(
30726
31358
  (current) => current === void 0 ? current : void 0
30727
31359
  );
@@ -30735,6 +31367,15 @@ function DocxEditorViewer({
30735
31367
  return;
30736
31368
  }
30737
31369
  let frameId = null;
31370
+ const commitObservedVisiblePageRange = (updater) => {
31371
+ if (hasLargeTableLayoutSurface) {
31372
+ flushSync(() => {
31373
+ setObservedVisiblePageRange(updater);
31374
+ });
31375
+ return;
31376
+ }
31377
+ setObservedVisiblePageRange(updater);
31378
+ };
30738
31379
  const syncVisiblePageRange = () => {
30739
31380
  frameId = null;
30740
31381
  const viewportRect = internalVirtualScrollUsesWindow ? {
@@ -30768,7 +31409,7 @@ function DocxEditorViewer({
30768
31409
  lastVisiblePageIndex = pageIndex;
30769
31410
  }
30770
31411
  if (firstVisiblePageIndex === void 0 || lastVisiblePageIndex === void 0) {
30771
- setObservedVisiblePageRange(
31412
+ commitObservedVisiblePageRange(
30772
31413
  (current) => current === void 0 ? current : void 0
30773
31414
  );
30774
31415
  return;
@@ -30783,7 +31424,7 @@ function DocxEditorViewer({
30783
31424
  startPageIndex,
30784
31425
  pageCount - 1
30785
31426
  );
30786
- setObservedVisiblePageRange((current) => {
31427
+ commitObservedVisiblePageRange((current) => {
30787
31428
  if (current?.startPageIndex === startPageIndex && current?.endPageIndex === endPageIndex) {
30788
31429
  return current;
30789
31430
  }
@@ -30835,14 +31476,42 @@ function DocxEditorViewer({
30835
31476
  }
30836
31477
  };
30837
31478
  }, [
31479
+ hasLargeTableLayoutSurface,
30838
31480
  internalPageVirtualizationEnabled,
30839
31481
  internalVirtualItems.length,
30840
31482
  internalVirtualScrollElement,
30841
31483
  internalVirtualScrollUsesWindow,
30842
31484
  pageCount,
30843
- pageVirtualizationOverscan
31485
+ pageVirtualizationOverscan,
31486
+ shouldObserveVisiblePageRange
31487
+ ]);
31488
+ const internalEffectiveRenderVisiblePageRange = React.useMemo(() => {
31489
+ if (!internalRenderVisiblePageRange) {
31490
+ return observedVisiblePageRange;
31491
+ }
31492
+ if (!observedVisiblePageRange || !hasLargeTableLayoutSurface) {
31493
+ return internalRenderVisiblePageRange;
31494
+ }
31495
+ const rangesAreAdjacentOrOverlapping = observedVisiblePageRange.startPageIndex <= internalRenderVisiblePageRange.endPageIndex + 2 && internalRenderVisiblePageRange.startPageIndex <= observedVisiblePageRange.endPageIndex + 2;
31496
+ if (!rangesAreAdjacentOrOverlapping) {
31497
+ return internalRenderVisiblePageRange;
31498
+ }
31499
+ return {
31500
+ startPageIndex: Math.min(
31501
+ internalRenderVisiblePageRange.startPageIndex,
31502
+ observedVisiblePageRange.startPageIndex
31503
+ ),
31504
+ endPageIndex: Math.max(
31505
+ internalRenderVisiblePageRange.endPageIndex,
31506
+ observedVisiblePageRange.endPageIndex
31507
+ )
31508
+ };
31509
+ }, [
31510
+ hasLargeTableLayoutSurface,
31511
+ internalRenderVisiblePageRange,
31512
+ observedVisiblePageRange
30844
31513
  ]);
30845
- const effectiveVisiblePageRange = visiblePageRange ?? internalRenderVisiblePageRange ?? observedVisiblePageRange ?? (internalPageVirtualizationPending ? {
31514
+ const effectiveVisiblePageRange = visiblePageRange ?? internalEffectiveRenderVisiblePageRange ?? observedVisiblePageRange ?? (internalPageVirtualizationPending ? {
30846
31515
  startPageIndex: 0,
30847
31516
  endPageIndex: Math.min(
30848
31517
  pageCount - 1,
@@ -30891,6 +31560,43 @@ function DocxEditorViewer({
30891
31560
  }
30892
31561
  return indexes;
30893
31562
  }, [pageCount, visiblePageEndIndex, visiblePageStartIndex]);
31563
+ React.useLayoutEffect(() => {
31564
+ if (typeof window === "undefined") {
31565
+ return;
31566
+ }
31567
+ setMeasuredParagraphOuterHeightsPxByNodeIndex((current) => {
31568
+ const next = new Map(current);
31569
+ let changed = false;
31570
+ paragraphElementsRef.current.forEach((element, nodeIndex) => {
31571
+ if (!element.isConnected || element.dataset.docxParagraphPartialLineRange === "true" || element.closest('[data-docx-header-footer-region="footer"]') || element.closest('[data-docx-header-footer-region="header"]')) {
31572
+ return;
31573
+ }
31574
+ const rect = element.getBoundingClientRect();
31575
+ if (rect.width <= 0 && rect.height <= 0) {
31576
+ return;
31577
+ }
31578
+ const style2 = window.getComputedStyle(element);
31579
+ const marginTop = Number.parseFloat(style2.marginTop || "0");
31580
+ const marginBottom = Number.parseFloat(style2.marginBottom || "0");
31581
+ const outerHeightPx = Math.max(
31582
+ 1,
31583
+ Math.round(
31584
+ rect.height + (Number.isFinite(marginTop) ? marginTop : 0) + (Number.isFinite(marginBottom) ? marginBottom : 0)
31585
+ )
31586
+ );
31587
+ if (next.get(nodeIndex) !== outerHeightPx) {
31588
+ next.set(nodeIndex, outerHeightPx);
31589
+ changed = true;
31590
+ }
31591
+ });
31592
+ return changed ? next : current;
31593
+ });
31594
+ }, [
31595
+ editor.documentLoadNonce,
31596
+ pageNodeSegmentIdentityKeysByPage,
31597
+ visiblePageEndIndex,
31598
+ visiblePageStartIndex
31599
+ ]);
30894
31600
  const visibleTableRowIndexesByNodeIndex = React.useMemo(() => {
30895
31601
  const rowsByNodeIndex = /* @__PURE__ */ new Map();
30896
31602
  const addRowIndex = (nodeIndex, rowIndex) => {
@@ -30965,7 +31671,8 @@ function DocxEditorViewer({
30965
31671
  tableMeasuredRowHeights,
30966
31672
  visiblePageIndexes
30967
31673
  ]);
30968
- const visiblePagesNeedMeasurementUnlock = !hideDocumentUntilPaginationSettled && visiblePagesHavePendingPaginationMeasurements;
31674
+ const allowPostImportPaginationMeasurement = !hasLargeTableLayoutSurface || !internalPageVirtualizationEnabled;
31675
+ const visiblePagesNeedMeasurementUnlock = !hideDocumentUntilPaginationSettled && allowPostImportPaginationMeasurement && visiblePagesHavePendingPaginationMeasurements;
30969
31676
  React.useEffect(() => {
30970
31677
  if (!visiblePagesNeedMeasurementUnlock) {
30971
31678
  return;
@@ -40937,11 +41644,17 @@ function DocxEditorViewer({
40937
41644
  } : void 0,
40938
41645
  outline: "none"
40939
41646
  };
40940
- const fallbackParagraphRuns = renderInteractiveParagraphRuns(
40941
- paragraph,
40942
- `body-cell-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
40943
- location
40944
- );
41647
+ let fallbackParagraphRuns;
41648
+ const getFallbackParagraphRuns = () => {
41649
+ if (fallbackParagraphRuns === void 0) {
41650
+ fallbackParagraphRuns = renderInteractiveParagraphRuns(
41651
+ paragraph,
41652
+ `body-cell-${tableIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
41653
+ location
41654
+ );
41655
+ }
41656
+ return fallbackParagraphRuns;
41657
+ };
40945
41658
  const renderedInteractiveParagraphContent = shouldRenderParagraphSegmentWithPretext ? /* @__PURE__ */ jsx(
40946
41659
  "div",
40947
41660
  {
@@ -40979,11 +41692,11 @@ function DocxEditorViewer({
40979
41692
  style: {
40980
41693
  transform: `translateY(-${paragraphSegmentTranslateYPx - paragraphSegmentClipBleedTopPx}px)`
40981
41694
  },
40982
- children: fallbackParagraphRuns
41695
+ children: getFallbackParagraphRuns()
40983
41696
  }
40984
41697
  )
40985
41698
  }
40986
- ) : fallbackParagraphRuns;
41699
+ ) : getFallbackParagraphRuns();
40987
41700
  return /* @__PURE__ */ jsx(
40988
41701
  "div",
40989
41702
  {
@@ -41225,6 +41938,7 @@ function DocxEditorViewer({
41225
41938
  ...resolvedAfterSpacingPx !== void 0 ? { marginBottom: resolvedAfterSpacingPx } : void 0
41226
41939
  } : void 0,
41227
41940
  ...letterheadStyleAdjustments ?? void 0,
41941
+ ...options?.normalizeParagraphHostFontSize ? { fontSize: `${paragraphBaseFontSizePx(node)}px` } : void 0,
41228
41942
  ...options?.suppressLetterheadColumnLayout && options?.isFirstInLetterheadColumn ? { marginTop: 0 } : void 0,
41229
41943
  ...pageAbsoluteAnchorOnlyParagraph ? {
41230
41944
  position: "relative",
@@ -41243,19 +41957,25 @@ function DocxEditorViewer({
41243
41957
  } : void 0,
41244
41958
  outline: "none"
41245
41959
  };
41246
- const fallbackParagraphRuns = renderInteractiveParagraphRuns(
41247
- node,
41248
- `node-${nodeIndex}`,
41249
- {
41250
- kind: "paragraph",
41251
- nodeIndex
41252
- },
41253
- {
41254
- pageFlowTopPx: paragraphPageFlowTopPx,
41255
- pageLayout: resolvedPageLayout,
41256
- suppressLikelyFullPageCoverImageKeys: options?.suppressLikelyFullPageCoverImageKeys
41960
+ let fallbackParagraphRuns;
41961
+ const getFallbackParagraphRuns = () => {
41962
+ if (fallbackParagraphRuns === void 0) {
41963
+ fallbackParagraphRuns = renderInteractiveParagraphRuns(
41964
+ node,
41965
+ `node-${nodeIndex}`,
41966
+ {
41967
+ kind: "paragraph",
41968
+ nodeIndex
41969
+ },
41970
+ {
41971
+ pageFlowTopPx: paragraphPageFlowTopPx,
41972
+ pageLayout: resolvedPageLayout,
41973
+ suppressLikelyFullPageCoverImageKeys: options?.suppressLikelyFullPageCoverImageKeys
41974
+ }
41975
+ );
41257
41976
  }
41258
- );
41977
+ return fallbackParagraphRuns;
41978
+ };
41259
41979
  const renderedInteractiveParagraphContent = shouldRenderParagraphSegmentWithPretext ? /* @__PURE__ */ jsx(
41260
41980
  "div",
41261
41981
  {
@@ -41296,11 +42016,11 @@ function DocxEditorViewer({
41296
42016
  style: {
41297
42017
  transform: `translateY(-${paragraphSegmentTranslateYPx - paragraphSegmentClipBleedTopPx}px)`
41298
42018
  },
41299
- children: fallbackParagraphRuns
42019
+ children: getFallbackParagraphRuns()
41300
42020
  }
41301
42021
  )
41302
42022
  }
41303
- ) : fallbackParagraphRuns;
42023
+ ) : getFallbackParagraphRuns();
41304
42024
  const paragraphDraftHtml = paragraphDraftsRef.current.get(nodeIndex);
41305
42025
  const renderedEditableParagraphHtml = typeof paragraphDraftHtml === "string" ? paragraphDraftHtml : renderStaticHtml(renderedInteractiveParagraphContent);
41306
42026
  return /* @__PURE__ */ jsx(
@@ -41311,6 +42031,7 @@ function DocxEditorViewer({
41311
42031
  "data-docx-paragraph-node-index": nodeIndex,
41312
42032
  "data-docx-paragraph-start-line": paragraphSegmentStartLine,
41313
42033
  "data-docx-paragraph-end-line": paragraphSegmentEndLine,
42034
+ "data-docx-paragraph-partial-line-range": hasPartialLineRange ? "true" : void 0,
41314
42035
  style: paragraphStyle,
41315
42036
  dangerouslySetInnerHTML: editable ? {
41316
42037
  __html: renderedEditableParagraphHtml
@@ -42348,6 +43069,68 @@ ${currentText.slice(end)}`;
42348
43069
  })() : void 0;
42349
43070
  const tableCellDraftHtml = tableCellDraftsRef.current.get(cellDraftKey);
42350
43071
  const renderedEditableCellHtml = editableCell ? typeof tableCellDraftHtml === "string" ? tableCellDraftHtml : renderStaticHtml(renderedEditableCellContent) : void 0;
43072
+ const renderStaticCellContent = () => {
43073
+ let paragraphCursor = 0;
43074
+ return cell.nodes.map(
43075
+ (cellContent, contentIndex) => {
43076
+ if (cellContent.type === "paragraph") {
43077
+ const paragraphIndex = paragraphCursor;
43078
+ paragraphCursor += 1;
43079
+ return /* @__PURE__ */ jsx(
43080
+ "div",
43081
+ {
43082
+ "data-docx-paragraph-host": "true",
43083
+ "data-docx-paragraph-kind": "table-cell",
43084
+ "data-docx-table-index": nodeIndex,
43085
+ "data-docx-row-index": rowIndex,
43086
+ "data-docx-cell-index": cellIndex,
43087
+ "data-docx-paragraph-index": paragraphIndex,
43088
+ "data-docx-table-paragraph-index": paragraphIndex,
43089
+ style: tableCellParagraphBlockStyle(
43090
+ cellContent,
43091
+ editor.model.metadata.numberingDefinitions,
43092
+ headingStyles,
43093
+ paragraphIndex,
43094
+ applyWordTableDefaults,
43095
+ nodeDocGridLinePitchPx
43096
+ ),
43097
+ children: renderInteractiveParagraphRuns(
43098
+ cellContent,
43099
+ `body-cell-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
43100
+ {
43101
+ kind: "table-cell",
43102
+ tableIndex: nodeIndex,
43103
+ rowIndex,
43104
+ cellIndex,
43105
+ paragraphIndex
43106
+ }
43107
+ )
43108
+ },
43109
+ `body-cell-p-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`
43110
+ );
43111
+ }
43112
+ return renderHeaderNode(
43113
+ cellContent,
43114
+ `body-cell-nested-table-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
43115
+ documentContentTheme,
43116
+ editor.model.metadata.numberingDefinitions,
43117
+ headingStyles,
43118
+ spannedWidthPx > 0 ? spannedWidthPx : void 0,
43119
+ scrollToBookmark,
43120
+ void 0,
43121
+ void 0,
43122
+ void 0,
43123
+ void 0,
43124
+ paragraphRunRenderOptions,
43125
+ void 0,
43126
+ void 0,
43127
+ tableCellEditScope,
43128
+ void 0,
43129
+ embeddedTableResizeController
43130
+ );
43131
+ }
43132
+ );
43133
+ };
42351
43134
  return /* @__PURE__ */ jsx(
42352
43135
  "td",
42353
43136
  {
@@ -43233,68 +44016,27 @@ ${currentText.slice(end)}`;
43233
44016
  );
43234
44017
  })
43235
44018
  }
43236
- ) : /* @__PURE__ */ jsx("div", { style: { display: "grid", gap: 4 }, children: (() => {
43237
- let paragraphCursor = 0;
43238
- return cell.nodes.map(
43239
- (cellContent, contentIndex) => {
43240
- if (cellContent.type === "paragraph") {
43241
- const paragraphIndex = paragraphCursor;
43242
- paragraphCursor += 1;
43243
- return /* @__PURE__ */ jsx(
43244
- "div",
43245
- {
43246
- "data-docx-paragraph-host": "true",
43247
- "data-docx-paragraph-kind": "table-cell",
43248
- "data-docx-table-index": nodeIndex,
43249
- "data-docx-row-index": rowIndex,
43250
- "data-docx-cell-index": cellIndex,
43251
- "data-docx-paragraph-index": paragraphIndex,
43252
- "data-docx-table-paragraph-index": paragraphIndex,
43253
- style: tableCellParagraphBlockStyle(
43254
- cellContent,
43255
- editor.model.metadata.numberingDefinitions,
43256
- headingStyles,
43257
- paragraphIndex,
43258
- applyWordTableDefaults,
43259
- nodeDocGridLinePitchPx
43260
- ),
43261
- children: renderInteractiveParagraphRuns(
43262
- cellContent,
43263
- `body-cell-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
43264
- {
43265
- kind: "table-cell",
43266
- tableIndex: nodeIndex,
43267
- rowIndex,
43268
- cellIndex,
43269
- paragraphIndex
43270
- }
43271
- )
43272
- },
43273
- `body-cell-p-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`
43274
- );
44019
+ ) : isSlicedRow && slicedCellViewportHeightPx ? /* @__PURE__ */ jsx(
44020
+ "div",
44021
+ {
44022
+ style: {
44023
+ height: slicedCellViewportHeightPx,
44024
+ overflow: "hidden",
44025
+ position: "relative"
44026
+ },
44027
+ children: /* @__PURE__ */ jsx(
44028
+ "div",
44029
+ {
44030
+ style: {
44031
+ display: "grid",
44032
+ gap: 0,
44033
+ transform: `translateY(-${tableRowSliceOffsetPx}px)`
44034
+ },
44035
+ children: renderStaticCellContent()
43275
44036
  }
43276
- return renderHeaderNode(
43277
- cellContent,
43278
- `body-cell-nested-table-${nodeIndex}-${rowIndex}-${cellIndex}-${contentIndex}`,
43279
- documentContentTheme,
43280
- editor.model.metadata.numberingDefinitions,
43281
- headingStyles,
43282
- spannedWidthPx > 0 ? spannedWidthPx : void 0,
43283
- scrollToBookmark,
43284
- void 0,
43285
- void 0,
43286
- void 0,
43287
- void 0,
43288
- paragraphRunRenderOptions,
43289
- void 0,
43290
- void 0,
43291
- tableCellEditScope,
43292
- void 0,
43293
- embeddedTableResizeController
43294
- );
43295
- }
43296
- );
43297
- })() })
44037
+ )
44038
+ }
44039
+ ) : /* @__PURE__ */ jsx("div", { style: { display: "grid", gap: 0 }, children: renderStaticCellContent() })
43298
44040
  },
43299
44041
  `cell-${nodeIndex}-${rowIndex}-${cellIndex}`
43300
44042
  );
@@ -44353,8 +45095,11 @@ ${currentText.slice(end)}`;
44353
45095
  () => new Map(endnotes.map((note) => [note.id, note])),
44354
45096
  [endnotes]
44355
45097
  );
44356
- const pageFootnotesByIndex = React.useMemo(
44357
- () => pageNodeSegmentsByPage.map((nodeSegments) => {
45098
+ const pageFootnotesByIndex = React.useMemo(() => {
45099
+ if (footnotes.length === 0) {
45100
+ return pageNodeSegmentsByPage.map(() => []);
45101
+ }
45102
+ return pageNodeSegmentsByPage.map((nodeSegments) => {
44358
45103
  const referencedIds = [];
44359
45104
  const seen = /* @__PURE__ */ new Set();
44360
45105
  nodeSegments.forEach((segment) => {
@@ -44376,10 +45121,17 @@ ${currentText.slice(end)}`;
44376
45121
  });
44377
45122
  });
44378
45123
  return referencedIds.map((referenceId) => footnotesById.get(referenceId)).filter((note) => Boolean(note));
44379
- }),
44380
- [editor.model.nodes, footnotesById, pageNodeSegmentsByPage]
44381
- );
45124
+ });
45125
+ }, [
45126
+ editor.model.nodes,
45127
+ footnotes.length,
45128
+ footnotesById,
45129
+ pageNodeSegmentsByPage
45130
+ ]);
44382
45131
  const referencedEndnotes = React.useMemo(() => {
45132
+ if (endnotes.length === 0) {
45133
+ return endnotes;
45134
+ }
44383
45135
  const referencedIds = [];
44384
45136
  const seen = /* @__PURE__ */ new Set();
44385
45137
  editor.model.nodes.forEach((node) => {
@@ -44609,6 +45361,7 @@ ${currentText.slice(end)}`;
44609
45361
  const pageVisible = isPageVisible(pageIndex);
44610
45362
  const pageWrapperWidthPx = showTrackedChangeGutter ? pageLayout.pageWidthPx + TRACKED_CHANGE_GUTTER_WIDTH_PX : pageLayout.pageWidthPx;
44611
45363
  if (!pageVisible) {
45364
+ const placeholderBackgroundColor = pageBackgroundColor ?? editor.model.metadata.documentBackgroundColor ?? pageSurfaceBaseStyle.backgroundColor;
44612
45365
  return /* @__PURE__ */ jsx(
44613
45366
  "div",
44614
45367
  {
@@ -44626,8 +45379,12 @@ ${currentText.slice(end)}`;
44626
45379
  "data-docx-page-placeholder": "true",
44627
45380
  ref: pagePlaceholderRefForIndex(pageIndex),
44628
45381
  style: {
45382
+ ...pageSurfaceBaseStyle,
44629
45383
  height: pageLayout.pageHeightPx,
44630
- width: pageLayout.pageWidthPx
45384
+ minHeight: pageLayout.pageHeightPx,
45385
+ width: pageLayout.pageWidthPx,
45386
+ backgroundColor: placeholderBackgroundColor,
45387
+ pointerEvents: "none"
44631
45388
  }
44632
45389
  }
44633
45390
  )
@@ -45085,6 +45842,14 @@ ${currentText.slice(end)}`;
45085
45842
  }
45086
45843
  );
45087
45844
  const explicitColumnWidthsPx = sectionColumns && sectionColumns.widthsPx?.length === sectionColumns.count ? sectionColumns.widthsPx : void 0;
45845
+ const flowSegmentsHaveExplicitColumnBreak = flowSegments.some((segment) => {
45846
+ if (segment.tableRowRange) {
45847
+ return false;
45848
+ }
45849
+ const segmentNode = editor.model.nodes[segment.nodeIndex];
45850
+ return segmentNode?.type === "paragraph" && paragraphHasExplicitColumnBreak(segmentNode);
45851
+ });
45852
+ const canUseColumnLineSplitRender = flowSegments.length > 0 && !flowSegmentsHaveExplicitColumnBreak;
45088
45853
  const renderSegmentInColumn = (columnSegment, columnContentWidthPx) => {
45089
45854
  const columnNode = editor.model.nodes[columnSegment.nodeIndex];
45090
45855
  if (!columnNode) {
@@ -45116,7 +45881,8 @@ ${currentText.slice(end)}`;
45116
45881
  suppressParagraphElementTracking: segmentIndex > 0,
45117
45882
  syntheticKeySuffix: `column-break-${segmentIndex}`,
45118
45883
  overrideBeforeSpacingPx: segmentIndex === 0 ? void 0 : 0,
45119
- overrideAfterSpacingPx: isLastSegment ? void 0 : 0
45884
+ overrideAfterSpacingPx: isLastSegment ? void 0 : 0,
45885
+ normalizeParagraphHostFontSize: true
45120
45886
  }
45121
45887
  )
45122
45888
  },
@@ -45137,7 +45903,8 @@ ${currentText.slice(end)}`;
45137
45903
  {
45138
45904
  pageLayout,
45139
45905
  contentWidthPxOverride: columnContentWidthPx,
45140
- suppressLikelyFullPageCoverImageKeys: suppressedLikelyFullPageCoverImageKeys
45906
+ suppressLikelyFullPageCoverImageKeys: suppressedLikelyFullPageCoverImageKeys,
45907
+ normalizeParagraphHostFontSize: true
45141
45908
  }
45142
45909
  );
45143
45910
  const segmentKeySuffix = columnSegment.tableRowRange ? `rows-${columnSegment.tableRowRange.startRowIndex}-${columnSegment.tableRowRange.endRowIndex}${columnSegment.tableRowSlice ? `-slice-${Math.max(
@@ -45176,7 +45943,91 @@ ${currentText.slice(end)}`;
45176
45943
  "div",
45177
45944
  {
45178
45945
  style: { position: "relative" },
45179
- children: explicitColumnWidthsPx && explicitColumnWidthsPx.length === 2 && flowSegments.length > 0 ? (() => {
45946
+ children: canUseColumnLineSplitRender ? (() => {
45947
+ const columnWidthsPx = explicitColumnWidthsPx && explicitColumnWidthsPx.length === sectionColumns.count ? explicitColumnWidthsPx : (() => {
45948
+ const inferredColumnWidthPx = Math.max(
45949
+ 120,
45950
+ Math.round(
45951
+ (pageContentWidthPx - sectionColumns.gapPx * Math.max(
45952
+ 0,
45953
+ sectionColumns.count - 1
45954
+ )) / Math.max(1, sectionColumns.count)
45955
+ )
45956
+ );
45957
+ return Array.from(
45958
+ { length: sectionColumns.count },
45959
+ () => inferredColumnWidthPx
45960
+ );
45961
+ })();
45962
+ const columnSegments = buildRenderColumnSegmentsForPageSection(
45963
+ editor.model,
45964
+ flowSegments,
45965
+ columnWidthsPx,
45966
+ pageBodyAvailableHeightPx,
45967
+ editor.model.metadata.numberingDefinitions,
45968
+ docGridLinePitchPxByNodeIndex,
45969
+ measuredParagraphOuterHeightsPxByNodeIndex,
45970
+ isLastPage
45971
+ );
45972
+ return /* @__PURE__ */ jsxs(Fragment2, { children: [
45973
+ overlaySegments.map((overlaySegment) => {
45974
+ const overlayNode = editor.model.nodes[overlaySegment.nodeIndex];
45975
+ if (!overlayNode) {
45976
+ return null;
45977
+ }
45978
+ return /* @__PURE__ */ jsx(
45979
+ React.Fragment,
45980
+ {
45981
+ children: renderDocumentNode(
45982
+ overlayNode,
45983
+ overlaySegment.nodeIndex,
45984
+ overlaySegment.tableRowRange,
45985
+ overlaySegment.tableRowSlice,
45986
+ overlaySegment.paragraphLineRange,
45987
+ {
45988
+ pageLayout,
45989
+ suppressLikelyFullPageCoverImageKeys: suppressedLikelyFullPageCoverImageKeys
45990
+ }
45991
+ )
45992
+ },
45993
+ `column-layout-overlay-${pageIndex}-${overlaySegment.nodeIndex}-${segmentIdentityKey(
45994
+ overlaySegment
45995
+ )}`
45996
+ );
45997
+ }),
45998
+ /* @__PURE__ */ jsx(
45999
+ "div",
46000
+ {
46001
+ style: {
46002
+ display: "grid",
46003
+ gridTemplateColumns: columnWidthsPx.map((widthPx) => `${widthPx}px`).join(" "),
46004
+ columnGap: sectionColumns.gapPx,
46005
+ alignItems: "start",
46006
+ minHeight: pageBodyAvailableHeightPx,
46007
+ position: "relative",
46008
+ zIndex: 1
46009
+ },
46010
+ children: columnSegments.map(
46011
+ (segmentsForColumn, columnIndex) => /* @__PURE__ */ jsx(
46012
+ "div",
46013
+ {
46014
+ style: {
46015
+ minHeight: pageBodyAvailableHeightPx
46016
+ },
46017
+ children: segmentsForColumn.map(
46018
+ (segment) => renderSegmentInColumn(
46019
+ segment,
46020
+ columnWidthsPx[columnIndex]
46021
+ )
46022
+ )
46023
+ },
46024
+ `column-layout-flow-${pageIndex}-${groupIndex}-${columnIndex}`
46025
+ )
46026
+ )
46027
+ }
46028
+ )
46029
+ ] });
46030
+ })() : explicitColumnWidthsPx && explicitColumnWidthsPx.length === 2 && flowSegments.length > 0 ? (() => {
45180
46031
  const [leftColumnWidthPx, rightColumnWidthPx] = explicitColumnWidthsPx;
45181
46032
  const prefixHeightsPx = new Array(
45182
46033
  flowSegments.length + 1
@@ -47490,6 +48341,7 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
47490
48341
  );
47491
48342
  }
47492
48343
  let rowStartIndex = 0;
48344
+ let tableBreakStartRowCursor = 0;
47493
48345
  while (rowStartIndex < estimatedRowHeightsPx.length) {
47494
48346
  const remainingHeightPx = Math.max(0, currentPageContentHeightPx - pageConsumedHeightPx);
47495
48347
  const fittedRowEndIndex = fitTableRowsWithinHeightPx2(
@@ -47501,9 +48353,10 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
47501
48353
  pageOverflowTolerancePx
47502
48354
  );
47503
48355
  let rowEndIndex = fittedRowEndIndex;
47504
- const forcedBreakRowIndex = tableBreakStartRows.find(
47505
- (breakRowIndex) => breakRowIndex > rowStartIndex
47506
- );
48356
+ while (tableBreakStartRowCursor < tableBreakStartRows.length && tableBreakStartRows[tableBreakStartRowCursor] <= rowStartIndex) {
48357
+ tableBreakStartRowCursor += 1;
48358
+ }
48359
+ const forcedBreakRowIndex = tableBreakStartRows[tableBreakStartRowCursor];
47507
48360
  if (forcedBreakRowIndex !== void 0) {
47508
48361
  rowEndIndex = Math.min(rowEndIndex, forcedBreakRowIndex);
47509
48362
  }