superdoc 1.0.0-beta.15 → 1.0.0-beta.16

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.
Files changed (27) hide show
  1. package/dist/chunks/{PdfViewer-DltPlBWC.cjs → PdfViewer-93eWvs8z.cjs} +1 -1
  2. package/dist/chunks/{PdfViewer-CjlHzt9e.es.js → PdfViewer-ODeuH1gb.es.js} +1 -1
  3. package/dist/chunks/{index-qg0AxQJC.es.js → index-DW5_UKLM.es.js} +3 -3
  4. package/dist/chunks/{index-Bds7gW4r-Pk_xAuWe.es.js → index-DexFffM7-Cbdy0Zy6.es.js} +1 -1
  5. package/dist/chunks/{index-Bds7gW4r-JPDW6c39.cjs → index-DexFffM7-XZD_g6eY.cjs} +1 -1
  6. package/dist/chunks/{index-BZnlco_f.cjs → index-RquHXtgI.cjs} +3 -3
  7. package/dist/chunks/{super-editor.es-CuAhqbzW.cjs → super-editor.es-BLKWkx5G.cjs} +1223 -131
  8. package/dist/chunks/{super-editor.es-CQTkj_nb.es.js → super-editor.es-Dg5uoFkw.es.js} +1223 -131
  9. package/dist/super-editor/ai-writer.es.js +2 -2
  10. package/dist/super-editor/chunks/{converter-qMoZOGGn.js → converter-C_R_BK8X.js} +1 -1
  11. package/dist/super-editor/chunks/{docx-zipper-QKiyORxV.js → docx-zipper-BvQAYmi1.js} +1 -1
  12. package/dist/super-editor/chunks/{editor-D8ZdjC2V.js → editor-DFFvalb1.js} +1224 -132
  13. package/dist/super-editor/chunks/{index-Bds7gW4r.js → index-DexFffM7.js} +1 -1
  14. package/dist/super-editor/chunks/{toolbar-Spi7vpev.js → toolbar-DLPfegtw.js} +2 -2
  15. package/dist/super-editor/converter.es.js +1 -1
  16. package/dist/super-editor/docx-zipper.es.js +2 -2
  17. package/dist/super-editor/editor.es.js +3 -3
  18. package/dist/super-editor/file-zipper.es.js +1 -1
  19. package/dist/super-editor/super-editor.es.js +6 -6
  20. package/dist/super-editor/toolbar.es.js +2 -2
  21. package/dist/super-editor.cjs +1 -1
  22. package/dist/super-editor.es.js +1 -1
  23. package/dist/superdoc.cjs +2 -2
  24. package/dist/superdoc.es.js +2 -2
  25. package/dist/superdoc.umd.js +1225 -133
  26. package/dist/superdoc.umd.js.map +1 -1
  27. package/package.json +1 -1
@@ -36266,7 +36266,7 @@ const _SuperConverter = class _SuperConverter2 {
36266
36266
  static getStoredSuperdocVersion(docx) {
36267
36267
  return _SuperConverter2.getStoredCustomProperty(docx, "SuperdocVersion");
36268
36268
  }
36269
- static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.15") {
36269
+ static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.16") {
36270
36270
  return _SuperConverter2.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
36271
36271
  }
36272
36272
  /**
@@ -52994,7 +52994,7 @@ const isHeadless = (editor) => {
52994
52994
  const shouldSkipNodeView = (editor) => {
52995
52995
  return isHeadless(editor);
52996
52996
  };
52997
- const summaryVersion = "1.0.0-beta.15";
52997
+ const summaryVersion = "1.0.0-beta.16";
52998
52998
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
52999
52999
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
53000
53000
  function mapAttributes(attrs) {
@@ -53773,7 +53773,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
53773
53773
  { default: remarkStringify },
53774
53774
  { default: remarkGfm }
53775
53775
  ] = await Promise.all([
53776
- Promise.resolve().then(() => require("./index-Bds7gW4r-JPDW6c39.cjs")),
53776
+ Promise.resolve().then(() => require("./index-DexFffM7-XZD_g6eY.cjs")),
53777
53777
  Promise.resolve().then(() => require("./index-DRCvimau-H4Ck3S9a.cjs")),
53778
53778
  Promise.resolve().then(() => require("./index-C_x_N6Uh-Db3CUJMX.cjs")),
53779
53779
  Promise.resolve().then(() => require("./index-D_sWOSiG-BtDZzJ6I.cjs")),
@@ -53978,7 +53978,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
53978
53978
  * Process collaboration migrations
53979
53979
  */
53980
53980
  processCollaborationMigrations() {
53981
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.15");
53981
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.16");
53982
53982
  if (!this.options.ydoc) return;
53983
53983
  const metaMap = this.options.ydoc.getMap("meta");
53984
53984
  let docVersion = metaMap.get("version");
@@ -55053,7 +55053,7 @@ const pickLang = (value) => {
55053
55053
  const normalized = value.trim().toLowerCase();
55054
55054
  return normalized || void 0;
55055
55055
  };
55056
- const normalizeColor = (value) => {
55056
+ const normalizeColor$1 = (value) => {
55057
55057
  if (typeof value !== "string") return void 0;
55058
55058
  const trimmed = value.trim();
55059
55059
  if (!trimmed || trimmed === "auto" || trimmed === "none") return void 0;
@@ -55693,14 +55693,14 @@ const resolveThemeColor = (attrs, themeColors) => {
55693
55693
  const resolveColorFromAttributes = (attrs, themeColors) => {
55694
55694
  if (!attrs) return void 0;
55695
55695
  if (typeof attrs.color === "string") {
55696
- const normalized = normalizeColor(attrs.color);
55696
+ const normalized = normalizeColor$1(attrs.color);
55697
55697
  if (normalized) {
55698
55698
  return normalized;
55699
55699
  }
55700
55700
  }
55701
55701
  const theme = resolveThemeColor(attrs, themeColors);
55702
55702
  if (theme) {
55703
- return normalizeColor(theme);
55703
+ return normalizeColor$1(theme);
55704
55704
  }
55705
55705
  return void 0;
55706
55706
  };
@@ -56135,13 +56135,8 @@ const MAX_BORDER_SIZE_PX = 100;
56135
56135
  const borderSizeToPx = (size2) => {
56136
56136
  if (!isFiniteNumber(size2)) return void 0;
56137
56137
  if (size2 <= 0) return 0;
56138
- let pixelValue;
56139
- if (size2 < EIGHTHS_PER_POINT) {
56140
- pixelValue = size2;
56141
- } else {
56142
- const points = size2 / EIGHTHS_PER_POINT;
56143
- pixelValue = points * PX_PER_PT;
56144
- }
56138
+ const points = size2 / EIGHTHS_PER_POINT;
56139
+ const pixelValue = points * PX_PER_PT;
56145
56140
  return Math.min(MAX_BORDER_SIZE_PX, Math.max(MIN_BORDER_SIZE_PX, pixelValue));
56146
56141
  };
56147
56142
  const normalizeColorWithDefault = (color) => {
@@ -56280,7 +56275,7 @@ const normalizeBorderSide = (value) => {
56280
56275
  if (style2 === "none") return void 0;
56281
56276
  const width = pickNumber(raw.size);
56282
56277
  const widthPx = borderSizeToPx(width);
56283
- const color = normalizeColor(raw.color);
56278
+ const color = normalizeColor$1(raw.color);
56284
56279
  const space = pickNumber(raw.space);
56285
56280
  if (!style2 && widthPx == null && space == null && !color) {
56286
56281
  return void 0;
@@ -56336,7 +56331,7 @@ const normalizeParagraphShading = (value) => {
56336
56331
  return Object.keys(shading).length > 0 ? shading : void 0;
56337
56332
  };
56338
56333
  const normalizeShadingColor = (value) => {
56339
- const normalized = normalizeColor(value);
56334
+ const normalized = normalizeColor$1(value);
56340
56335
  if (!normalized) return void 0;
56341
56336
  if (normalized.toLowerCase() === "#auto") {
56342
56337
  return void 0;
@@ -57499,11 +57494,11 @@ const buildMarkerLayout = ({
57499
57494
  baselineOffsetPx: markerRun.baselineShift ?? 0,
57500
57495
  gutterWidthPx: markerBoxWidthPx,
57501
57496
  justification: numbering.lvlJc ?? "left",
57502
- suffix: normalizeSuffix(numbering.suffix) ?? "tab",
57497
+ suffix: normalizeSuffix$1(numbering.suffix) ?? "tab",
57503
57498
  run: markerRun,
57504
57499
  path: numbering.path
57505
57500
  });
57506
- const normalizeSuffix = (suffix2) => {
57501
+ const normalizeSuffix$1 = (suffix2) => {
57507
57502
  if (suffix2 === "tab" || suffix2 === "space" || suffix2 === "nothing") {
57508
57503
  return suffix2;
57509
57504
  }
@@ -57957,6 +57952,154 @@ const cloneIfObject = (value) => {
57957
57952
  };
57958
57953
  const { resolveSpacingIndent } = Engines;
57959
57954
  const DEFAULT_DECIMAL_SEPARATOR$2 = ".";
57955
+ const asOoxmlElement = (value) => {
57956
+ if (!value || typeof value !== "object") return void 0;
57957
+ const element = value;
57958
+ if (element.name == null && element.attributes == null && element.elements == null) return void 0;
57959
+ return element;
57960
+ };
57961
+ const findChild = (parent, name) => {
57962
+ return parent?.elements?.find((child) => child?.name === name);
57963
+ };
57964
+ const getAttribute = (element, key2) => {
57965
+ if (!element?.attributes) return void 0;
57966
+ const attrs = element.attributes;
57967
+ return attrs[key2] ?? attrs[key2.startsWith("w:") ? key2.slice(2) : `w:${key2}`];
57968
+ };
57969
+ const parseNumberAttr = (value) => {
57970
+ if (value == null) return void 0;
57971
+ const num = typeof value === "number" ? value : Number.parseInt(String(value), 10);
57972
+ return Number.isFinite(num) ? num : void 0;
57973
+ };
57974
+ const normalizeNumFmt = (value) => {
57975
+ if (typeof value !== "string") return void 0;
57976
+ switch (value) {
57977
+ case "decimal":
57978
+ return "decimal";
57979
+ case "lowerLetter":
57980
+ return "lowerLetter";
57981
+ case "upperLetter":
57982
+ return "upperLetter";
57983
+ case "lowerRoman":
57984
+ return "lowerRoman";
57985
+ case "upperRoman":
57986
+ return "upperRoman";
57987
+ case "bullet":
57988
+ return "bullet";
57989
+ default:
57990
+ return void 0;
57991
+ }
57992
+ };
57993
+ const normalizeSuffix = (value) => {
57994
+ if (typeof value !== "string") return void 0;
57995
+ if (value === "tab" || value === "space" || value === "nothing") {
57996
+ return value;
57997
+ }
57998
+ return void 0;
57999
+ };
58000
+ const normalizeJustification = (value) => {
58001
+ if (typeof value !== "string") return void 0;
58002
+ if (value === "start") return "left";
58003
+ if (value === "end") return "right";
58004
+ if (value === "left" || value === "center" || value === "right") return value;
58005
+ return void 0;
58006
+ };
58007
+ const extractIndentFromLevel = (lvl) => {
58008
+ const pPr = findChild(lvl, "w:pPr");
58009
+ const ind = findChild(pPr, "w:ind");
58010
+ if (!ind) return void 0;
58011
+ const left2 = parseNumberAttr(getAttribute(ind, "w:left"));
58012
+ const right2 = parseNumberAttr(getAttribute(ind, "w:right"));
58013
+ const firstLine = parseNumberAttr(getAttribute(ind, "w:firstLine"));
58014
+ const hanging = parseNumberAttr(getAttribute(ind, "w:hanging"));
58015
+ const indent = {};
58016
+ if (left2 != null) indent.left = left2;
58017
+ if (right2 != null) indent.right = right2;
58018
+ if (firstLine != null) indent.firstLine = firstLine;
58019
+ if (hanging != null) indent.hanging = hanging;
58020
+ return Object.keys(indent).length ? indent : void 0;
58021
+ };
58022
+ const normalizeColor = (value) => {
58023
+ if (typeof value !== "string") return void 0;
58024
+ const trimmed = value.trim();
58025
+ if (!trimmed || trimmed.toLowerCase() === "auto") return void 0;
58026
+ const upper = trimmed.startsWith("#") ? trimmed.slice(1) : trimmed;
58027
+ return `#${upper.toUpperCase()}`;
58028
+ };
58029
+ const extractMarkerRun = (lvl) => {
58030
+ const rPr = findChild(lvl, "w:rPr");
58031
+ if (!rPr) return void 0;
58032
+ const run2 = {};
58033
+ const rFonts = findChild(rPr, "w:rFonts");
58034
+ const font = getAttribute(rFonts, "w:ascii") ?? getAttribute(rFonts, "w:hAnsi") ?? getAttribute(rFonts, "w:eastAsia");
58035
+ if (typeof font === "string" && font.trim()) {
58036
+ run2.fontFamily = font;
58037
+ }
58038
+ const sz = parseNumberAttr(getAttribute(findChild(rPr, "w:sz"), "w:val")) ?? parseNumberAttr(getAttribute(findChild(rPr, "w:szCs"), "w:val"));
58039
+ if (sz != null) {
58040
+ run2.fontSize = sz / 2;
58041
+ }
58042
+ const color = normalizeColor(getAttribute(findChild(rPr, "w:color"), "w:val"));
58043
+ if (color) run2.color = color;
58044
+ if (findChild(rPr, "w:b")) run2.bold = true;
58045
+ if (findChild(rPr, "w:i")) run2.italic = true;
58046
+ const spacingTwips = parseNumberAttr(getAttribute(findChild(rPr, "w:spacing"), "w:val"));
58047
+ if (spacingTwips != null && Number.isFinite(spacingTwips)) {
58048
+ run2.letterSpacing = twipsToPx$1(spacingTwips);
58049
+ }
58050
+ return Object.keys(run2).length ? run2 : void 0;
58051
+ };
58052
+ const findNumFmtElement = (lvl) => {
58053
+ if (!lvl) return void 0;
58054
+ const direct = findChild(lvl, "w:numFmt");
58055
+ if (direct) return direct;
58056
+ const alternate = findChild(lvl, "mc:AlternateContent");
58057
+ const choice = findChild(alternate, "mc:Choice");
58058
+ if (choice) {
58059
+ return findChild(choice, "w:numFmt");
58060
+ }
58061
+ return void 0;
58062
+ };
58063
+ const resolveNumberingFromContext = (numId, ilvl, numbering) => {
58064
+ const definitions = numbering?.definitions;
58065
+ const abstracts = numbering?.abstracts;
58066
+ if (!definitions || !abstracts) return void 0;
58067
+ const numDef = asOoxmlElement(definitions[String(numId)]);
58068
+ if (!numDef) return void 0;
58069
+ const abstractId = getAttribute(findChild(numDef, "w:abstractNumId"), "w:val");
58070
+ if (abstractId == null) return void 0;
58071
+ const abstract = asOoxmlElement(abstracts[String(abstractId)]);
58072
+ if (!abstract) return void 0;
58073
+ let levelDef = abstract.elements?.find(
58074
+ (el) => el?.name === "w:lvl" && parseNumberAttr(el.attributes?.["w:ilvl"]) === ilvl
58075
+ );
58076
+ const override = numDef.elements?.find(
58077
+ (el) => el?.name === "w:lvlOverride" && parseNumberAttr(el.attributes?.["w:ilvl"]) === ilvl
58078
+ );
58079
+ const overrideLvl = findChild(override, "w:lvl");
58080
+ if (overrideLvl) {
58081
+ levelDef = overrideLvl;
58082
+ }
58083
+ const startOverride = parseNumberAttr(getAttribute(findChild(override, "w:startOverride"), "w:val"));
58084
+ if (!levelDef) return void 0;
58085
+ const numFmtEl = findNumFmtElement(levelDef);
58086
+ const lvlText = getAttribute(findChild(levelDef, "w:lvlText"), "w:val");
58087
+ const start2 = startOverride ?? parseNumberAttr(getAttribute(findChild(levelDef, "w:start"), "w:val"));
58088
+ const suffix2 = normalizeSuffix(getAttribute(findChild(levelDef, "w:suff"), "w:val"));
58089
+ const lvlJc = normalizeJustification(getAttribute(findChild(levelDef, "w:lvlJc"), "w:val"));
58090
+ const indent = extractIndentFromLevel(levelDef);
58091
+ const markerRun = extractMarkerRun(levelDef);
58092
+ const numFmt = normalizeNumFmt(getAttribute(numFmtEl, "w:val"));
58093
+ return {
58094
+ format: numFmt,
58095
+ lvlText,
58096
+ start: start2,
58097
+ suffix: suffix2,
58098
+ lvlJc,
58099
+ resolvedLevelIndent: indent,
58100
+ resolvedMarkerRpr: markerRun
58101
+ };
58102
+ };
57960
58103
  const isTruthy = (value) => {
57961
58104
  if (value === true || value === 1) return true;
57962
58105
  if (typeof value === "string") {
@@ -58589,6 +58732,30 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
58589
58732
  const ilvl = Number.isFinite(numberingProps.ilvl) ? Math.max(0, Math.floor(Number(numberingProps.ilvl))) : 0;
58590
58733
  const listRendering = normalizeListRenderingAttrs(attrs.listRendering);
58591
58734
  const numericNumId = typeof numId === "number" ? numId : void 0;
58735
+ const resolvedLevel = resolveNumberingFromContext(numId, ilvl, converterContext?.numbering);
58736
+ if (resolvedLevel) {
58737
+ if (resolvedLevel.format && numberingProps.format == null) {
58738
+ numberingProps.format = resolvedLevel.format;
58739
+ }
58740
+ if (resolvedLevel.lvlText && numberingProps.lvlText == null) {
58741
+ numberingProps.lvlText = resolvedLevel.lvlText;
58742
+ }
58743
+ if (resolvedLevel.start != null && numberingProps.start == null) {
58744
+ numberingProps.start = resolvedLevel.start;
58745
+ }
58746
+ if (resolvedLevel.suffix && numberingProps.suffix == null) {
58747
+ numberingProps.suffix = resolvedLevel.suffix;
58748
+ }
58749
+ if (resolvedLevel.lvlJc && numberingProps.lvlJc == null) {
58750
+ numberingProps.lvlJc = resolvedLevel.lvlJc;
58751
+ }
58752
+ if (resolvedLevel.resolvedLevelIndent && !numberingProps.resolvedLevelIndent) {
58753
+ numberingProps.resolvedLevelIndent = resolvedLevel.resolvedLevelIndent;
58754
+ }
58755
+ if (resolvedLevel.resolvedMarkerRpr && !numberingProps.resolvedMarkerRpr) {
58756
+ numberingProps.resolvedMarkerRpr = resolvedLevel.resolvedMarkerRpr;
58757
+ }
58758
+ }
58592
58759
  let counterValue = 1;
58593
58760
  if (listCounterContext && typeof numericNumId === "number") {
58594
58761
  counterValue = listCounterContext.incrementListCounter(numericNumId, ilvl);
@@ -59814,41 +59981,45 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
59814
59981
  }
59815
59982
  return;
59816
59983
  }
59817
- if (node.type === "hardBreak") {
59818
- flushParagraph();
59819
- blocks.push({
59820
- kind: "pageBreak",
59821
- id: nextId(),
59822
- attrs: node.attrs || {}
59823
- });
59824
- return;
59825
- }
59826
- if (node.type === "lineBreak") {
59984
+ if (node.type === "hardBreak" || node.type === "lineBreak") {
59827
59985
  const attrs = node.attrs ?? {};
59828
- if (attrs.lineBreakType === "column") {
59986
+ const breakType = attrs.pageBreakType ?? attrs.lineBreakType ?? "line";
59987
+ if (breakType === "page") {
59988
+ flushParagraph();
59989
+ blocks.push({
59990
+ kind: "pageBreak",
59991
+ id: nextId(),
59992
+ attrs: node.attrs || {}
59993
+ });
59994
+ return;
59995
+ }
59996
+ if (breakType === "column") {
59829
59997
  flushParagraph();
59830
59998
  blocks.push({
59831
59999
  kind: "columnBreak",
59832
60000
  id: nextId(),
59833
60001
  attrs: node.attrs || {}
59834
60002
  });
60003
+ return;
60004
+ }
60005
+ const lineBreakRun = { kind: "lineBreak", attrs: {} };
60006
+ const lbAttrs = {};
60007
+ if (attrs.lineBreakType) lbAttrs.lineBreakType = String(attrs.lineBreakType);
60008
+ if (attrs.clear) lbAttrs.clear = String(attrs.clear);
60009
+ if (Object.keys(lbAttrs).length > 0) {
60010
+ lineBreakRun.attrs = lbAttrs;
59835
60011
  } else {
59836
- const lineBreakRun = { kind: "lineBreak", attrs: {} };
59837
- const lbAttrs = {};
59838
- if (attrs.lineBreakType) lbAttrs.lineBreakType = String(attrs.lineBreakType);
59839
- if (attrs.clear) lbAttrs.clear = String(attrs.clear);
59840
- if (Object.keys(lbAttrs).length > 0) {
59841
- lineBreakRun.attrs = lbAttrs;
59842
- } else {
59843
- delete lineBreakRun.attrs;
59844
- }
59845
- const pos = positions.get(node);
59846
- if (pos) {
59847
- lineBreakRun.pmStart = pos.start;
59848
- lineBreakRun.pmEnd = pos.end;
59849
- }
59850
- currentRuns.push(lineBreakRun);
60012
+ delete lineBreakRun.attrs;
60013
+ }
60014
+ const pos = positions.get(node);
60015
+ if (pos) {
60016
+ lineBreakRun.pmStart = pos.start;
60017
+ lineBreakRun.pmEnd = pos.end;
59851
60018
  }
60019
+ if (activeSdt) {
60020
+ lineBreakRun.sdt = activeSdt;
60021
+ }
60022
+ currentRuns.push(lineBreakRun);
59852
60023
  return;
59853
60024
  }
59854
60025
  };
@@ -60441,6 +60612,22 @@ const normalizeTableWidth = (value) => {
60441
60612
  };
60442
60613
  const isTableRowNode = (node) => node.type === "tableRow" || node.type === "table_row";
60443
60614
  const isTableCellNode = (node) => node.type === "tableCell" || node.type === "table_cell" || node.type === "tableHeader" || node.type === "table_header";
60615
+ const normalizeRowHeight = (rowProps) => {
60616
+ if (!rowProps || typeof rowProps !== "object") return void 0;
60617
+ const rawRowHeight = rowProps.rowHeight;
60618
+ if (!rawRowHeight || typeof rawRowHeight !== "object") return void 0;
60619
+ const heightObj = rawRowHeight;
60620
+ const rawValue = pickNumber(heightObj.value ?? heightObj.val);
60621
+ if (rawValue == null) return void 0;
60622
+ const rawRule = heightObj.rule ?? heightObj.hRule;
60623
+ const rule = rawRule === "exact" || rawRule === "atLeast" || rawRule === "auto" ? rawRule : "atLeast";
60624
+ const isLikelyTwips = rawValue >= 300 || Math.abs(rawValue % 15) < 1e-6;
60625
+ const valuePx = isLikelyTwips ? twipsToPx$1(rawValue) : rawValue;
60626
+ return {
60627
+ value: valuePx,
60628
+ rule
60629
+ };
60630
+ };
60444
60631
  const parseTableCell = (args) => {
60445
60632
  const { cellNode, rowIndex, cellIndex, context, defaultCellPadding } = args;
60446
60633
  if (!isTableCellNode(cellNode) || !Array.isArray(cellNode.content)) {
@@ -60478,8 +60665,9 @@ const parseTableCell = (args) => {
60478
60665
  const padding = extractCellPadding(cellNode.attrs ?? {}) ?? (defaultCellPadding ? { ...defaultCellPadding } : void 0);
60479
60666
  if (padding) cellAttrs.padding = padding;
60480
60667
  const verticalAlign = cellNode.attrs?.verticalAlign;
60481
- if (verticalAlign === "top" || verticalAlign === "middle" || verticalAlign === "bottom") {
60482
- cellAttrs.verticalAlign = verticalAlign;
60668
+ const normalizedVerticalAlign = verticalAlign === "middle" ? "center" : verticalAlign === "center" ? "center" : verticalAlign;
60669
+ if (normalizedVerticalAlign === "top" || normalizedVerticalAlign === "center" || normalizedVerticalAlign === "bottom") {
60670
+ cellAttrs.verticalAlign = normalizedVerticalAlign;
60483
60671
  }
60484
60672
  const background = cellNode.attrs?.background;
60485
60673
  if (background && typeof background.color === "string") {
@@ -60522,15 +60710,89 @@ const parseTableRow = (args) => {
60522
60710
  });
60523
60711
  if (cells.length === 0) return null;
60524
60712
  const rowProps = rowNode.attrs?.tableRowProperties;
60713
+ const rowHeight = normalizeRowHeight(rowProps);
60525
60714
  const attrs = rowProps && typeof rowProps === "object" ? {
60526
- tableRowProperties: rowProps
60527
- } : void 0;
60715
+ tableRowProperties: rowProps,
60716
+ ...rowHeight ? { rowHeight } : {}
60717
+ } : rowHeight ? { rowHeight } : void 0;
60528
60718
  return {
60529
60719
  id: context.nextBlockId(`row-${rowIndex}`),
60530
60720
  cells,
60531
60721
  attrs
60532
60722
  };
60533
60723
  };
60724
+ function extractFloatingTableAnchorWrap(node) {
60725
+ const tableProperties = node.attrs?.tableProperties;
60726
+ const floatingProps = tableProperties?.floatingTableProperties;
60727
+ if (!floatingProps) {
60728
+ return {};
60729
+ }
60730
+ const hasPositioning = floatingProps.tblpX !== void 0 || floatingProps.tblpY !== void 0 || floatingProps.tblpXSpec !== void 0 || floatingProps.tblpYSpec !== void 0 || floatingProps.horzAnchor !== void 0 || floatingProps.vertAnchor !== void 0;
60731
+ if (!hasPositioning) {
60732
+ return {};
60733
+ }
60734
+ const mapHorzAnchor = (val) => {
60735
+ switch (val) {
60736
+ case "page":
60737
+ return "page";
60738
+ case "margin":
60739
+ return "margin";
60740
+ case "text":
60741
+ default:
60742
+ return "column";
60743
+ }
60744
+ };
60745
+ const mapVertAnchor = (val) => {
60746
+ switch (val) {
60747
+ case "page":
60748
+ return "page";
60749
+ case "margin":
60750
+ return "margin";
60751
+ case "text":
60752
+ default:
60753
+ return "paragraph";
60754
+ }
60755
+ };
60756
+ const anchor = {
60757
+ isAnchored: true,
60758
+ hRelativeFrom: mapHorzAnchor(floatingProps.horzAnchor),
60759
+ vRelativeFrom: mapVertAnchor(floatingProps.vertAnchor)
60760
+ };
60761
+ if (floatingProps.tblpXSpec) {
60762
+ anchor.alignH = floatingProps.tblpXSpec;
60763
+ }
60764
+ if (floatingProps.tblpYSpec) {
60765
+ anchor.alignV = floatingProps.tblpYSpec;
60766
+ }
60767
+ if (floatingProps.tblpX !== void 0) {
60768
+ anchor.offsetH = twipsToPx$1(floatingProps.tblpX);
60769
+ }
60770
+ if (floatingProps.tblpY !== void 0) {
60771
+ anchor.offsetV = twipsToPx$1(floatingProps.tblpY);
60772
+ }
60773
+ const hasDistances = floatingProps.leftFromText !== void 0 || floatingProps.rightFromText !== void 0 || floatingProps.topFromText !== void 0 || floatingProps.bottomFromText !== void 0;
60774
+ const wrap2 = {
60775
+ type: "Square",
60776
+ // Floating tables with text distances use square wrapping
60777
+ wrapText: "bothSides"
60778
+ // Default to text on both sides
60779
+ };
60780
+ if (hasDistances) {
60781
+ if (floatingProps.topFromText !== void 0) {
60782
+ wrap2.distTop = twipsToPx$1(floatingProps.topFromText);
60783
+ }
60784
+ if (floatingProps.bottomFromText !== void 0) {
60785
+ wrap2.distBottom = twipsToPx$1(floatingProps.bottomFromText);
60786
+ }
60787
+ if (floatingProps.leftFromText !== void 0) {
60788
+ wrap2.distLeft = twipsToPx$1(floatingProps.leftFromText);
60789
+ }
60790
+ if (floatingProps.rightFromText !== void 0) {
60791
+ wrap2.distRight = twipsToPx$1(floatingProps.rightFromText);
60792
+ }
60793
+ }
60794
+ return { anchor, wrap: wrap2 };
60795
+ }
60534
60796
  function tableNodeToBlock$1(node, nextBlockId, positions, defaultFont, defaultSize, _styleContext, trackedChanges, bookmarks, hyperlinkConfig, themeColors, paragraphToFlowBlocks2, converterContext) {
60535
60797
  if (!Array.isArray(node.content) || node.content.length === 0) return null;
60536
60798
  if (!paragraphToFlowBlocks2) return null;
@@ -60595,6 +60857,10 @@ function tableNodeToBlock$1(node, nextBlockId, positions, defaultFont, defaultSi
60595
60857
  if (tableLayout) {
60596
60858
  tableAttrs.tableLayout = tableLayout;
60597
60859
  }
60860
+ const tableProperties = node.attrs?.tableProperties;
60861
+ if (tableProperties && typeof tableProperties === "object") {
60862
+ tableAttrs.tableProperties = tableProperties;
60863
+ }
60598
60864
  let columnWidths = void 0;
60599
60865
  const twipsToPixels2 = (twips) => {
60600
60866
  const PIXELS_PER_INCH2 = 96;
@@ -60638,12 +60904,15 @@ function tableNodeToBlock$1(node, nextBlockId, positions, defaultFont, defaultSi
60638
60904
  columnWidths = void 0;
60639
60905
  }
60640
60906
  }
60907
+ const { anchor, wrap: wrap2 } = extractFloatingTableAnchorWrap(node);
60641
60908
  const tableBlock = {
60642
60909
  kind: "table",
60643
60910
  id: nextBlockId("table"),
60644
60911
  rows,
60645
60912
  attrs: Object.keys(tableAttrs).length > 0 ? tableAttrs : void 0,
60646
- columnWidths
60913
+ columnWidths,
60914
+ ...anchor ? { anchor } : {},
60915
+ ...wrap2 ? { wrap: wrap2 } : {}
60647
60916
  };
60648
60917
  return tableBlock;
60649
60918
  }
@@ -60979,7 +61248,7 @@ function getMeasurementContext() {
60979
61248
  return measurementCtx;
60980
61249
  }
60981
61250
  function getRunFontString(run2) {
60982
- if (run2.kind === "tab" || run2.kind === "lineBreak" || "src" in run2) {
61251
+ if (run2.kind === "tab" || run2.kind === "lineBreak" || run2.kind === "break" || "src" in run2) {
60983
61252
  return "normal normal 16px Arial";
60984
61253
  }
60985
61254
  const style2 = run2.italic ? "italic" : "normal";
@@ -61006,6 +61275,10 @@ function sliceRunsForLine$1(block, line) {
61006
61275
  result.push(run2);
61007
61276
  continue;
61008
61277
  }
61278
+ if (run2.kind === "break") {
61279
+ result.push(run2);
61280
+ continue;
61281
+ }
61009
61282
  const text = run2.text ?? "";
61010
61283
  const isFirstRun = runIndex === line.fromRun;
61011
61284
  const isLastRun = runIndex === line.toRun;
@@ -61039,7 +61312,7 @@ function measureCharacterX(block, line, charOffset) {
61039
61312
  1,
61040
61313
  runs2.reduce((sum, run2) => {
61041
61314
  if (isTabRun$1(run2)) return sum + TAB_CHAR_LENGTH;
61042
- if ("src" in run2 || run2.kind === "lineBreak") return sum;
61315
+ if ("src" in run2 || run2.kind === "lineBreak" || run2.kind === "break") return sum;
61043
61316
  return sum + (run2.text ?? "").length;
61044
61317
  }, 0)
61045
61318
  );
@@ -61060,7 +61333,7 @@ function measureCharacterX(block, line, charOffset) {
61060
61333
  currentCharOffset += runLength2;
61061
61334
  continue;
61062
61335
  }
61063
- const text = "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
61336
+ const text = "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" ? "" : run2.text ?? "";
61064
61337
  const runLength = text.length;
61065
61338
  if (currentCharOffset + runLength >= charOffset) {
61066
61339
  const offsetInRun = charOffset - currentCharOffset;
@@ -61103,7 +61376,7 @@ function measureCharacterXSegmentBased(block, line, charOffset, ctx2) {
61103
61376
  if (isTabRun$1(run2)) {
61104
61377
  return segmentBaseX + (offsetInSegment > 0 ? segment.width ?? 0 : 0);
61105
61378
  }
61106
- if ("src" in run2 || run2.kind === "lineBreak") {
61379
+ if ("src" in run2 || run2.kind === "lineBreak" || run2.kind === "break") {
61107
61380
  return segmentBaseX + (offsetInSegment >= segmentChars ? segment.width ?? 0 : 0);
61108
61381
  }
61109
61382
  const text = run2.text ?? "";
@@ -61126,7 +61399,7 @@ function findCharacterAtX(block, line, x2, pmStart) {
61126
61399
  1,
61127
61400
  runs2.reduce((sum, run2) => {
61128
61401
  if (isTabRun$1(run2)) return sum + TAB_CHAR_LENGTH;
61129
- if ("src" in run2 || run2.kind === "lineBreak") return sum;
61402
+ if ("src" in run2 || run2.kind === "lineBreak" || run2.kind === "break") return sum;
61130
61403
  return sum + (run2.text ?? "").length;
61131
61404
  }, 0)
61132
61405
  );
@@ -61161,7 +61434,7 @@ function findCharacterAtX(block, line, x2, pmStart) {
61161
61434
  currentCharOffset += TAB_CHAR_LENGTH;
61162
61435
  continue;
61163
61436
  }
61164
- const text = "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
61437
+ const text = "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" ? "" : run2.text ?? "";
61165
61438
  const runLength = text.length;
61166
61439
  if (runLength === 0) continue;
61167
61440
  ctx2.font = getRunFontString(run2);
@@ -61594,6 +61867,40 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
61594
61867
  };
61595
61868
  zones.push(zone);
61596
61869
  },
61870
+ registerTable(tableBlock, measure, anchorY, columnIndex, pageNumber) {
61871
+ if (!tableBlock.anchor?.isAnchored) {
61872
+ return;
61873
+ }
61874
+ const { wrap: wrap2, anchor } = tableBlock;
61875
+ const wrapType = wrap2?.type ?? "None";
61876
+ if (wrapType === "None") {
61877
+ return;
61878
+ }
61879
+ const tableWidth = measure.totalWidth ?? 0;
61880
+ const tableHeight = measure.totalHeight ?? 0;
61881
+ const x2 = computeTableAnchorX(anchor, columnIndex, columns, tableWidth, margins, pageWidth);
61882
+ const y2 = anchorY + (anchor.offsetV ?? 0);
61883
+ const zone = {
61884
+ imageBlockId: tableBlock.id,
61885
+ // Reusing imageBlockId field for table id
61886
+ pageNumber,
61887
+ columnIndex,
61888
+ bounds: {
61889
+ x: x2,
61890
+ y: y2,
61891
+ width: tableWidth,
61892
+ height: tableHeight
61893
+ },
61894
+ distances: {
61895
+ top: wrap2?.distTop ?? 0,
61896
+ bottom: wrap2?.distBottom ?? 0,
61897
+ left: wrap2?.distLeft ?? 0,
61898
+ right: wrap2?.distRight ?? 0
61899
+ },
61900
+ wrapMode: computeTableWrapMode(wrap2)
61901
+ };
61902
+ zones.push(zone);
61903
+ },
61597
61904
  getExclusionsForLine(lineY, lineHeight2, columnIndex, pageNumber) {
61598
61905
  const result = zones.filter((zone) => {
61599
61906
  if (zone.pageNumber !== pageNumber || zone.columnIndex !== columnIndex) {
@@ -61701,6 +62008,49 @@ function computeWrapMode(wrap2, _anchor) {
61701
62008
  if (wrapText === "largest") return "largest";
61702
62009
  return "both";
61703
62010
  }
62011
+ function computeTableAnchorX(anchor, columnIndex, columns, tableWidth, margins, pageWidth) {
62012
+ const alignH = anchor.alignH ?? "left";
62013
+ const offsetH = anchor.offsetH ?? 0;
62014
+ const marginLeft = Math.max(0, margins?.left ?? 0);
62015
+ const marginRight = Math.max(0, margins?.right ?? 0);
62016
+ const contentWidth = pageWidth != null ? Math.max(1, pageWidth - (marginLeft + marginRight)) : columns.width;
62017
+ const contentLeft = marginLeft;
62018
+ const columnLeft = contentLeft + columnIndex * (columns.width + columns.gap);
62019
+ const relativeFrom = anchor.hRelativeFrom ?? "column";
62020
+ let baseX;
62021
+ let availableWidth;
62022
+ if (relativeFrom === "page") {
62023
+ if (columns.count === 1) {
62024
+ baseX = contentLeft;
62025
+ availableWidth = contentWidth;
62026
+ } else {
62027
+ baseX = 0;
62028
+ availableWidth = pageWidth != null ? pageWidth : contentWidth;
62029
+ }
62030
+ } else if (relativeFrom === "margin") {
62031
+ baseX = contentLeft;
62032
+ availableWidth = contentWidth;
62033
+ } else {
62034
+ baseX = columnLeft;
62035
+ availableWidth = columns.width;
62036
+ }
62037
+ let effectiveAlignH = alignH;
62038
+ if (alignH === "inside") effectiveAlignH = "left";
62039
+ if (alignH === "outside") effectiveAlignH = "right";
62040
+ const result = effectiveAlignH === "left" ? baseX + offsetH : effectiveAlignH === "right" ? baseX + availableWidth - tableWidth - offsetH : effectiveAlignH === "center" ? baseX + (availableWidth - tableWidth) / 2 + offsetH : baseX;
62041
+ return result;
62042
+ }
62043
+ function computeTableWrapMode(wrap2) {
62044
+ if (!wrap2) return "none";
62045
+ if (wrap2.type === "None") {
62046
+ return "none";
62047
+ }
62048
+ const wrapText = wrap2.wrapText ?? "bothSides";
62049
+ if (wrapText === "left") return "right";
62050
+ if (wrapText === "right") return "left";
62051
+ if (wrapText === "largest") return "largest";
62052
+ return "both";
62053
+ }
61704
62054
  function computeNextSectionPropsAtBreak(blocks) {
61705
62055
  const nextSectionPropsAtBreak = /* @__PURE__ */ new Map();
61706
62056
  const docxBreakIndexes = [];
@@ -62397,6 +62747,206 @@ function generateColumnBoundaries(measure) {
62397
62747
  }
62398
62748
  return boundaries;
62399
62749
  }
62750
+ function countHeaderRows(block) {
62751
+ let count = 0;
62752
+ for (let i = 0; i < block.rows.length; i++) {
62753
+ const row = block.rows[i];
62754
+ const repeatHeader = row.attrs?.tableRowProperties?.repeatHeader;
62755
+ if (repeatHeader === true) {
62756
+ count++;
62757
+ } else {
62758
+ break;
62759
+ }
62760
+ }
62761
+ return count;
62762
+ }
62763
+ function sumRowHeights(rows, fromRow, toRow) {
62764
+ let total = 0;
62765
+ for (let i = fromRow; i < toRow && i < rows.length; i++) {
62766
+ total += rows[i].height;
62767
+ }
62768
+ return total;
62769
+ }
62770
+ function calculateFragmentHeight(fragment, measure, _headerCount) {
62771
+ let height = 0;
62772
+ if (fragment.repeatHeaderCount && fragment.repeatHeaderCount > 0) {
62773
+ height += sumRowHeights(measure.rows, 0, fragment.repeatHeaderCount);
62774
+ }
62775
+ height += sumRowHeights(measure.rows, fragment.fromRow, fragment.toRow);
62776
+ return height;
62777
+ }
62778
+ const MIN_PARTIAL_ROW_HEIGHT = 20;
62779
+ function getCellLines(cell) {
62780
+ if (cell.blocks && cell.blocks.length > 0) {
62781
+ const allLines = [];
62782
+ for (const block of cell.blocks) {
62783
+ if (block.kind === "paragraph") {
62784
+ if (block.kind === "paragraph" && "lines" in block) {
62785
+ const paraBlock = block;
62786
+ if (paraBlock.lines) {
62787
+ allLines.push(...paraBlock.lines);
62788
+ }
62789
+ }
62790
+ }
62791
+ }
62792
+ return allLines;
62793
+ }
62794
+ if (cell.paragraph?.lines) {
62795
+ return cell.paragraph.lines;
62796
+ }
62797
+ return [];
62798
+ }
62799
+ function getCellPadding(cellIdx, blockRow) {
62800
+ const padding = blockRow?.cells?.[cellIdx]?.attrs?.padding ?? {};
62801
+ return {
62802
+ top: padding.top ?? 2,
62803
+ bottom: padding.bottom ?? 2,
62804
+ left: padding.left ?? 4,
62805
+ right: padding.right ?? 4
62806
+ };
62807
+ }
62808
+ function getCellTotalLines(cell) {
62809
+ return getCellLines(cell).length;
62810
+ }
62811
+ function computePartialRow(rowIndex, blockRow, measure, availableHeight, fromLineByCell) {
62812
+ const row = measure.rows[rowIndex];
62813
+ if (!row) {
62814
+ throw new Error(`Invalid rowIndex ${rowIndex}: measure.rows has ${measure.rows.length} rows`);
62815
+ }
62816
+ const cellCount = row.cells.length;
62817
+ const startLines = fromLineByCell || new Array(cellCount).fill(0);
62818
+ const toLineByCell = [];
62819
+ const heightByCell = [];
62820
+ const cellPaddings = row.cells.map((_2, idx) => getCellPadding(idx, blockRow));
62821
+ for (let cellIdx = 0; cellIdx < cellCount; cellIdx++) {
62822
+ const cell = row.cells[cellIdx];
62823
+ const startLine = startLines[cellIdx] || 0;
62824
+ const cellPadding = cellPaddings[cellIdx];
62825
+ const availableForLines = Math.max(0, availableHeight - (cellPadding.top + cellPadding.bottom));
62826
+ const lines = getCellLines(cell);
62827
+ let cumulativeHeight = 0;
62828
+ let cutLine = startLine;
62829
+ for (let i = startLine; i < lines.length; i++) {
62830
+ const lineHeight2 = lines[i].lineHeight || 0;
62831
+ if (cumulativeHeight + lineHeight2 > availableForLines) {
62832
+ break;
62833
+ }
62834
+ cumulativeHeight += lineHeight2;
62835
+ cutLine = i + 1;
62836
+ }
62837
+ toLineByCell.push(cutLine);
62838
+ heightByCell.push(cumulativeHeight);
62839
+ }
62840
+ const positiveHeights = heightByCell.filter((h) => h > 0);
62841
+ const minHeight = positiveHeights.length > 0 ? Math.min(...positiveHeights) : 0;
62842
+ let actualPartialHeight = 0;
62843
+ let maxPaddingTotal = 0;
62844
+ for (let cellIdx = 0; cellIdx < cellCount; cellIdx++) {
62845
+ const cell = row.cells[cellIdx];
62846
+ const startLine = startLines[cellIdx] || 0;
62847
+ const lines = getCellLines(cell);
62848
+ const cellPadding = cellPaddings[cellIdx];
62849
+ const paddingTotal = cellPadding.top + cellPadding.bottom;
62850
+ maxPaddingTotal = Math.max(maxPaddingTotal, paddingTotal);
62851
+ let cumulativeHeight = 0;
62852
+ let cutLine = startLine;
62853
+ for (let i = startLine; i < lines.length; i++) {
62854
+ const lineHeight2 = lines[i].lineHeight || 0;
62855
+ if (cumulativeHeight + lineHeight2 > minHeight) {
62856
+ break;
62857
+ }
62858
+ cumulativeHeight += lineHeight2;
62859
+ cutLine = i + 1;
62860
+ }
62861
+ toLineByCell[cellIdx] = cutLine;
62862
+ actualPartialHeight = Math.max(actualPartialHeight, cumulativeHeight + paddingTotal);
62863
+ }
62864
+ const madeProgress = toLineByCell.some((cutLine, idx) => cutLine > (startLines[idx] || 0));
62865
+ const isFirstPart = startLines.every((l3) => l3 === 0);
62866
+ const allCellsExhausted = toLineByCell.every((cutLine, idx) => {
62867
+ const totalLines = getCellTotalLines(row.cells[idx]);
62868
+ return cutLine >= totalLines;
62869
+ });
62870
+ const isLastPart = allCellsExhausted || !madeProgress;
62871
+ if (actualPartialHeight === 0 && isFirstPart) {
62872
+ actualPartialHeight = maxPaddingTotal;
62873
+ }
62874
+ return {
62875
+ rowIndex,
62876
+ fromLineByCell: startLines,
62877
+ toLineByCell,
62878
+ isFirstPart,
62879
+ isLastPart,
62880
+ partialHeight: actualPartialHeight
62881
+ };
62882
+ }
62883
+ function findSplitPoint(block, measure, startRow, availableHeight, fullPageHeight, _pendingPartialRow) {
62884
+ let accumulatedHeight = 0;
62885
+ let lastFitRow = startRow;
62886
+ for (let i = startRow; i < block.rows.length; i++) {
62887
+ const row = block.rows[i];
62888
+ const rowHeight = measure.rows[i]?.height || 0;
62889
+ const cantSplit = row.attrs?.tableRowProperties?.cantSplit === true;
62890
+ if (accumulatedHeight + rowHeight <= availableHeight) {
62891
+ accumulatedHeight += rowHeight;
62892
+ lastFitRow = i + 1;
62893
+ } else {
62894
+ const remainingHeight = availableHeight - accumulatedHeight;
62895
+ if (fullPageHeight && rowHeight > fullPageHeight) {
62896
+ const partialRow = computePartialRow(i, block.rows[i], measure, remainingHeight);
62897
+ return { endRow: i + 1, partialRow };
62898
+ }
62899
+ if (cantSplit) {
62900
+ if (lastFitRow === startRow) {
62901
+ return { endRow: startRow, partialRow: null };
62902
+ }
62903
+ return { endRow: lastFitRow, partialRow: null };
62904
+ }
62905
+ if (remainingHeight >= MIN_PARTIAL_ROW_HEIGHT) {
62906
+ const partialRow = computePartialRow(i, block.rows[i], measure, remainingHeight);
62907
+ const hasContent = partialRow.toLineByCell.some(
62908
+ (cutLine, idx) => cutLine > (partialRow.fromLineByCell[idx] || 0)
62909
+ );
62910
+ if (hasContent) {
62911
+ return { endRow: i + 1, partialRow };
62912
+ }
62913
+ }
62914
+ return { endRow: lastFitRow, partialRow: null };
62915
+ }
62916
+ }
62917
+ return { endRow: block.rows.length, partialRow: null };
62918
+ }
62919
+ function generateFragmentMetadata(measure, _fromRow, _toRow, _repeatHeaderCount) {
62920
+ return {
62921
+ columnBoundaries: generateColumnBoundaries(measure),
62922
+ coordinateSystem: "fragment"
62923
+ };
62924
+ }
62925
+ function layoutMonolithicTable(context) {
62926
+ let state2 = context.ensurePage();
62927
+ if (state2.cursorY + context.measure.totalHeight > state2.contentBottom && state2.page.fragments.length > 0) {
62928
+ state2 = context.advanceColumn(state2);
62929
+ }
62930
+ state2 = context.ensurePage();
62931
+ const height = Math.min(context.measure.totalHeight, state2.contentBottom - state2.cursorY);
62932
+ const metadata = {
62933
+ columnBoundaries: generateColumnBoundaries(context.measure),
62934
+ coordinateSystem: "fragment"
62935
+ };
62936
+ const fragment = {
62937
+ kind: "table",
62938
+ blockId: context.block.id,
62939
+ fromRow: 0,
62940
+ toRow: context.block.rows.length,
62941
+ x: context.columnX(state2.columnIndex),
62942
+ y: state2.cursorY,
62943
+ width: Math.min(context.columnWidth, context.measure.totalWidth || context.columnWidth),
62944
+ height,
62945
+ metadata
62946
+ };
62947
+ state2.page.fragments.push(fragment);
62948
+ state2.cursorY += height;
62949
+ }
62400
62950
  function layoutTableBlock({
62401
62951
  block,
62402
62952
  measure,
@@ -62405,30 +62955,176 @@ function layoutTableBlock({
62405
62955
  advanceColumn,
62406
62956
  columnX
62407
62957
  }) {
62958
+ if (block.anchor?.isAnchored) {
62959
+ return;
62960
+ }
62961
+ const tableProps = block.attrs?.tableProperties;
62962
+ const floatingProps = tableProps?.floatingTableProperties;
62963
+ if (floatingProps && Object.keys(floatingProps).length > 0) {
62964
+ layoutMonolithicTable({ block, measure, columnWidth, ensurePage, advanceColumn, columnX });
62965
+ return;
62966
+ }
62967
+ const headerCount = countHeaderRows(block);
62968
+ const headerHeight = headerCount > 0 ? sumRowHeights(measure.rows, 0, headerCount) : 0;
62408
62969
  let state2 = ensurePage();
62409
- if (state2.cursorY + measure.totalHeight > state2.contentBottom && state2.page.fragments.length > 0) {
62410
- state2 = advanceColumn(state2);
62970
+ let currentRow = 0;
62971
+ let isTableContinuation = false;
62972
+ let pendingPartialRow = null;
62973
+ while (currentRow < block.rows.length || pendingPartialRow !== null) {
62974
+ state2 = ensurePage();
62975
+ const availableHeight = state2.contentBottom - state2.cursorY;
62976
+ let repeatHeaderCount = 0;
62977
+ if (currentRow === 0 && !pendingPartialRow) {
62978
+ repeatHeaderCount = 0;
62979
+ } else {
62980
+ if (headerCount > 0 && headerHeight <= availableHeight) {
62981
+ repeatHeaderCount = headerCount;
62982
+ } else if (headerCount > 0 && headerHeight > availableHeight) {
62983
+ repeatHeaderCount = 0;
62984
+ }
62985
+ }
62986
+ const availableForBody = repeatHeaderCount > 0 ? availableHeight - headerHeight : availableHeight;
62987
+ const fullPageHeight = state2.contentBottom;
62988
+ if (pendingPartialRow !== null) {
62989
+ const rowIndex = pendingPartialRow.rowIndex;
62990
+ const fromLineByCell = pendingPartialRow.toLineByCell;
62991
+ const continuationPartialRow = computePartialRow(
62992
+ rowIndex,
62993
+ block.rows[rowIndex],
62994
+ measure,
62995
+ availableForBody,
62996
+ fromLineByCell
62997
+ );
62998
+ const madeProgress = continuationPartialRow.toLineByCell.some(
62999
+ (toLine, idx) => toLine > (fromLineByCell[idx] || 0)
63000
+ );
63001
+ const hasRemainingLinesAfterContinuation = continuationPartialRow.toLineByCell.some(
63002
+ (toLine, idx) => {
63003
+ const totalLines = getCellTotalLines(measure.rows[rowIndex].cells[idx]);
63004
+ return toLine < totalLines;
63005
+ }
63006
+ );
63007
+ const hadRemainingLinesBefore = fromLineByCell.some((fromLine, idx) => {
63008
+ const totalLines = getCellTotalLines(measure.rows[rowIndex].cells[idx]);
63009
+ return fromLine < totalLines;
63010
+ });
63011
+ const fragmentHeight2 = continuationPartialRow.partialHeight + (repeatHeaderCount > 0 ? headerHeight : 0);
63012
+ if (fragmentHeight2 > 0) {
63013
+ const fragment2 = {
63014
+ kind: "table",
63015
+ blockId: block.id,
63016
+ fromRow: rowIndex,
63017
+ toRow: rowIndex + 1,
63018
+ x: columnX(state2.columnIndex),
63019
+ y: state2.cursorY,
63020
+ width: Math.min(columnWidth, measure.totalWidth || columnWidth),
63021
+ height: fragmentHeight2,
63022
+ continuesFromPrev: true,
63023
+ continuesOnNext: hasRemainingLinesAfterContinuation || rowIndex + 1 < block.rows.length,
63024
+ repeatHeaderCount,
63025
+ partialRow: continuationPartialRow,
63026
+ metadata: generateFragmentMetadata(measure)
63027
+ };
63028
+ state2.page.fragments.push(fragment2);
63029
+ state2.cursorY += fragmentHeight2;
63030
+ }
63031
+ const rowComplete = !hasRemainingLinesAfterContinuation;
63032
+ if (rowComplete) {
63033
+ currentRow = rowIndex + 1;
63034
+ pendingPartialRow = null;
63035
+ } else if (!madeProgress && hadRemainingLinesBefore) {
63036
+ state2 = advanceColumn(state2);
63037
+ } else {
63038
+ state2 = advanceColumn(state2);
63039
+ pendingPartialRow = continuationPartialRow;
63040
+ }
63041
+ isTableContinuation = true;
63042
+ continue;
63043
+ }
63044
+ const bodyStartRow = currentRow;
63045
+ const { endRow, partialRow } = findSplitPoint(block, measure, bodyStartRow, availableForBody, fullPageHeight);
63046
+ if (endRow === bodyStartRow && partialRow === null && state2.page.fragments.length > 0) {
63047
+ state2 = advanceColumn(state2);
63048
+ continue;
63049
+ }
63050
+ if (endRow === bodyStartRow && partialRow === null) {
63051
+ const forcedPartialRow = computePartialRow(bodyStartRow, block.rows[bodyStartRow], measure, availableForBody);
63052
+ const forcedEndRow = bodyStartRow + 1;
63053
+ const fragmentHeight2 = forcedPartialRow.partialHeight + (repeatHeaderCount > 0 ? headerHeight : 0);
63054
+ const fragment2 = {
63055
+ kind: "table",
63056
+ blockId: block.id,
63057
+ fromRow: bodyStartRow,
63058
+ toRow: forcedEndRow,
63059
+ x: columnX(state2.columnIndex),
63060
+ y: state2.cursorY,
63061
+ width: Math.min(columnWidth, measure.totalWidth || columnWidth),
63062
+ height: fragmentHeight2,
63063
+ continuesFromPrev: isTableContinuation,
63064
+ continuesOnNext: !forcedPartialRow.isLastPart || forcedEndRow < block.rows.length,
63065
+ repeatHeaderCount,
63066
+ partialRow: forcedPartialRow,
63067
+ metadata: generateFragmentMetadata(measure)
63068
+ };
63069
+ state2.page.fragments.push(fragment2);
63070
+ state2.cursorY += fragmentHeight2;
63071
+ pendingPartialRow = forcedPartialRow;
63072
+ isTableContinuation = true;
63073
+ continue;
63074
+ }
63075
+ let fragmentHeight;
63076
+ if (partialRow) {
63077
+ const fullRowsHeight = sumRowHeights(measure.rows, bodyStartRow, endRow - 1);
63078
+ fragmentHeight = fullRowsHeight + partialRow.partialHeight + (repeatHeaderCount > 0 ? headerHeight : 0);
63079
+ } else {
63080
+ fragmentHeight = calculateFragmentHeight(
63081
+ { fromRow: bodyStartRow, toRow: endRow, repeatHeaderCount },
63082
+ measure
63083
+ );
63084
+ }
63085
+ const fragment = {
63086
+ kind: "table",
63087
+ blockId: block.id,
63088
+ fromRow: bodyStartRow,
63089
+ toRow: endRow,
63090
+ x: columnX(state2.columnIndex),
63091
+ y: state2.cursorY,
63092
+ width: Math.min(columnWidth, measure.totalWidth || columnWidth),
63093
+ height: fragmentHeight,
63094
+ continuesFromPrev: isTableContinuation,
63095
+ continuesOnNext: endRow < block.rows.length || (partialRow ? !partialRow.isLastPart : false),
63096
+ repeatHeaderCount,
63097
+ partialRow: partialRow || void 0,
63098
+ metadata: generateFragmentMetadata(measure)
63099
+ };
63100
+ state2.page.fragments.push(fragment);
63101
+ state2.cursorY += fragmentHeight;
63102
+ if (partialRow && !partialRow.isLastPart) {
63103
+ pendingPartialRow = partialRow;
63104
+ currentRow = partialRow.rowIndex;
63105
+ } else {
63106
+ currentRow = endRow;
63107
+ pendingPartialRow = null;
63108
+ }
63109
+ isTableContinuation = true;
62411
63110
  }
62412
- state2 = ensurePage();
62413
- const height = Math.min(measure.totalHeight, state2.contentBottom - state2.cursorY);
63111
+ }
63112
+ function createAnchoredTableFragment(block, measure, x2, y2) {
62414
63113
  const metadata = {
62415
63114
  columnBoundaries: generateColumnBoundaries(measure),
62416
63115
  coordinateSystem: "fragment"
62417
- // rowBoundaries omitted - not needed for column resize, reduces DOM overhead
62418
63116
  };
62419
- const fragment = {
63117
+ return {
62420
63118
  kind: "table",
62421
63119
  blockId: block.id,
62422
63120
  fromRow: 0,
62423
63121
  toRow: block.rows.length,
62424
- x: columnX(state2.columnIndex),
62425
- y: state2.cursorY,
62426
- width: Math.min(columnWidth, measure.totalWidth || columnWidth),
62427
- height,
63122
+ x: x2,
63123
+ y: y2,
63124
+ width: measure.totalWidth ?? 0,
63125
+ height: measure.totalHeight ?? 0,
62428
63126
  metadata
62429
63127
  };
62430
- state2.page.fragments.push(fragment);
62431
- state2.cursorY += height;
62432
63128
  }
62433
63129
  function isPageRelativeAnchor(block) {
62434
63130
  const vRelativeFrom = block.anchor?.vRelativeFrom;
@@ -62455,9 +63151,6 @@ function collectPreRegisteredAnchors(blocks, measures) {
62455
63151
  function collectAnchoredDrawings(blocks, measures) {
62456
63152
  const map22 = /* @__PURE__ */ new Map();
62457
63153
  const len = Math.min(blocks.length, measures.length);
62458
- for (let i = 0; i < len; i += 1) {
62459
- if (blocks[i].kind === "paragraph") ;
62460
- }
62461
63154
  const nearestPrevParagraph = (fromIndex) => {
62462
63155
  for (let i = fromIndex - 1; i >= 0; i -= 1) {
62463
63156
  if (blocks[i].kind === "paragraph") return i;
@@ -62493,6 +63186,36 @@ function collectAnchoredDrawings(blocks, measures) {
62493
63186
  }
62494
63187
  return map22;
62495
63188
  }
63189
+ function collectAnchoredTables(blocks, measures) {
63190
+ const map22 = /* @__PURE__ */ new Map();
63191
+ const nearestPrevParagraph = (fromIndex) => {
63192
+ for (let i = fromIndex - 1; i >= 0; i -= 1) {
63193
+ if (blocks[i].kind === "paragraph") return i;
63194
+ }
63195
+ return null;
63196
+ };
63197
+ const nearestNextParagraph = (fromIndex) => {
63198
+ for (let i = fromIndex + 1; i < blocks.length; i += 1) {
63199
+ if (blocks[i].kind === "paragraph") return i;
63200
+ }
63201
+ return null;
63202
+ };
63203
+ for (let i = 0; i < blocks.length; i += 1) {
63204
+ const block = blocks[i];
63205
+ const measure = measures[i];
63206
+ if (block.kind !== "table" || measure?.kind !== "table") continue;
63207
+ const tableBlock = block;
63208
+ const tableMeasure = measure;
63209
+ if (!tableBlock.anchor?.isAnchored) continue;
63210
+ let anchorParaIndex = nearestPrevParagraph(i);
63211
+ if (anchorParaIndex == null) anchorParaIndex = nearestNextParagraph(i);
63212
+ if (anchorParaIndex == null) continue;
63213
+ const list = map22.get(anchorParaIndex) ?? [];
63214
+ list.push({ block: tableBlock, measure: tableMeasure });
63215
+ map22.set(anchorParaIndex, list);
63216
+ }
63217
+ return map22;
63218
+ }
62496
63219
  function createPaginator(opts) {
62497
63220
  const states = [];
62498
63221
  const pages = [];
@@ -63078,7 +63801,9 @@ function layoutDocument(blocks, measures, options = {}) {
63078
63801
  cachedColumnsState.state = null;
63079
63802
  };
63080
63803
  const anchoredByParagraph = collectAnchoredDrawings(blocks, measures);
63804
+ const anchoredTablesByParagraph = collectAnchoredTables(blocks, measures);
63081
63805
  const placedAnchoredIds = /* @__PURE__ */ new Set();
63806
+ const placedAnchoredTableIds = /* @__PURE__ */ new Set();
63082
63807
  const preRegisteredAnchors = collectPreRegisteredAnchors(blocks, measures);
63083
63808
  const preRegisteredPositions = /* @__PURE__ */ new Map();
63084
63809
  for (const entry of preRegisteredAnchors) {
@@ -63256,6 +63981,19 @@ function layoutDocument(blocks, measures, options = {}) {
63256
63981
  }
63257
63982
  }
63258
63983
  const anchorsForPara = anchoredByParagraph.get(index2);
63984
+ const tablesForPara = anchoredTablesByParagraph.get(index2);
63985
+ if (tablesForPara) {
63986
+ const state2 = paginator.ensurePage();
63987
+ for (const { block: tableBlock, measure: tableMeasure } of tablesForPara) {
63988
+ if (placedAnchoredTableIds.has(tableBlock.id)) continue;
63989
+ floatManager.registerTable(tableBlock, tableMeasure, state2.cursorY, state2.columnIndex, state2.page.number);
63990
+ const anchorX = tableBlock.anchor?.offsetH ?? columnX(state2.columnIndex);
63991
+ const anchorY = state2.cursorY + (tableBlock.anchor?.offsetV ?? 0);
63992
+ const tableFragment = createAnchoredTableFragment(tableBlock, tableMeasure, anchorX, anchorY);
63993
+ state2.page.fragments.push(tableFragment);
63994
+ placedAnchoredTableIds.add(tableBlock.id);
63995
+ }
63996
+ }
63259
63997
  layoutParagraphBlock(
63260
63998
  {
63261
63999
  block,
@@ -63527,7 +64265,9 @@ const hashRuns = (block) => {
63527
64265
  const trackedMode = block.attrs && "trackedChangesMode" in block.attrs && block.attrs.trackedChangesMode || "review";
63528
64266
  const trackedEnabled = resolveTrackedChangesEnabled(block.attrs, true);
63529
64267
  const runsHash = block.runs.map((run2) => {
63530
- const text = normalizeText("src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "");
64268
+ const text = normalizeText(
64269
+ "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" ? "" : run2.text ?? ""
64270
+ );
63531
64271
  const bold = "bold" in run2 ? run2.bold : false;
63532
64272
  const italic = "italic" in run2 ? run2.italic : false;
63533
64273
  const color = "color" in run2 ? run2.color : void 0;
@@ -64187,7 +64927,7 @@ function fontString(run2) {
64187
64927
  return `${italic}${bold}${size2}px ${family}`.trim();
64188
64928
  }
64189
64929
  function runText(run2) {
64190
- return "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
64930
+ return "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" ? "" : run2.text ?? "";
64191
64931
  }
64192
64932
  function measureRunSliceWidth(run2, fromChar, toChar) {
64193
64933
  const context = getCtx();
@@ -64349,7 +65089,7 @@ const paragraphBlocksEqual = (a, b2) => {
64349
65089
  for (let i = 0; i < a.runs.length; i += 1) {
64350
65090
  const runA = a.runs[i];
64351
65091
  const runB = b2.runs[i];
64352
- if (("src" in runA || runA.kind === "lineBreak" ? "" : runA.text) !== ("src" in runB || runB.kind === "lineBreak" ? "" : runB.text) || ("bold" in runA ? runA.bold : false) !== ("bold" in runB ? runB.bold : false) || ("italic" in runA ? runA.italic : false) !== ("italic" in runB ? runB.italic : false) || ("color" in runA ? runA.color : void 0) !== ("color" in runB ? runB.color : void 0) || getTrackedChangeKey(runA) !== getTrackedChangeKey(runB)) {
65092
+ if (("src" in runA || runA.kind === "lineBreak" || runA.kind === "break" ? "" : runA.text) !== ("src" in runB || runB.kind === "lineBreak" || runB.kind === "break" ? "" : runB.text) || ("bold" in runA ? runA.bold : false) !== ("bold" in runB ? runB.bold : false) || ("italic" in runA ? runA.italic : false) !== ("italic" in runB ? runB.italic : false) || ("color" in runA ? runA.color : void 0) !== ("color" in runB ? runB.color : void 0) || getTrackedChangeKey(runA) !== getTrackedChangeKey(runB)) {
64353
65093
  return false;
64354
65094
  }
64355
65095
  }
@@ -64469,7 +65209,7 @@ function computeHeaderFooterContentHash(blocks) {
64469
65209
  parts.push(block.id);
64470
65210
  if (block.kind === "paragraph") {
64471
65211
  for (const run2 of block.runs) {
64472
- if (!("src" in run2) && run2.kind !== "lineBreak") {
65212
+ if (!("src" in run2) && run2.kind !== "lineBreak" && run2.kind !== "break") {
64473
65213
  parts.push(run2.text ?? "");
64474
65214
  }
64475
65215
  if ("bold" in run2 && run2.bold) parts.push("b");
@@ -65440,7 +66180,7 @@ function computeLinePmRange$1(block, line) {
65440
66180
  for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
65441
66181
  const run2 = block.runs[runIndex];
65442
66182
  if (!run2) continue;
65443
- const text = "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
66183
+ const text = "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" ? "" : run2.text ?? "";
65444
66184
  const runLength = text.length;
65445
66185
  const runPmStart = run2.pmStart ?? null;
65446
66186
  const runPmEnd = run2.pmEnd ?? (runPmStart != null ? runPmStart + runLength : null);
@@ -68048,7 +68788,20 @@ const resolveTableCellBorders = (tableBorders, rowIndex, colIndex, totalRows, to
68048
68788
  };
68049
68789
  };
68050
68790
  const renderTableCell = (deps) => {
68051
- const { doc: doc2, x: x2, y: y2, rowHeight, cellMeasure, cell, borders, renderLine, context, applySdtDataset } = deps;
68791
+ const {
68792
+ doc: doc2,
68793
+ x: x2,
68794
+ y: y2,
68795
+ rowHeight,
68796
+ cellMeasure,
68797
+ cell,
68798
+ borders,
68799
+ renderLine,
68800
+ context,
68801
+ applySdtDataset,
68802
+ fromLine,
68803
+ toLine
68804
+ } = deps;
68052
68805
  const cellEl = doc2.createElement("div");
68053
68806
  cellEl.style.position = "absolute";
68054
68807
  cellEl.style.left = `${x2}px`;
@@ -68056,6 +68809,7 @@ const renderTableCell = (deps) => {
68056
68809
  cellEl.style.width = `${cellMeasure.width}px`;
68057
68810
  cellEl.style.height = `${rowHeight}px`;
68058
68811
  cellEl.style.boxSizing = "border-box";
68812
+ cellEl.style.overflow = "hidden";
68059
68813
  if (borders) {
68060
68814
  applyCellBorders(cellEl, borders);
68061
68815
  }
@@ -68069,36 +68823,87 @@ const renderTableCell = (deps) => {
68069
68823
  }
68070
68824
  let contentElement;
68071
68825
  const attrs = cell?.attrs;
68072
- const padding = attrs?.padding || { top: 2, left: 4, right: 4 };
68826
+ const padding = attrs?.padding || { top: 2, left: 4, right: 4, bottom: 2 };
68073
68827
  const paddingLeft = padding.left ?? 4;
68074
68828
  const paddingTop = padding.top ?? 2;
68075
68829
  const paddingRight = padding.right ?? 4;
68830
+ const paddingBottom = padding.bottom ?? 2;
68076
68831
  const cellBlocks = cell?.blocks ?? (cell?.paragraph ? [cell.paragraph] : []);
68077
- const blockMeasures = cellMeasure.blocks ?? (cellMeasure.paragraph ? [cellMeasure.paragraph] : []);
68832
+ const blockMeasures = cellMeasure?.blocks ?? (cellMeasure?.paragraph ? [cellMeasure.paragraph] : []);
68078
68833
  if (cellBlocks.length > 0 && blockMeasures.length > 0) {
68079
68834
  const content = doc2.createElement("div");
68080
68835
  content.style.position = "absolute";
68081
68836
  content.style.left = `${x2 + paddingLeft}px`;
68082
68837
  content.style.top = `${y2 + paddingTop}px`;
68083
- content.style.width = `${Math.max(0, cellMeasure.width - paddingLeft - paddingRight)}px`;
68084
- let blockY = 0;
68838
+ const contentWidth = Math.max(0, cellMeasure.width - paddingLeft - paddingRight);
68839
+ const contentHeight = Math.max(0, rowHeight - paddingTop - paddingBottom);
68840
+ content.style.width = `${contentWidth + 1}px`;
68841
+ content.style.height = `${contentHeight}px`;
68842
+ content.style.display = "flex";
68843
+ content.style.flexDirection = "column";
68844
+ content.style.overflowX = "visible";
68845
+ content.style.overflowY = "hidden";
68846
+ if (cell?.attrs?.verticalAlign === "center") {
68847
+ content.style.justifyContent = "center";
68848
+ } else if (cell?.attrs?.verticalAlign === "bottom") {
68849
+ content.style.justifyContent = "flex-end";
68850
+ } else {
68851
+ content.style.justifyContent = "flex-start";
68852
+ }
68853
+ const blockLineCounts = [];
68854
+ for (let i = 0; i < Math.min(blockMeasures.length, cellBlocks.length); i++) {
68855
+ const bm = blockMeasures[i];
68856
+ if (bm.kind === "paragraph") {
68857
+ blockLineCounts.push(bm.lines?.length || 0);
68858
+ } else {
68859
+ blockLineCounts.push(0);
68860
+ }
68861
+ }
68862
+ const totalLines = blockLineCounts.reduce((a, b2) => a + b2, 0);
68863
+ const globalFromLine = fromLine ?? 0;
68864
+ const globalToLine = toLine === -1 || toLine === void 0 ? totalLines : toLine;
68865
+ let cumulativeLineCount = 0;
68085
68866
  for (let i = 0; i < Math.min(blockMeasures.length, cellBlocks.length); i++) {
68086
68867
  const blockMeasure = blockMeasures[i];
68087
68868
  const block = cellBlocks[i];
68088
68869
  if (blockMeasure.kind === "paragraph" && block?.kind === "paragraph") {
68870
+ const lines = blockMeasure.lines;
68871
+ const blockLineCount = lines?.length || 0;
68872
+ const blockStartGlobal = cumulativeLineCount;
68873
+ const blockEndGlobal = cumulativeLineCount + blockLineCount;
68874
+ if (blockEndGlobal <= globalFromLine) {
68875
+ cumulativeLineCount += blockLineCount;
68876
+ continue;
68877
+ }
68878
+ if (blockStartGlobal >= globalToLine) {
68879
+ cumulativeLineCount += blockLineCount;
68880
+ continue;
68881
+ }
68882
+ const localStartLine = Math.max(0, globalFromLine - blockStartGlobal);
68883
+ const localEndLine = Math.min(blockLineCount, globalToLine - blockStartGlobal);
68089
68884
  const paraWrapper = doc2.createElement("div");
68090
- paraWrapper.style.position = "absolute";
68091
- paraWrapper.style.top = `${blockY}px`;
68885
+ paraWrapper.style.position = "relative";
68092
68886
  paraWrapper.style.left = "0";
68093
68887
  paraWrapper.style.width = "100%";
68094
68888
  applySdtDataset(paraWrapper, block.attrs?.sdt);
68095
- const lines = blockMeasure.lines;
68096
- lines.forEach((line) => {
68889
+ let renderedHeight = 0;
68890
+ for (let lineIdx = localStartLine; lineIdx < localEndLine && lineIdx < lines.length; lineIdx++) {
68891
+ const line = lines[lineIdx];
68097
68892
  const lineEl = renderLine(block, line, { ...context, section: "body" });
68098
68893
  paraWrapper.appendChild(lineEl);
68099
- });
68894
+ renderedHeight += line.lineHeight;
68895
+ }
68896
+ const renderedEntireBlock = localStartLine === 0 && localEndLine >= blockLineCount;
68897
+ if (renderedEntireBlock && blockMeasure.totalHeight && blockMeasure.totalHeight > renderedHeight) {
68898
+ renderedHeight = blockMeasure.totalHeight;
68899
+ }
68100
68900
  content.appendChild(paraWrapper);
68101
- blockY += blockMeasure.totalHeight;
68901
+ if (renderedHeight > 0) {
68902
+ paraWrapper.style.height = `${renderedHeight}px`;
68903
+ }
68904
+ cumulativeLineCount += blockLineCount;
68905
+ } else {
68906
+ cumulativeLineCount += 0;
68102
68907
  }
68103
68908
  }
68104
68909
  contentElement = content;
@@ -68119,7 +68924,10 @@ const renderTableRow = (deps) => {
68119
68924
  allRowHeights,
68120
68925
  context,
68121
68926
  renderLine,
68122
- applySdtDataset
68927
+ applySdtDataset,
68928
+ continuesFromPrev,
68929
+ continuesOnNext,
68930
+ partialRow
68123
68931
  } = deps;
68124
68932
  const calculateXPosition = (gridColumnStart) => {
68125
68933
  let x2 = 0;
@@ -68152,25 +68960,57 @@ const renderTableRow = (deps) => {
68152
68960
  const isLastRow = rowIndex === totalRows - 1;
68153
68961
  const isFirstCol = gridColIndex === 0;
68154
68962
  const isLastCol = gridColIndex === totalCols - 1;
68963
+ const treatAsFirstRow = isFirstRow || continuesFromPrev;
68964
+ const treatAsLastRow = isLastRow || continuesOnNext;
68155
68965
  resolvedBorders = {
68156
- // For top: use cell's if defined, otherwise use table's top for first row
68157
- top: cellBordersAttr.top ?? borderValueToSpec(isFirstRow ? tableBorders.top : tableBorders.insideH),
68158
- // For bottom: use cell's if defined, otherwise use table's bottom for last row only
68159
- bottom: cellBordersAttr.bottom ?? borderValueToSpec(isLastRow ? tableBorders.bottom : void 0),
68966
+ // For top: use cell's if defined, otherwise use table's top border for first row OR continuation
68967
+ top: cellBordersAttr.top ?? borderValueToSpec(treatAsFirstRow ? tableBorders.top : tableBorders.insideH),
68968
+ // For bottom: use cell's if defined, otherwise use table's bottom border for last row OR before continuation
68969
+ bottom: cellBordersAttr.bottom ?? borderValueToSpec(treatAsLastRow ? tableBorders.bottom : void 0),
68160
68970
  // For left: use cell's if defined, otherwise use table's left for first col
68161
68971
  left: cellBordersAttr.left ?? borderValueToSpec(isFirstCol ? tableBorders.left : tableBorders.insideV),
68162
68972
  // For right: use cell's if defined, otherwise use table's right for last col only
68163
68973
  right: cellBordersAttr.right ?? borderValueToSpec(isLastCol ? tableBorders.right : void 0)
68164
68974
  };
68165
68975
  } else if (hasExplicitBorders) {
68166
- resolvedBorders = cellBordersAttr;
68976
+ resolvedBorders = {
68977
+ top: cellBordersAttr.top,
68978
+ bottom: cellBordersAttr.bottom,
68979
+ left: cellBordersAttr.left,
68980
+ right: cellBordersAttr.right
68981
+ };
68167
68982
  } else if (tableBorders) {
68168
- resolvedBorders = resolveTableCellBorders(tableBorders, rowIndex, gridColIndex, totalRows, totalCols);
68983
+ const isFirstRow = rowIndex === 0;
68984
+ const isLastRow = rowIndex === totalRows - 1;
68985
+ const treatAsFirstRow = isFirstRow || continuesFromPrev;
68986
+ const treatAsLastRow = isLastRow || continuesOnNext;
68987
+ const baseBorders = resolveTableCellBorders(tableBorders, rowIndex, gridColIndex, totalRows, totalCols);
68988
+ if (baseBorders) {
68989
+ resolvedBorders = {
68990
+ // If this is a continuation (continuesFromPrev), use table's top border
68991
+ top: treatAsFirstRow ? borderValueToSpec(tableBorders.top) : baseBorders.top,
68992
+ // If this continues on next (continuesOnNext), use table's bottom border
68993
+ bottom: treatAsLastRow ? borderValueToSpec(tableBorders.bottom) : baseBorders.bottom,
68994
+ left: baseBorders.left,
68995
+ right: baseBorders.right
68996
+ };
68997
+ } else {
68998
+ resolvedBorders = void 0;
68999
+ }
68169
69000
  } else {
68170
69001
  resolvedBorders = void 0;
68171
69002
  }
68172
69003
  const rowSpan = cellMeasure.rowSpan ?? 1;
68173
- const cellHeight = rowSpan > 1 ? calculateRowspanHeight(rowIndex, rowSpan) : rowMeasure.height;
69004
+ let cellHeight;
69005
+ if (partialRow) {
69006
+ cellHeight = partialRow.partialHeight;
69007
+ } else if (rowSpan > 1) {
69008
+ cellHeight = calculateRowspanHeight(rowIndex, rowSpan);
69009
+ } else {
69010
+ cellHeight = rowMeasure.height;
69011
+ }
69012
+ const fromLine = partialRow?.fromLineByCell?.[cellIndex];
69013
+ const toLine = partialRow?.toLineByCell?.[cellIndex];
68174
69014
  const { cellElement, contentElement } = renderTableCell({
68175
69015
  doc: doc2,
68176
69016
  x: x2,
@@ -68181,7 +69021,9 @@ const renderTableRow = (deps) => {
68181
69021
  borders: resolvedBorders,
68182
69022
  renderLine,
68183
69023
  context,
68184
- applySdtDataset
69024
+ applySdtDataset,
69025
+ fromLine,
69026
+ toLine
68185
69027
  });
68186
69028
  container.appendChild(cellElement);
68187
69029
  if (contentElement) {
@@ -68295,11 +69137,46 @@ const renderTableFragment = (deps) => {
68295
69137
  if (borderCollapse === "separate" && block.attrs?.cellSpacing) {
68296
69138
  container.style.borderSpacing = `${block.attrs.cellSpacing}px`;
68297
69139
  }
68298
- const allRowHeights = measure.rows.map((r2) => r2.height);
69140
+ const allRowHeights = measure.rows.map((r2, idx) => {
69141
+ if (fragment.partialRow && fragment.partialRow.rowIndex === idx) {
69142
+ return fragment.partialRow.partialHeight;
69143
+ }
69144
+ return r2?.height ?? 0;
69145
+ });
68299
69146
  let y2 = 0;
69147
+ if (fragment.repeatHeaderCount && fragment.repeatHeaderCount > 0) {
69148
+ for (let r2 = 0; r2 < fragment.repeatHeaderCount; r2 += 1) {
69149
+ const rowMeasure = measure.rows[r2];
69150
+ if (!rowMeasure) break;
69151
+ renderTableRow({
69152
+ doc: doc2,
69153
+ container,
69154
+ rowIndex: r2,
69155
+ y: y2,
69156
+ rowMeasure,
69157
+ row: block.rows[r2],
69158
+ totalRows: block.rows.length,
69159
+ tableBorders,
69160
+ columnWidths: measure.columnWidths,
69161
+ allRowHeights,
69162
+ context,
69163
+ renderLine,
69164
+ applySdtDataset,
69165
+ // Headers are always rendered as-is (no border suppression)
69166
+ continuesFromPrev: false,
69167
+ continuesOnNext: false
69168
+ });
69169
+ y2 += rowMeasure.height;
69170
+ }
69171
+ }
68300
69172
  for (let r2 = fragment.fromRow; r2 < fragment.toRow; r2 += 1) {
68301
69173
  const rowMeasure = measure.rows[r2];
68302
69174
  if (!rowMeasure) break;
69175
+ const isFirstRenderedBodyRow = r2 === fragment.fromRow;
69176
+ const isLastRenderedBodyRow = r2 === fragment.toRow - 1;
69177
+ const isPartialRow = fragment.partialRow && fragment.partialRow.rowIndex === r2;
69178
+ const partialRowData = isPartialRow ? fragment.partialRow : void 0;
69179
+ const actualRowHeight = partialRowData ? partialRowData.partialHeight : rowMeasure.height;
68303
69180
  renderTableRow({
68304
69181
  doc: doc2,
68305
69182
  container,
@@ -68313,9 +69190,15 @@ const renderTableFragment = (deps) => {
68313
69190
  allRowHeights,
68314
69191
  context,
68315
69192
  renderLine,
68316
- applySdtDataset
69193
+ applySdtDataset,
69194
+ // Draw top border if table continues from previous fragment (MS Word behavior)
69195
+ continuesFromPrev: isFirstRenderedBodyRow && fragment.continuesFromPrev === true,
69196
+ // Draw bottom border if table continues on next fragment (MS Word behavior)
69197
+ continuesOnNext: isLastRenderedBodyRow && fragment.continuesOnNext === true,
69198
+ // Pass partial row data for mid-row splits
69199
+ partialRow: partialRowData
68317
69200
  });
68318
- y2 += rowMeasure.height;
69201
+ y2 += actualRowHeight;
68319
69202
  }
68320
69203
  return container;
68321
69204
  };
@@ -70103,6 +70986,12 @@ const _DomPainter = class _DomPainter2 {
70103
70986
  isLineBreakRun(run2) {
70104
70987
  return run2.kind === "lineBreak";
70105
70988
  }
70989
+ /**
70990
+ * Type guard to check if a run is a break run.
70991
+ */
70992
+ isBreakRun(run2) {
70993
+ return run2.kind === "break";
70994
+ }
70106
70995
  renderRun(run2, context, trackedConfig) {
70107
70996
  if (this.isImageRun(run2)) {
70108
70997
  return this.renderImageRun(run2);
@@ -70110,7 +70999,10 @@ const _DomPainter = class _DomPainter2 {
70110
70999
  if (this.isLineBreakRun(run2)) {
70111
71000
  return null;
70112
71001
  }
70113
- if (!run2.text || !this.doc) {
71002
+ if (this.isBreakRun(run2)) {
71003
+ return null;
71004
+ }
71005
+ if (!("text" in run2) || !run2.text || !this.doc) {
70114
71006
  return null;
70115
71007
  }
70116
71008
  const linkData = this.extractLinkData(run2);
@@ -70251,6 +71143,12 @@ const _DomPainter = class _DomPainter2 {
70251
71143
  if (styleId) {
70252
71144
  el.setAttribute("styleid", styleId);
70253
71145
  }
71146
+ const alignment2 = block.attrs?.alignment;
71147
+ if (alignment2 === "center" || alignment2 === "right" || alignment2 === "justify") {
71148
+ el.style.textAlign = alignment2 === "justify" ? "justify" : alignment2;
71149
+ } else {
71150
+ el.style.textAlign = "left";
71151
+ }
70254
71152
  const lineRange = computeLinePmRange(block, line);
70255
71153
  if (lineRange.pmStart != null) {
70256
71154
  el.dataset.pmStart = String(lineRange.pmStart);
@@ -70368,10 +71266,16 @@ const _DomPainter = class _DomPainter2 {
70368
71266
  if (this.isLineBreakRun(baseRun)) {
70369
71267
  continue;
70370
71268
  }
71269
+ if (this.isBreakRun(baseRun)) {
71270
+ continue;
71271
+ }
70371
71272
  const runSegments = segmentsByRun.get(runIndex);
70372
71273
  if (!runSegments || runSegments.length === 0) {
70373
71274
  continue;
70374
71275
  }
71276
+ if (!("text" in baseRun)) {
71277
+ continue;
71278
+ }
70375
71279
  const baseText = baseRun.text ?? "";
70376
71280
  const runPmStart = baseRun.pmStart ?? null;
70377
71281
  const fallbackPmEnd = runPmStart != null && baseRun.pmEnd == null ? runPmStart + baseText.length : baseRun.pmEnd ?? null;
@@ -70690,7 +71594,12 @@ const fragmentKey = (fragment) => {
70690
71594
  if (fragment.kind === "drawing") {
70691
71595
  return `drawing:${fragment.blockId}:${fragment.x}:${fragment.y}`;
70692
71596
  }
70693
- return `${fragment.kind}:${fragment.blockId}`;
71597
+ if (fragment.kind === "table") {
71598
+ const partialKey = fragment.partialRow ? `:${fragment.partialRow.fromLineByCell.join(",")}-${fragment.partialRow.toLineByCell.join(",")}` : "";
71599
+ return `table:${fragment.blockId}:${fragment.fromRow}:${fragment.toRow}${partialKey}`;
71600
+ }
71601
+ const _exhaustiveCheck = fragment;
71602
+ return _exhaustiveCheck;
70694
71603
  };
70695
71604
  const fragmentSignature = (fragment, lookup2) => {
70696
71605
  const base2 = lookup2.get(fragment.blockId)?.version ?? "missing";
@@ -70732,6 +71641,20 @@ const fragmentSignature = (fragment, lookup2) => {
70732
71641
  fragment.zIndex ?? ""
70733
71642
  ].join("|");
70734
71643
  }
71644
+ if (fragment.kind === "table") {
71645
+ const partialSig = fragment.partialRow ? `${fragment.partialRow.fromLineByCell.join(",")}-${fragment.partialRow.toLineByCell.join(",")}-${fragment.partialRow.partialHeight}` : "";
71646
+ return [
71647
+ base2,
71648
+ fragment.fromRow,
71649
+ fragment.toRow,
71650
+ fragment.width,
71651
+ fragment.height,
71652
+ fragment.continuesFromPrev ? 1 : 0,
71653
+ fragment.continuesOnNext ? 1 : 0,
71654
+ fragment.repeatHeaderCount ?? 0,
71655
+ partialSig
71656
+ ].join("|");
71657
+ }
70735
71658
  return base2;
70736
71659
  };
70737
71660
  const deriveBlockVersion = (block) => {
@@ -70877,7 +71800,7 @@ const deriveBlockVersion = (block) => {
70877
71800
  return block.id;
70878
71801
  };
70879
71802
  const applyRunStyles = (element, run2, isLink = false) => {
70880
- if (run2.kind === "tab" || run2.kind === "image" || run2.kind === "lineBreak") {
71803
+ if (run2.kind === "tab" || run2.kind === "image" || run2.kind === "lineBreak" || run2.kind === "break") {
70881
71804
  return;
70882
71805
  }
70883
71806
  element.style.fontFamily = run2.fontFamily;
@@ -71011,6 +71934,17 @@ const sliceRunsForLine = (block, line) => {
71011
71934
  result.push(run2);
71012
71935
  continue;
71013
71936
  }
71937
+ if (run2.kind === "break") {
71938
+ result.push(run2);
71939
+ continue;
71940
+ }
71941
+ if (run2.kind === "tab") {
71942
+ result.push(run2);
71943
+ continue;
71944
+ }
71945
+ if (!("text" in run2)) {
71946
+ continue;
71947
+ }
71014
71948
  const text = run2.text ?? "";
71015
71949
  const isFirstRun = runIndex === line.fromRun;
71016
71950
  const isLastRun = runIndex === line.toRun;
@@ -71024,20 +71958,14 @@ const sliceRunsForLine = (block, line) => {
71024
71958
  if (!slice2) continue;
71025
71959
  const pmSliceStart = runPmStart != null ? runPmStart + start2 : void 0;
71026
71960
  const pmSliceEnd = runPmStart != null ? runPmStart + end2 : fallbackPmEnd ?? void 0;
71027
- if (run2.kind === "tab") {
71028
- if (slice2.includes(" ")) {
71029
- result.push(run2);
71030
- }
71031
- } else {
71032
- const sliced = {
71033
- ...run2,
71034
- text: slice2,
71035
- pmStart: pmSliceStart,
71036
- pmEnd: pmSliceEnd,
71037
- comments: run2.comments ? [...run2.comments] : void 0
71038
- };
71039
- result.push(sliced);
71040
- }
71961
+ const sliced = {
71962
+ ...run2,
71963
+ text: slice2,
71964
+ pmStart: pmSliceStart,
71965
+ pmEnd: pmSliceEnd,
71966
+ comments: run2.comments ? [...run2.comments] : void 0
71967
+ };
71968
+ result.push(sliced);
71041
71969
  } else {
71042
71970
  result.push(run2);
71043
71971
  }
@@ -71080,6 +72008,39 @@ const computeLinePmRange = (block, line) => {
71080
72008
  }
71081
72009
  continue;
71082
72010
  }
72011
+ if (run2.kind === "break") {
72012
+ const runPmStart2 = run2.pmStart ?? null;
72013
+ const runPmEnd = run2.pmEnd ?? null;
72014
+ if (runPmStart2 == null || runPmEnd == null) {
72015
+ continue;
72016
+ }
72017
+ if (pmStart == null) {
72018
+ pmStart = runPmStart2;
72019
+ }
72020
+ pmEnd = runPmEnd;
72021
+ if (runIndex === line.toRun) {
72022
+ break;
72023
+ }
72024
+ continue;
72025
+ }
72026
+ if (run2.kind === "tab") {
72027
+ const runPmStart2 = run2.pmStart ?? null;
72028
+ const runPmEnd = run2.pmEnd ?? null;
72029
+ if (runPmStart2 == null || runPmEnd == null) {
72030
+ continue;
72031
+ }
72032
+ if (pmStart == null) {
72033
+ pmStart = runPmStart2;
72034
+ }
72035
+ pmEnd = runPmEnd;
72036
+ if (runIndex === line.toRun) {
72037
+ break;
72038
+ }
72039
+ continue;
72040
+ }
72041
+ if (!("text" in run2)) {
72042
+ continue;
72043
+ }
71083
72044
  const text = run2.text ?? "";
71084
72045
  const runLength = text.length;
71085
72046
  const runPmStart = run2.pmStart ?? null;
@@ -71121,6 +72082,12 @@ const resolveRunText = (run2, context) => {
71121
72082
  if (run2.kind === "lineBreak") {
71122
72083
  return "";
71123
72084
  }
72085
+ if (run2.kind === "break") {
72086
+ return "";
72087
+ }
72088
+ if (!("text" in run2)) {
72089
+ return "";
72090
+ }
71124
72091
  if (!runToken) {
71125
72092
  return run2.text ?? "";
71126
72093
  }
@@ -71318,6 +72285,7 @@ async function measureBlock(block, constraints) {
71318
72285
  async function measureParagraphBlock(block, maxWidth) {
71319
72286
  const ctx2 = getCanvasContext();
71320
72287
  const wordLayout = block.attrs?.wordLayout;
72288
+ const WIDTH_FUDGE_PX = 0.5;
71321
72289
  const lines = [];
71322
72290
  const indent = block.attrs?.indent;
71323
72291
  const spacing = block.attrs?.spacing;
@@ -71412,8 +72380,67 @@ async function measureParagraphBlock(block, maxWidth) {
71412
72380
  lastAppliedTabAlign = { target, val };
71413
72381
  pendingTabAlignment = null;
71414
72382
  };
71415
- for (let runIndex = 0; runIndex < block.runs.length; runIndex++) {
71416
- const run2 = block.runs[runIndex];
72383
+ const runsToProcess = [];
72384
+ for (const run2 of block.runs) {
72385
+ if (run2.text && typeof run2.text === "string" && run2.text.includes("\n")) {
72386
+ const textRun = run2;
72387
+ const segments = textRun.text.split("\n");
72388
+ let cursor = textRun.pmStart ?? 0;
72389
+ segments.forEach((seg, idx) => {
72390
+ runsToProcess.push({
72391
+ ...textRun,
72392
+ text: seg,
72393
+ pmStart: cursor,
72394
+ pmEnd: cursor + seg.length
72395
+ });
72396
+ cursor += seg.length;
72397
+ if (idx !== segments.length - 1) {
72398
+ runsToProcess.push({
72399
+ kind: "break",
72400
+ breakType: "line",
72401
+ pmStart: cursor,
72402
+ pmEnd: cursor + 1,
72403
+ sdt: run2.sdt
72404
+ });
72405
+ cursor += 1;
72406
+ }
72407
+ });
72408
+ } else {
72409
+ runsToProcess.push(run2);
72410
+ }
72411
+ }
72412
+ for (let runIndex = 0; runIndex < runsToProcess.length; runIndex++) {
72413
+ const run2 = runsToProcess[runIndex];
72414
+ if (run2.kind === "break") {
72415
+ if (currentLine) {
72416
+ const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
72417
+ const completedLine = { ...currentLine, ...metrics };
72418
+ addBarTabsToLine(completedLine);
72419
+ lines.push(completedLine);
72420
+ currentLine = null;
72421
+ } else {
72422
+ const textRunWithSize = block.runs.find(
72423
+ (r2) => r2.kind !== "tab" && r2.kind !== "lineBreak" && r2.kind !== "break" && !("src" in r2) && "fontSize" in r2
72424
+ );
72425
+ const fallbackSize = textRunWithSize?.fontSize ?? 12;
72426
+ const metrics = calculateTypographyMetrics(fallbackSize, spacing);
72427
+ const emptyLine = {
72428
+ fromRun: runIndex,
72429
+ fromChar: 0,
72430
+ toRun: runIndex,
72431
+ toChar: 0,
72432
+ width: 0,
72433
+ segments: [],
72434
+ ...metrics
72435
+ };
72436
+ addBarTabsToLine(emptyLine);
72437
+ lines.push(emptyLine);
72438
+ }
72439
+ tabStopCursor = 0;
72440
+ pendingTabAlignment = null;
72441
+ lastAppliedTabAlign = null;
72442
+ continue;
72443
+ }
71417
72444
  if (isLineBreakRun(run2)) {
71418
72445
  if (currentLine) {
71419
72446
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
@@ -71564,6 +72591,9 @@ async function measureParagraphBlock(block, maxWidth) {
71564
72591
  }
71565
72592
  continue;
71566
72593
  }
72594
+ if (!("text" in run2) || !("fontSize" in run2)) {
72595
+ continue;
72596
+ }
71567
72597
  lastFontSize = run2.fontSize;
71568
72598
  const { font } = buildFontString(run2);
71569
72599
  const tabSegments = run2.text.split(" ");
@@ -71603,18 +72633,18 @@ async function measureParagraphBlock(block, maxWidth) {
71603
72633
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
71604
72634
  };
71605
72635
  const ls = run2.letterSpacing ?? 0;
71606
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth) {
72636
+ if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX) {
71607
72637
  currentLine.toChar = wordEndWithSpace;
71608
72638
  currentLine.width = roundValue(currentLine.width + spaceWidth + ls);
71609
72639
  charPosInRun = wordEndWithSpace;
71610
72640
  } else {
71611
- charPosInRun = wordEndNoSpace;
72641
+ charPosInRun = wordEndWithSpace;
71612
72642
  }
71613
72643
  continue;
71614
72644
  }
71615
72645
  const isTocEntry = block.attrs?.isTocEntry;
71616
72646
  const boundarySpacing = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
71617
- if (currentLine.width + boundarySpacing + wordOnlyWidth > currentLine.maxWidth && currentLine.width > 0 && !isTocEntry) {
72647
+ if (currentLine.width + boundarySpacing + wordOnlyWidth > currentLine.maxWidth - WIDTH_FUDGE_PX && currentLine.width > 0 && !isTocEntry) {
71618
72648
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
71619
72649
  const completedLine = {
71620
72650
  ...currentLine,
@@ -71634,16 +72664,16 @@ async function measureParagraphBlock(block, maxWidth) {
71634
72664
  maxWidth: getEffectiveWidth(contentWidth),
71635
72665
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
71636
72666
  };
71637
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth) {
72667
+ if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX) {
71638
72668
  currentLine.toChar = wordEndWithSpace;
71639
72669
  currentLine.width = roundValue(currentLine.width + spaceWidth + (run2.letterSpacing ?? 0));
71640
72670
  charPosInRun = wordEndWithSpace;
71641
72671
  } else {
71642
- charPosInRun = wordEndNoSpace;
72672
+ charPosInRun = wordEndWithSpace;
71643
72673
  }
71644
72674
  } else {
71645
72675
  currentLine.toRun = runIndex;
71646
- if (!isLastWord && currentLine.width + boundarySpacing + wordOnlyWidth + spaceWidth > currentLine.maxWidth) {
72676
+ if (!isLastWord && currentLine.width + boundarySpacing + wordOnlyWidth + spaceWidth > currentLine.maxWidth - WIDTH_FUDGE_PX) {
71647
72677
  currentLine.toChar = wordEndNoSpace;
71648
72678
  currentLine.width = roundValue(currentLine.width + boundarySpacing + wordOnlyWidth);
71649
72679
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run2.fontSize);
@@ -71769,6 +72799,34 @@ async function measureParagraphBlock(block, maxWidth) {
71769
72799
  async function measureTableBlock(block, constraints) {
71770
72800
  const maxWidth = typeof constraints === "number" ? constraints : constraints.maxWidth;
71771
72801
  let columnWidths;
72802
+ const scaleColumnWidths = (widths, targetWidth) => {
72803
+ const totalWidth2 = widths.reduce((a, b2) => a + b2, 0);
72804
+ if (totalWidth2 <= targetWidth || widths.length === 0) return widths;
72805
+ const scale = targetWidth / totalWidth2;
72806
+ const scaled = widths.map((w2) => Math.max(1, Math.round(w2 * scale)));
72807
+ const sum = scaled.reduce((a, b2) => a + b2, 0);
72808
+ if (sum !== targetWidth) {
72809
+ const adjust = (delta) => {
72810
+ let idx = 0;
72811
+ const direction = delta > 0 ? 1 : -1;
72812
+ delta = Math.abs(delta);
72813
+ while (delta > 0 && scaled.length > 0) {
72814
+ const i = idx % scaled.length;
72815
+ if (direction > 0) {
72816
+ scaled[i] += 1;
72817
+ delta -= 1;
72818
+ } else if (scaled[i] > 1) {
72819
+ scaled[i] -= 1;
72820
+ delta -= 1;
72821
+ }
72822
+ idx += 1;
72823
+ if (idx > scaled.length * 2 && delta > 0) break;
72824
+ }
72825
+ };
72826
+ adjust(targetWidth - sum);
72827
+ }
72828
+ return scaled;
72829
+ };
71772
72830
  const maxCellCount = Math.max(1, Math.max(...block.rows.map((r2) => r2.cells.length)));
71773
72831
  if (block.columnWidths && block.columnWidths.length > 0) {
71774
72832
  columnWidths = [...block.columnWidths];
@@ -71777,8 +72835,7 @@ async function measureTableBlock(block, constraints) {
71777
72835
  if (hasExplicitWidth || hasFixedLayout) {
71778
72836
  const totalWidth2 = columnWidths.reduce((a, b2) => a + b2, 0);
71779
72837
  if (totalWidth2 > maxWidth) {
71780
- const scale = maxWidth / totalWidth2;
71781
- columnWidths = columnWidths.map((w2) => Math.max(1, Math.floor(w2 * scale)));
72838
+ columnWidths = scaleColumnWidths(columnWidths, maxWidth);
71782
72839
  }
71783
72840
  } else {
71784
72841
  if (columnWidths.length < maxCellCount) {
@@ -71792,8 +72849,7 @@ async function measureTableBlock(block, constraints) {
71792
72849
  }
71793
72850
  const totalWidth2 = columnWidths.reduce((a, b2) => a + b2, 0);
71794
72851
  if (totalWidth2 > maxWidth) {
71795
- const scale = maxWidth / totalWidth2;
71796
- columnWidths = columnWidths.map((w2) => Math.max(1, Math.floor(w2 * scale)));
72852
+ columnWidths = scaleColumnWidths(columnWidths, maxWidth);
71797
72853
  }
71798
72854
  }
71799
72855
  } else {
@@ -71810,6 +72866,8 @@ async function measureTableBlock(block, constraints) {
71810
72866
  };
71811
72867
  const rowspanTracker = new Array(gridColumnCount).fill(0);
71812
72868
  const rows = [];
72869
+ const rowBaseHeights = new Array(block.rows.length).fill(0);
72870
+ const spanConstraints = [];
71813
72871
  for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex++) {
71814
72872
  const row = block.rows[rowIndex];
71815
72873
  const cellMeasures = [];
@@ -71856,6 +72914,11 @@ async function measureTableBlock(block, constraints) {
71856
72914
  colSpan: colspan,
71857
72915
  rowSpan: rowspan
71858
72916
  });
72917
+ if (rowspan === 1) {
72918
+ rowBaseHeights[rowIndex] = Math.max(rowBaseHeights[rowIndex], totalCellHeight);
72919
+ } else {
72920
+ spanConstraints.push({ startRow: rowIndex, rowSpan: rowspan, requiredHeight: totalCellHeight });
72921
+ }
71859
72922
  gridColIndex += colspan;
71860
72923
  }
71861
72924
  for (let col = gridColIndex; col < gridColumnCount; col++) {
@@ -71863,10 +72926,39 @@ async function measureTableBlock(block, constraints) {
71863
72926
  rowspanTracker[col]--;
71864
72927
  }
71865
72928
  }
71866
- const rowHeight = Math.max(0, ...cellMeasures.map((c2) => c2.height));
71867
- rows.push({ cells: cellMeasures, height: rowHeight });
72929
+ rows.push({ cells: cellMeasures, height: 0 });
72930
+ }
72931
+ const rowHeights = [...rowBaseHeights];
72932
+ for (const constraint of spanConstraints) {
72933
+ const { startRow, rowSpan, requiredHeight } = constraint;
72934
+ if (rowSpan <= 0) continue;
72935
+ let currentHeight = 0;
72936
+ for (let i = 0; i < rowSpan && startRow + i < rowHeights.length; i++) {
72937
+ currentHeight += rowHeights[startRow + i];
72938
+ }
72939
+ if (currentHeight < requiredHeight) {
72940
+ const spanLength = Math.min(rowSpan, rowHeights.length - startRow);
72941
+ const increment = spanLength > 0 ? (requiredHeight - currentHeight) / spanLength : 0;
72942
+ for (let i = 0; i < spanLength; i++) {
72943
+ rowHeights[startRow + i] += increment;
72944
+ }
72945
+ }
72946
+ }
72947
+ block.rows.forEach((row, index2) => {
72948
+ const spec = row.attrs?.rowHeight;
72949
+ if (spec?.value != null && Number.isFinite(spec.value)) {
72950
+ const rule = spec.rule ?? "atLeast";
72951
+ if (rule === "exact") {
72952
+ rowHeights[index2] = spec.value;
72953
+ } else {
72954
+ rowHeights[index2] = Math.max(rowHeights[index2], spec.value);
72955
+ }
72956
+ }
72957
+ });
72958
+ for (let i = 0; i < rows.length; i++) {
72959
+ rows[i].height = Math.max(0, rowHeights[i]);
71868
72960
  }
71869
- const totalHeight = rows.reduce((sum, r2) => sum + r2.height, 0);
72961
+ const totalHeight = rowHeights.reduce((sum, h) => sum + h, 0);
71870
72962
  const totalWidth = columnWidths.reduce((a, b2) => a + b2, 0);
71871
72963
  return {
71872
72964
  kind: "table",
@@ -72072,7 +73164,7 @@ const resolveLineHeight = (spacing, baseLineHeight) => {
72072
73164
  if (spacing.lineRule === "atLeast") {
72073
73165
  return Math.max(baseLineHeight, raw);
72074
73166
  }
72075
- return raw;
73167
+ return Math.max(baseLineHeight, raw);
72076
73168
  };
72077
73169
  const sanitizePositive = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : 0;
72078
73170
  const sanitizeDecimalSeparator = (value) => {