@harbour-enterprises/superdoc 2.0.0-next.1 → 2.0.0-next.11

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 (30) hide show
  1. package/dist/chunks/{PdfViewer-BDQHgDVD.es.js → PdfViewer-CKia_BiV.es.js} +1 -1
  2. package/dist/chunks/{PdfViewer-Cun5Zr8u.cjs → PdfViewer-CqLaaynu.cjs} +1 -1
  3. package/dist/chunks/{index-if-EH8uU.cjs → index-B6y8QUV4.cjs} +3 -3
  4. package/dist/chunks/{index-Dq6vXk74-Vm-euNb7.cjs → index-Bym7r582-C-HNFdqE.cjs} +1 -1
  5. package/dist/chunks/{index-Dq6vXk74-CQD7nLbH.es.js → index-Bym7r582-C74MxNIS.es.js} +1 -1
  6. package/dist/chunks/{index-CGAmeAEK.es.js → index-CI_4oB5b.es.js} +3 -3
  7. package/dist/chunks/{super-editor.es-CwNpXZzP.cjs → super-editor.es-cwkDFZH7.cjs} +781 -158
  8. package/dist/chunks/{super-editor.es-DyaHVXrq.es.js → super-editor.es-d52fdTl1.es.js} +781 -158
  9. package/dist/packages/superdoc/src/core/SuperDoc.d.ts.map +1 -1
  10. package/dist/style.css +6 -6
  11. package/dist/super-editor/ai-writer.es.js +2 -2
  12. package/dist/super-editor/chunks/{converter-BtoNJWI9.js → converter-BdRh3O4f.js} +45 -3
  13. package/dist/super-editor/chunks/{docx-zipper-CLkDdGOr.js → docx-zipper-Bn6DCl5u.js} +1 -1
  14. package/dist/super-editor/chunks/{editor-COH8793Z.js → editor-015kcgto.js} +734 -170
  15. package/dist/super-editor/chunks/{index-Dq6vXk74.js → index-Bym7r582.js} +1 -1
  16. package/dist/super-editor/chunks/{toolbar-Ca-BPuJ2.js → toolbar-CoU_nhyU.js} +2 -2
  17. package/dist/super-editor/converter.es.js +1 -1
  18. package/dist/super-editor/docx-zipper.es.js +2 -2
  19. package/dist/super-editor/editor.es.js +3 -3
  20. package/dist/super-editor/file-zipper.es.js +1 -1
  21. package/dist/super-editor/style.css +6 -6
  22. package/dist/super-editor/super-editor.es.js +41 -17
  23. package/dist/super-editor/toolbar.es.js +2 -2
  24. package/dist/super-editor.cjs +1 -1
  25. package/dist/super-editor.es.js +1 -1
  26. package/dist/superdoc.cjs +2 -2
  27. package/dist/superdoc.es.js +2 -2
  28. package/dist/superdoc.umd.js +783 -160
  29. package/dist/superdoc.umd.js.map +1 -1
  30. package/package.json +1 -1
@@ -39217,11 +39217,15 @@ Please report this to https://github.com/markedjs/marked.`, e) {
39217
39217
  }
39218
39218
  if (elements.length === 1) {
39219
39219
  text2 = elements[0].text;
39220
- const xmlSpace = encodedAttrs.xmlSpace ?? elements[0]?.attributes?.["xml:space"];
39220
+ const docXmlSpace = params2.converter?.documentAttributes?.["xml:space"];
39221
+ const xmlSpace = encodedAttrs.xmlSpace ?? attributes?.["xml:space"] ?? elements[0]?.attributes?.["xml:space"] ?? docXmlSpace;
39221
39222
  if (xmlSpace !== "preserve" && typeof text2 === "string") {
39222
39223
  text2 = text2.replace(/^[ \t\n\r]+/, "").replace(/[ \t\n\r]+$/, "");
39223
39224
  }
39224
39225
  text2 = text2.replace(/\[\[sdspace\]\]/g, "");
39226
+ if (xmlSpace !== "preserve" && typeof text2 === "string" && !text2.trim()) {
39227
+ return null;
39228
+ }
39225
39229
  } else if (!elements.length && encodedAttrs.xmlSpace === "preserve") {
39226
39230
  text2 = " ";
39227
39231
  } else return null;
@@ -42204,8 +42208,46 @@ Please report this to https://github.com/markedjs/marked.`, e) {
42204
42208
  this.declaration = this.initialJSON?.declaration;
42205
42209
  this.resolveDocumentGuid();
42206
42210
  }
42211
+ /**
42212
+ * Parses XML content into JSON format while preserving whitespace-only text runs.
42213
+ *
42214
+ * This method wraps xml-js's xml2json parser with additional preprocessing to prevent
42215
+ * the parser from dropping whitespace-only content in <w:t> and <w:delText> elements.
42216
+ * This is critical for correctly handling documents that rely on document-level
42217
+ * xml:space="preserve" rather than per-element attributes, which is common in
42218
+ * PDF-to-DOCX converted documents.
42219
+ *
42220
+ * The whitespace preservation strategy:
42221
+ * 1. Before parsing, wraps whitespace-only content with [[sdspace]] placeholders
42222
+ * 2. xml-js parser preserves the placeholder-wrapped text
42223
+ * 3. During text node processing (t-translator.js), placeholders are removed
42224
+ *
42225
+ * @param {string} xml - The XML string to parse
42226
+ * @returns {Object} The parsed JSON representation of the XML document
42227
+ *
42228
+ * @example
42229
+ * // Handles whitespace-only text runs
42230
+ * const xml = '<w:t> </w:t>';
42231
+ * const result = parseXmlToJson(xml);
42232
+ * // Result preserves the space: { elements: [{ text: '[[sdspace]] [[sdspace]]' }] }
42233
+ *
42234
+ * @example
42235
+ * // Handles elements with attributes
42236
+ * const xml = '<w:t xml:space="preserve"> text </w:t>';
42237
+ * const result = parseXmlToJson(xml);
42238
+ * // Preserves content and attributes
42239
+ *
42240
+ * @example
42241
+ * // Handles both w:t and w:delText elements
42242
+ * const xml = '<w:delText> </w:delText>';
42243
+ * const result = parseXmlToJson(xml);
42244
+ * // Preserves whitespace in deleted text
42245
+ */
42207
42246
  parseXmlToJson(xml2) {
42208
- const newXml = xml2.replace(/(<w:t xml:space="preserve">)(\s+)(<\/w:t>)/g, "$1[[sdspace]]$2[[sdspace]]$3");
42247
+ const newXml = xml2.replace(
42248
+ /(<w:(?:t|delText)(?:\s[^>]*)?>)(\s+)(<\/w:(?:t|delText)>)/g,
42249
+ "$1[[sdspace]]$2[[sdspace]]$3"
42250
+ );
42209
42251
  return JSON.parse(xmljs.xml2json(newXml, null, 2));
42210
42252
  }
42211
42253
  /**
@@ -42428,7 +42470,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
42428
42470
  static getStoredSuperdocVersion(docx) {
42429
42471
  return _SuperConverter2.getStoredCustomProperty(docx, "SuperdocVersion");
42430
42472
  }
42431
- static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "2.0.0-next.1") {
42473
+ static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "2.0.0-next.11") {
42432
42474
  return _SuperConverter2.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
42433
42475
  }
42434
42476
  /**
@@ -68384,7 +68426,7 @@ ${err.toString()}`);
68384
68426
  const shouldSkipNodeView = (editor) => {
68385
68427
  return isHeadless(editor);
68386
68428
  };
68387
- const summaryVersion = "2.0.0-next.1";
68429
+ const summaryVersion = "2.0.0-next.11";
68388
68430
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
68389
68431
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
68390
68432
  function mapAttributes(attrs) {
@@ -69173,7 +69215,7 @@ ${err.toString()}`);
69173
69215
  { default: remarkStringify2 },
69174
69216
  { default: remarkGfm2 }
69175
69217
  ] = await Promise.all([
69176
- Promise.resolve().then(() => indexDq6vXk74),
69218
+ Promise.resolve().then(() => indexBym7r582),
69177
69219
  Promise.resolve().then(() => indexDRCvimau),
69178
69220
  Promise.resolve().then(() => indexC_x_N6Uh),
69179
69221
  Promise.resolve().then(() => indexD_sWOSiG),
@@ -69378,7 +69420,7 @@ ${err.toString()}`);
69378
69420
  * Process collaboration migrations
69379
69421
  */
69380
69422
  processCollaborationMigrations() {
69381
- console.debug("[checkVersionMigrations] Current editor version", "2.0.0-next.1");
69423
+ console.debug("[checkVersionMigrations] Current editor version", "2.0.0-next.11");
69382
69424
  if (!this.options.ydoc) return;
69383
69425
  const metaMap = this.options.ydoc.getMap("meta");
69384
69426
  let docVersion = metaMap.get("version");
@@ -76630,7 +76672,7 @@ ${l}
76630
76672
  return true;
76631
76673
  }
76632
76674
  const LIST_MARKER_GAP$2 = 8;
76633
- const DEFAULT_TAB_INTERVAL_PX$1 = 48;
76675
+ const DEFAULT_TAB_INTERVAL_PX$2 = 48;
76634
76676
  const DEFAULT_PAGE_HEIGHT_PX = 1056;
76635
76677
  const DEFAULT_VIRTUALIZED_PAGE_GAP$1 = 72;
76636
76678
  const COMMENT_EXTERNAL_COLOR = "#B1124B";
@@ -77557,6 +77599,7 @@ ${l}
77557
77599
  const block = lookup2.block;
77558
77600
  const measure = lookup2.measure;
77559
77601
  const wordLayout = isMinimalWordLayout(block.attrs?.wordLayout) ? block.attrs.wordLayout : void 0;
77602
+ const alignment2 = block.attrs?.alignment;
77560
77603
  const fragmentEl = this.doc.createElement("div");
77561
77604
  fragmentEl.classList.add(CLASS_NAMES$1.fragment);
77562
77605
  const isTocEntry = block.attrs?.isTocEntry;
@@ -77635,7 +77678,7 @@ ${l}
77635
77678
  const textStart = paraIndentLeft + firstLine;
77636
77679
  tabWidth = textStart - currentPos;
77637
77680
  if (tabWidth <= 0) {
77638
- tabWidth = DEFAULT_TAB_INTERVAL_PX$1 - currentPos % DEFAULT_TAB_INTERVAL_PX$1;
77681
+ tabWidth = DEFAULT_TAB_INTERVAL_PX$2 - currentPos % DEFAULT_TAB_INTERVAL_PX$2;
77639
77682
  } else if (tabWidth < LIST_MARKER_GAP$2) {
77640
77683
  tabWidth = LIST_MARKER_GAP$2;
77641
77684
  }
@@ -77662,6 +77705,21 @@ ${l}
77662
77705
  let availableWidthOverride = line.maxWidth != null ? Math.min(line.maxWidth, fallbackAvailableWidth) : fallbackAvailableWidth;
77663
77706
  if (index2 === 0 && listFirstLineMarkerTabWidth != null) {
77664
77707
  availableWidthOverride = fragment.width - listFirstLineMarkerTabWidth - Math.max(0, paraIndentRight);
77708
+ if (alignment2 === "justify" || alignment2 === "both") {
77709
+ console.log(
77710
+ "[justify-debug][painter-firstline-available]",
77711
+ JSON.stringify({
77712
+ blockId: block.id,
77713
+ fragmentWidth: fragment.width,
77714
+ markerTabWidth: listFirstLineMarkerTabWidth,
77715
+ paraIndentRight,
77716
+ availableWidthOverride,
77717
+ lineMaxWidth: line.maxWidth ?? null,
77718
+ lineWidth: line.width,
77719
+ lineNaturalWidth: line.naturalWidth ?? null
77720
+ })
77721
+ );
77722
+ }
77665
77723
  }
77666
77724
  const isLastLineOfFragment = index2 === lines.length - 1;
77667
77725
  const isLastLineOfParagraph = isLastLineOfFragment && !fragment.continuesOnNext;
@@ -77787,7 +77845,7 @@ ${l}
77787
77845
  const textStart = paraIndentLeft + firstLine;
77788
77846
  tabWidth = textStart - currentPos;
77789
77847
  if (tabWidth <= 0) {
77790
- tabWidth = DEFAULT_TAB_INTERVAL_PX$1 - currentPos % DEFAULT_TAB_INTERVAL_PX$1;
77848
+ tabWidth = DEFAULT_TAB_INTERVAL_PX$2 - currentPos % DEFAULT_TAB_INTERVAL_PX$2;
77791
77849
  } else if (tabWidth < LIST_MARKER_GAP$2) {
77792
77850
  tabWidth = LIST_MARKER_GAP$2;
77793
77851
  }
@@ -79321,6 +79379,23 @@ ${l}
79321
79379
  if (spacingPerSpace !== 0) {
79322
79380
  el.style.wordSpacing = `${spacingPerSpace}px`;
79323
79381
  }
79382
+ if (justifyShouldApply && spacingPerSpace < 0) {
79383
+ console.log(
79384
+ "[justify-debug][painter-wordspacing-negative]",
79385
+ JSON.stringify({
79386
+ blockId: block.id,
79387
+ lineIndex: lineIndex ?? null,
79388
+ alignment: alignment2 ?? null,
79389
+ availableWidth,
79390
+ lineWidth,
79391
+ lineMaxWidth: line.maxWidth ?? null,
79392
+ lineNaturalWidth: line.naturalWidth ?? null,
79393
+ spaceCount,
79394
+ hasExplicitPositioning: Boolean(hasExplicitPositioning),
79395
+ skipJustify: Boolean(skipJustify)
79396
+ })
79397
+ );
79398
+ }
79324
79399
  if (hasExplicitPositioning && line.segments) {
79325
79400
  const paraIndent = block.attrs?.indent;
79326
79401
  const indentLeft = paraIndent?.left ?? 0;
@@ -81514,6 +81589,28 @@ ${l}
81514
81589
  const TAB_CHAR_LENGTH = 1;
81515
81590
  const SPACE_CHARS = SPACE_CHARS$1;
81516
81591
  const isTabRun$1 = (run2) => run2?.kind === "tab";
81592
+ const isWordChar$3 = (char) => {
81593
+ if (!char) return false;
81594
+ const code2 = char.charCodeAt(0);
81595
+ return code2 >= 48 && code2 <= 57 || code2 >= 65 && code2 <= 90 || code2 >= 97 && code2 <= 122 || char === "'";
81596
+ };
81597
+ const capitalizeText$2 = (text2) => {
81598
+ if (!text2) return text2;
81599
+ let result = "";
81600
+ for (let i2 = 0; i2 < text2.length; i2 += 1) {
81601
+ const prevChar = i2 > 0 ? text2[i2 - 1] : "";
81602
+ const ch = text2[i2];
81603
+ result += isWordChar$3(ch) && !isWordChar$3(prevChar) ? ch.toUpperCase() : ch;
81604
+ }
81605
+ return result;
81606
+ };
81607
+ const applyTextTransform$2 = (text2, transform) => {
81608
+ if (!text2 || !transform || transform === "none") return text2;
81609
+ if (transform === "uppercase") return text2.toUpperCase();
81610
+ if (transform === "lowercase") return text2.toLowerCase();
81611
+ if (transform === "capitalize") return capitalizeText$2(text2);
81612
+ return text2;
81613
+ };
81517
81614
  function getMeasurementContext() {
81518
81615
  if (measurementCtx) return measurementCtx;
81519
81616
  if (typeof document === "undefined") {
@@ -81689,17 +81786,19 @@ ${l}
81689
81786
  }
81690
81787
  const text2 = "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation" ? "" : run2.text ?? "";
81691
81788
  const runLength = text2.length;
81789
+ const transform = isTabRun$1(run2) || "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation" ? void 0 : run2.textTransform;
81790
+ const displayText = applyTextTransform$2(text2, transform);
81692
81791
  if (currentCharOffset + runLength >= charOffset) {
81693
81792
  const offsetInRun = charOffset - currentCharOffset;
81694
81793
  ctx2.font = getRunFontString(run2);
81695
- const textUpToTarget = text2.slice(0, offsetInRun);
81794
+ const textUpToTarget = displayText.slice(0, offsetInRun);
81696
81795
  const measured2 = ctx2.measureText(textUpToTarget);
81697
81796
  const spacingWidth = computeLetterSpacingWidth(run2, offsetInRun, runLength);
81698
- const spacesInPortion = justify.extraPerSpace !== 0 ? countSpaces(textUpToTarget) : 0;
81797
+ const spacesInPortion = justify.extraPerSpace !== 0 ? countSpaces(text2.slice(0, offsetInRun)) : 0;
81699
81798
  return alignmentOffset + currentX + measured2.width + spacingWidth + justify.extraPerSpace * (spaceTally + spacesInPortion);
81700
81799
  }
81701
81800
  ctx2.font = getRunFontString(run2);
81702
- const measured = ctx2.measureText(text2);
81801
+ const measured = ctx2.measureText(displayText);
81703
81802
  const runLetterSpacing = computeLetterSpacingWidth(run2, runLength, runLength);
81704
81803
  const spacesInRun = justify.extraPerSpace !== 0 ? countSpaces(text2) : 0;
81705
81804
  currentX += measured.width + runLetterSpacing + justify.extraPerSpace * spacesInRun;
@@ -81738,8 +81837,10 @@ ${l}
81738
81837
  return segmentBaseX + (offsetInSegment >= segmentChars ? segment.width ?? 0 : 0);
81739
81838
  }
81740
81839
  const text2 = run2.text ?? "";
81741
- const segmentText = text2.slice(segment.fromChar, segment.toChar);
81742
- const textUpToTarget = segmentText.slice(0, offsetInSegment);
81840
+ const transform = "textTransform" in run2 ? run2.textTransform : void 0;
81841
+ const displayText = applyTextTransform$2(text2, transform);
81842
+ const displaySegmentText = displayText.slice(segment.fromChar, segment.toChar);
81843
+ const textUpToTarget = displaySegmentText.slice(0, offsetInSegment);
81743
81844
  ctx2.font = getRunFontString(run2);
81744
81845
  const measured = ctx2.measureText(textUpToTarget);
81745
81846
  const spacingWidth = computeLetterSpacingWidth(run2, offsetInSegment, segmentChars);
@@ -81835,12 +81936,14 @@ ${l}
81835
81936
  }
81836
81937
  const text2 = "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation" ? "" : run2.text ?? "";
81837
81938
  const runLength = text2.length;
81939
+ const transform = isTabRun$1(run2) || "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation" ? void 0 : run2.textTransform;
81940
+ const displayText = applyTextTransform$2(text2, transform);
81838
81941
  if (runLength === 0) continue;
81839
81942
  ctx2.font = getRunFontString(run2);
81840
81943
  for (let i2 = 0; i2 <= runLength; i2++) {
81841
- const textUpToChar = text2.slice(0, i2);
81944
+ const textUpToChar = displayText.slice(0, i2);
81842
81945
  const measured2 = ctx2.measureText(textUpToChar);
81843
- const spacesInPortion = justify.extraPerSpace > 0 ? countSpaces(textUpToChar) : 0;
81946
+ const spacesInPortion = justify.extraPerSpace > 0 ? countSpaces(text2.slice(0, i2)) : 0;
81844
81947
  const charX = currentX + measured2.width + computeLetterSpacingWidth(run2, i2, runLength) + justify.extraPerSpace * (spaceTally + spacesInPortion);
81845
81948
  if (charX >= safeX) {
81846
81949
  if (i2 === 0) {
@@ -81850,7 +81953,7 @@ ${l}
81850
81953
  pmPosition: pmPosition3
81851
81954
  };
81852
81955
  }
81853
- const prevText = text2.slice(0, i2 - 1);
81956
+ const prevText = displayText.slice(0, i2 - 1);
81854
81957
  const prevMeasured = ctx2.measureText(prevText);
81855
81958
  const prevX = currentX + prevMeasured.width + computeLetterSpacingWidth(run2, i2 - 1, runLength);
81856
81959
  const distToPrev = Math.abs(safeX - prevX);
@@ -81863,7 +81966,7 @@ ${l}
81863
81966
  };
81864
81967
  }
81865
81968
  }
81866
- const measured = ctx2.measureText(text2);
81969
+ const measured = ctx2.measureText(displayText);
81867
81970
  const runLetterSpacing = computeLetterSpacingWidth(run2, runLength, runLength);
81868
81971
  const spacesInRun = justify.extraPerSpace > 0 ? countSpaces(text2) : 0;
81869
81972
  currentX += measured.width + runLetterSpacing + justify.extraPerSpace * spacesInRun;
@@ -82294,6 +82397,83 @@ ${l}
82294
82397
  }
82295
82398
  return index2;
82296
82399
  }
82400
+ const LIST_MARKER_GAP$1 = 8;
82401
+ const MIN_MARKER_GUTTER = 24;
82402
+ const DEFAULT_LIST_INDENT_BASE_PX = 24;
82403
+ const DEFAULT_LIST_INDENT_STEP_PX = 24;
82404
+ const DEFAULT_LIST_HANGING_PX$1 = 18;
82405
+ const SPACE_SUFFIX_GAP_PX = 4;
82406
+ const DEFAULT_TAB_INTERVAL_PX$1 = 48;
82407
+ function resolveListTextStartPx(wordLayout, indentLeft, firstLine, hanging, measureMarkerText) {
82408
+ const marker = wordLayout?.marker;
82409
+ if (!marker) {
82410
+ const textStartPx = wordLayout?.firstLineIndentMode === true && typeof wordLayout.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : void 0;
82411
+ return textStartPx;
82412
+ }
82413
+ const markerBoxWidth = typeof marker.markerBoxWidthPx === "number" && Number.isFinite(marker.markerBoxWidthPx) ? marker.markerBoxWidthPx : 0;
82414
+ let markerTextWidth = typeof marker.glyphWidthPx === "number" && Number.isFinite(marker.glyphWidthPx) ? marker.glyphWidthPx : void 0;
82415
+ if (markerTextWidth == null && marker.markerText) {
82416
+ markerTextWidth = measureMarkerText(marker.markerText, marker);
82417
+ }
82418
+ if (!Number.isFinite(markerTextWidth) || markerTextWidth !== void 0 && markerTextWidth < 0) {
82419
+ markerTextWidth = markerBoxWidth;
82420
+ }
82421
+ const finalMarkerTextWidth = Math.max(0, markerTextWidth ?? 0);
82422
+ let markerStartPos;
82423
+ if (wordLayout?.firstLineIndentMode === true && typeof marker.markerX === "number" && Number.isFinite(marker.markerX)) {
82424
+ markerStartPos = marker.markerX;
82425
+ } else {
82426
+ markerStartPos = indentLeft - hanging + firstLine;
82427
+ }
82428
+ if (!Number.isFinite(markerStartPos)) {
82429
+ markerStartPos = 0;
82430
+ }
82431
+ const currentPos = markerStartPos + finalMarkerTextWidth;
82432
+ const suffix2 = marker.suffix ?? "tab";
82433
+ if (suffix2 === "space") {
82434
+ return markerStartPos + finalMarkerTextWidth + SPACE_SUFFIX_GAP_PX;
82435
+ }
82436
+ if (suffix2 === "nothing") {
82437
+ return markerStartPos + finalMarkerTextWidth;
82438
+ }
82439
+ const markerJustification = marker.justification ?? "left";
82440
+ if (markerJustification !== "left") {
82441
+ const gutterWidth = typeof marker.gutterWidthPx === "number" && Number.isFinite(marker.gutterWidthPx) && marker.gutterWidthPx > 0 ? marker.gutterWidthPx : LIST_MARKER_GAP$1;
82442
+ return markerStartPos + finalMarkerTextWidth + Math.max(gutterWidth, LIST_MARKER_GAP$1);
82443
+ }
82444
+ if (wordLayout?.firstLineIndentMode === true) {
82445
+ let targetTabStop;
82446
+ if (Array.isArray(wordLayout.tabsPx)) {
82447
+ for (const tab of wordLayout.tabsPx) {
82448
+ if (typeof tab === "number" && tab > currentPos) {
82449
+ targetTabStop = tab;
82450
+ break;
82451
+ }
82452
+ }
82453
+ }
82454
+ const textStartTarget = typeof marker.textStartX === "number" && Number.isFinite(marker.textStartX) ? marker.textStartX : wordLayout.textStartPx;
82455
+ let tabWidth2;
82456
+ if (targetTabStop !== void 0) {
82457
+ tabWidth2 = targetTabStop - currentPos;
82458
+ } else if (textStartTarget !== void 0 && Number.isFinite(textStartTarget) && textStartTarget > currentPos) {
82459
+ tabWidth2 = textStartTarget - currentPos;
82460
+ } else {
82461
+ tabWidth2 = LIST_MARKER_GAP$1;
82462
+ }
82463
+ if (tabWidth2 < LIST_MARKER_GAP$1) {
82464
+ tabWidth2 = LIST_MARKER_GAP$1;
82465
+ }
82466
+ return markerStartPos + finalMarkerTextWidth + tabWidth2;
82467
+ }
82468
+ const textStart = indentLeft + firstLine;
82469
+ let tabWidth = textStart - currentPos;
82470
+ if (tabWidth <= 0) {
82471
+ tabWidth = DEFAULT_TAB_INTERVAL_PX$1 - currentPos % DEFAULT_TAB_INTERVAL_PX$1;
82472
+ } else if (tabWidth < LIST_MARKER_GAP$1) {
82473
+ tabWidth = LIST_MARKER_GAP$1;
82474
+ }
82475
+ return markerStartPos + finalMarkerTextWidth + tabWidth;
82476
+ }
82297
82477
  function getWordLayoutConfig(block) {
82298
82478
  if (!block || block.kind !== "paragraph") {
82299
82479
  return void 0;
@@ -82326,9 +82506,16 @@ ${l}
82326
82506
  const isFirstLineIndentMode = wordLayout?.firstLineIndentMode === true;
82327
82507
  let indentAdjust = paraIndentLeft;
82328
82508
  if (isListItem2 && isFirstLine && isFirstLineIndentMode) {
82509
+ const resolvedTextStart = resolveListTextStartPx(
82510
+ wordLayout,
82511
+ paraIndentLeft,
82512
+ Math.max(firstLineIndent, 0),
82513
+ Math.max(hangingIndent, 0),
82514
+ () => markerWidth
82515
+ // Use provided markerWidth since we don't have canvas access here
82516
+ );
82329
82517
  const textStartFallback = paraIndentLeft + Math.max(firstLineIndent, 0) + markerWidth;
82330
- const markerTextStartX = wordLayout?.marker?.textStartX;
82331
- indentAdjust = typeof markerTextStartX === "number" && Number.isFinite(markerTextStartX) ? markerTextStartX : typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : textStartFallback;
82518
+ indentAdjust = typeof resolvedTextStart === "number" && Number.isFinite(resolvedTextStart) ? resolvedTextStart : textStartFallback;
82332
82519
  } else if (isFirstLine && !isListItem2) {
82333
82520
  indentAdjust += firstLineOffset;
82334
82521
  }
@@ -82484,7 +82671,10 @@ ${l}
82484
82671
  }
82485
82672
  function createFloatingObjectManager(columns, margins, pageWidth) {
82486
82673
  const zones = [];
82487
- const marginLeft = Math.max(0, margins?.left ?? 0);
82674
+ let currentColumns = columns;
82675
+ let currentMargins = margins;
82676
+ let currentPageWidth = pageWidth;
82677
+ let marginLeft = Math.max(0, currentMargins?.left ?? 0);
82488
82678
  return {
82489
82679
  registerDrawing(drawingBlock, measure, anchorY, columnIndex, pageNumber) {
82490
82680
  if (!drawingBlock.anchor?.isAnchored) {
@@ -82497,7 +82687,7 @@ ${l}
82497
82687
  }
82498
82688
  const objectWidth = measure.width ?? 0;
82499
82689
  const objectHeight = measure.height ?? 0;
82500
- const x2 = computeAnchorX(anchor, columnIndex, columns, objectWidth, margins, pageWidth);
82690
+ const x2 = computeAnchorX(anchor, columnIndex, currentColumns, objectWidth, currentMargins, currentPageWidth);
82501
82691
  const y2 = anchorY + (anchor.offsetV ?? 0);
82502
82692
  const zone = {
82503
82693
  imageBlockId: drawingBlock.id,
@@ -82531,7 +82721,7 @@ ${l}
82531
82721
  }
82532
82722
  const tableWidth = measure.totalWidth ?? 0;
82533
82723
  const tableHeight = measure.totalHeight ?? 0;
82534
- const x2 = computeTableAnchorX(anchor, columnIndex, columns, tableWidth, margins, pageWidth);
82724
+ const x2 = computeTableAnchorX(anchor, columnIndex, currentColumns, tableWidth, currentMargins, currentPageWidth);
82535
82725
  const y2 = anchorY + (anchor.offsetV ?? 0);
82536
82726
  const zone = {
82537
82727
  imageBlockId: tableBlock.id,
@@ -82579,7 +82769,7 @@ ${l}
82579
82769
  }
82580
82770
  const leftFloats = [];
82581
82771
  const rightFloats = [];
82582
- const columnOrigin = marginLeft + columnIndex * (columns.width + columns.gap);
82772
+ const columnOrigin = marginLeft + columnIndex * (currentColumns.width + currentColumns.gap);
82583
82773
  const columnCenter = columnOrigin + baseWidth / 2;
82584
82774
  for (const zone of wrappingZones) {
82585
82775
  if (zone.wrapMode === "left") {
@@ -82618,6 +82808,22 @@ ${l}
82618
82808
  },
82619
82809
  clear() {
82620
82810
  zones.length = 0;
82811
+ },
82812
+ /**
82813
+ * Update layout context used for positioning and wrapping (columns, margins, page width).
82814
+ * This method should be called when the layout configuration changes (e.g., section breaks,
82815
+ * column changes, page size changes) to ensure floating objects are positioned and wrapped
82816
+ * correctly relative to the new layout boundaries.
82817
+ *
82818
+ * @param nextColumns - Column layout configuration (width, gap, count)
82819
+ * @param nextMargins - Optional page margins (left, right) in pixels
82820
+ * @param nextPageWidth - Optional total page width in pixels
82821
+ */
82822
+ setLayoutContext(nextColumns, nextMargins, nextPageWidth) {
82823
+ currentColumns = nextColumns;
82824
+ currentMargins = nextMargins;
82825
+ currentPageWidth = nextPageWidth;
82826
+ marginLeft = Math.max(0, currentMargins?.left ?? 0);
82621
82827
  }
82622
82828
  };
82623
82829
  }
@@ -82717,7 +82923,14 @@ ${l}
82717
82923
  const props = {};
82718
82924
  if (source.kind !== "sectionBreak") return props;
82719
82925
  if (source.margins) {
82720
- props.margins = { header: source.margins.header, footer: source.margins.footer };
82926
+ props.margins = {
82927
+ header: source.margins.header,
82928
+ footer: source.margins.footer,
82929
+ top: source.margins.top,
82930
+ right: source.margins.right,
82931
+ bottom: source.margins.bottom,
82932
+ left: source.margins.left
82933
+ };
82721
82934
  }
82722
82935
  if (source.pageSize) {
82723
82936
  props.pageSize = { w: source.pageSize.w, h: source.pageSize.h };
@@ -82765,20 +82978,36 @@ ${l}
82765
82978
  next2.activeOrientation = block.orientation;
82766
82979
  next2.pendingOrientation = null;
82767
82980
  }
82981
+ const headerDistance = typeof block.margins?.header === "number" ? Math.max(0, block.margins.header) : next2.activeHeaderDistance;
82982
+ const footerDistance = typeof block.margins?.footer === "number" ? Math.max(0, block.margins.footer) : next2.activeFooterDistance;
82983
+ const sectionTop = typeof block.margins?.top === "number" ? Math.max(0, block.margins.top) : baseMargins.top;
82984
+ const sectionBottom = typeof block.margins?.bottom === "number" ? Math.max(0, block.margins.bottom) : baseMargins.bottom;
82768
82985
  if (block.margins?.header !== void 0) {
82769
- const headerDistance = Math.max(0, block.margins.header);
82770
82986
  next2.activeHeaderDistance = headerDistance;
82771
82987
  next2.pendingHeaderDistance = headerDistance;
82772
- next2.activeTopMargin = calcRequiredTopMargin(headerDistance, baseMargins.top);
82773
- next2.pendingTopMargin = next2.activeTopMargin;
82774
82988
  }
82775
82989
  if (block.margins?.footer !== void 0) {
82776
- const footerDistance = Math.max(0, block.margins.footer);
82777
82990
  next2.activeFooterDistance = footerDistance;
82778
82991
  next2.pendingFooterDistance = footerDistance;
82779
- next2.activeBottomMargin = calcRequiredBottomMargin(footerDistance, baseMargins.bottom);
82992
+ }
82993
+ if (block.margins?.top !== void 0 || block.margins?.header !== void 0) {
82994
+ next2.activeTopMargin = calcRequiredTopMargin(headerDistance, sectionTop);
82995
+ next2.pendingTopMargin = next2.activeTopMargin;
82996
+ }
82997
+ if (block.margins?.bottom !== void 0 || block.margins?.footer !== void 0) {
82998
+ next2.activeBottomMargin = calcRequiredBottomMargin(footerDistance, sectionBottom);
82780
82999
  next2.pendingBottomMargin = next2.activeBottomMargin;
82781
83000
  }
83001
+ if (block.margins?.left !== void 0) {
83002
+ const leftMargin = Math.max(0, block.margins.left);
83003
+ next2.activeLeftMargin = leftMargin;
83004
+ next2.pendingLeftMargin = leftMargin;
83005
+ }
83006
+ if (block.margins?.right !== void 0) {
83007
+ const rightMargin = Math.max(0, block.margins.right);
83008
+ next2.activeRightMargin = rightMargin;
83009
+ next2.pendingRightMargin = rightMargin;
83010
+ }
82782
83011
  if (block.columns) {
82783
83012
  next2.activeColumns = { count: block.columns.count, gap: block.columns.gap };
82784
83013
  next2.pendingColumns = null;
@@ -82787,26 +83016,42 @@ ${l}
82787
83016
  }
82788
83017
  const headerPx = block.margins?.header;
82789
83018
  const footerPx = block.margins?.footer;
83019
+ const topPx = block.margins?.top;
83020
+ const bottomPx = block.margins?.bottom;
82790
83021
  const nextTop = next2.pendingTopMargin ?? next2.activeTopMargin;
82791
83022
  const nextBottom = next2.pendingBottomMargin ?? next2.activeBottomMargin;
83023
+ const nextLeft = next2.pendingLeftMargin ?? next2.activeLeftMargin;
83024
+ const nextRight = next2.pendingRightMargin ?? next2.activeRightMargin;
82792
83025
  const nextHeader = next2.pendingHeaderDistance ?? next2.activeHeaderDistance;
82793
83026
  const nextFooter = next2.pendingFooterDistance ?? next2.activeFooterDistance;
82794
- if (typeof headerPx === "number") {
82795
- const newHeaderDist = Math.max(0, headerPx);
83027
+ if (typeof headerPx === "number" || typeof topPx === "number") {
83028
+ const newHeaderDist = typeof headerPx === "number" ? Math.max(0, headerPx) : nextHeader;
83029
+ const sectionTop = typeof topPx === "number" ? Math.max(0, topPx) : baseMargins.top;
82796
83030
  next2.pendingHeaderDistance = newHeaderDist;
82797
- next2.pendingTopMargin = calcRequiredTopMargin(newHeaderDist, baseMargins.top);
83031
+ next2.pendingTopMargin = calcRequiredTopMargin(newHeaderDist, sectionTop);
82798
83032
  } else {
82799
83033
  next2.pendingTopMargin = nextTop;
82800
83034
  next2.pendingHeaderDistance = nextHeader;
82801
83035
  }
82802
- if (typeof footerPx === "number") {
82803
- const newFooterDist = Math.max(0, footerPx);
83036
+ if (typeof footerPx === "number" || typeof bottomPx === "number") {
83037
+ const newFooterDist = typeof footerPx === "number" ? Math.max(0, footerPx) : nextFooter;
83038
+ const sectionBottom = typeof bottomPx === "number" ? Math.max(0, bottomPx) : baseMargins.bottom;
82804
83039
  next2.pendingFooterDistance = newFooterDist;
82805
- next2.pendingBottomMargin = calcRequiredBottomMargin(newFooterDist, baseMargins.bottom);
83040
+ next2.pendingBottomMargin = calcRequiredBottomMargin(newFooterDist, sectionBottom);
82806
83041
  } else {
82807
83042
  next2.pendingBottomMargin = nextBottom;
82808
83043
  next2.pendingFooterDistance = nextFooter;
82809
83044
  }
83045
+ if (typeof block.margins?.left === "number") {
83046
+ next2.pendingLeftMargin = Math.max(0, block.margins.left);
83047
+ } else {
83048
+ next2.pendingLeftMargin = nextLeft;
83049
+ }
83050
+ if (typeof block.margins?.right === "number") {
83051
+ next2.pendingRightMargin = Math.max(0, block.margins.right);
83052
+ } else {
83053
+ next2.pendingRightMargin = nextRight;
83054
+ }
82810
83055
  if (block.pageSize) {
82811
83056
  next2.pendingPageSize = { w: block.pageSize.w, h: block.pageSize.h };
82812
83057
  }
@@ -82866,6 +83111,12 @@ ${l}
82866
83111
  if (next2.pendingBottomMargin != null) {
82867
83112
  next2.activeBottomMargin = next2.pendingBottomMargin;
82868
83113
  }
83114
+ if (next2.pendingLeftMargin != null) {
83115
+ next2.activeLeftMargin = next2.pendingLeftMargin;
83116
+ }
83117
+ if (next2.pendingRightMargin != null) {
83118
+ next2.activeRightMargin = next2.pendingRightMargin;
83119
+ }
82869
83120
  if (next2.pendingHeaderDistance != null) {
82870
83121
  next2.activeHeaderDistance = next2.pendingHeaderDistance;
82871
83122
  }
@@ -82883,6 +83134,8 @@ ${l}
82883
83134
  }
82884
83135
  next2.pendingTopMargin = null;
82885
83136
  next2.pendingBottomMargin = null;
83137
+ next2.pendingLeftMargin = null;
83138
+ next2.pendingRightMargin = null;
82886
83139
  next2.pendingHeaderDistance = null;
82887
83140
  next2.pendingFooterDistance = null;
82888
83141
  next2.pendingPageSize = null;
@@ -83111,7 +83364,8 @@ ${l}
83111
83364
  if (typeof remeasureParagraph2 === "function" && typeof measurementWidth === "number" && measurementWidth > remeasureWidth) {
83112
83365
  const firstLineIndent = calculateFirstLineIndent(block, measure);
83113
83366
  const newMeasure = remeasureParagraph2(block, columnWidth, firstLineIndent);
83114
- lines = normalizeLines(newMeasure);
83367
+ const newLines = normalizeLines(newMeasure);
83368
+ lines = newLines;
83115
83369
  didRemeasureForColumnWidth = true;
83116
83370
  }
83117
83371
  let fromLine = 0;
@@ -83193,7 +83447,8 @@ ${l}
83193
83447
  if (narrowestRemeasureWidth < remeasureWidth) {
83194
83448
  const firstLineIndent = calculateFirstLineIndent(block, measure);
83195
83449
  const newMeasure = remeasureParagraph2(block, narrowestRemeasureWidth, firstLineIndent);
83196
- lines = normalizeLines(newMeasure);
83450
+ const newLines = normalizeLines(newMeasure);
83451
+ lines = newLines;
83197
83452
  didRemeasureForFloats = true;
83198
83453
  }
83199
83454
  }
@@ -83537,6 +83792,94 @@ ${l}
83537
83792
  function getCellTotalLines(cell2) {
83538
83793
  return getCellLines(cell2).length;
83539
83794
  }
83795
+ function mergePmRange(target, range2) {
83796
+ if (typeof range2.pmStart === "number") {
83797
+ target.pmStart = target.pmStart == null ? range2.pmStart : Math.min(target.pmStart, range2.pmStart);
83798
+ }
83799
+ if (typeof range2.pmEnd === "number") {
83800
+ target.pmEnd = target.pmEnd == null ? range2.pmEnd : Math.max(target.pmEnd, range2.pmEnd);
83801
+ }
83802
+ }
83803
+ function computeCellPmRange(cell2, cellMeasure, fromLine, toLine) {
83804
+ const range2 = {};
83805
+ if (!cell2 || !cellMeasure) return range2;
83806
+ const cellBlocks = cell2.blocks ?? (cell2.paragraph ? [cell2.paragraph] : []);
83807
+ const blockMeasures = cellMeasure.blocks ?? (cellMeasure.paragraph ? [cellMeasure.paragraph] : []);
83808
+ const maxBlocks = Math.min(cellBlocks.length, blockMeasures.length);
83809
+ let cumulativeLineCount = 0;
83810
+ for (let i2 = 0; i2 < maxBlocks; i2++) {
83811
+ const block = cellBlocks[i2];
83812
+ const blockMeasure = blockMeasures[i2];
83813
+ if (blockMeasure.kind === "paragraph" && block?.kind === "paragraph") {
83814
+ const paraMeasure = blockMeasure;
83815
+ const lines = paraMeasure.lines;
83816
+ const blockLineCount = lines?.length ?? 0;
83817
+ const blockStartGlobal = cumulativeLineCount;
83818
+ const blockEndGlobal = cumulativeLineCount + blockLineCount;
83819
+ const localFrom = Math.max(fromLine, blockStartGlobal) - blockStartGlobal;
83820
+ const localTo = Math.min(toLine, blockEndGlobal) - blockStartGlobal;
83821
+ if (lines && lines.length > 0 && localFrom < localTo) {
83822
+ mergePmRange(range2, computeFragmentPmRange(block, lines, localFrom, localTo));
83823
+ } else {
83824
+ mergePmRange(range2, extractBlockPmRange(block));
83825
+ }
83826
+ cumulativeLineCount += blockLineCount;
83827
+ continue;
83828
+ }
83829
+ mergePmRange(range2, extractBlockPmRange(block));
83830
+ }
83831
+ return range2;
83832
+ }
83833
+ function computeTableFragmentPmRange(block, measure, fromRow, toRow, partialRow) {
83834
+ const range2 = {};
83835
+ for (let rowIndex = fromRow; rowIndex < toRow; rowIndex++) {
83836
+ const row2 = block.rows[rowIndex];
83837
+ const rowMeasure = measure.rows[rowIndex];
83838
+ if (!row2 || !rowMeasure) continue;
83839
+ const isPartial = partialRow?.rowIndex === rowIndex;
83840
+ const cellCount = Math.min(row2.cells.length, rowMeasure.cells.length);
83841
+ for (let cellIndex = 0; cellIndex < cellCount; cellIndex++) {
83842
+ const cell2 = row2.cells[cellIndex];
83843
+ const cellMeasure = rowMeasure.cells[cellIndex];
83844
+ if (!cell2 || !cellMeasure) continue;
83845
+ const totalLines = getCellTotalLines(cellMeasure);
83846
+ let fromLine = 0;
83847
+ let toLine = totalLines;
83848
+ if (isPartial) {
83849
+ const hasValidFromLineByCell = partialRow?.fromLineByCell && cellIndex < partialRow.fromLineByCell.length;
83850
+ const hasValidToLineByCell = partialRow?.toLineByCell && cellIndex < partialRow.toLineByCell.length;
83851
+ if (hasValidFromLineByCell) {
83852
+ const rawFrom = partialRow.fromLineByCell[cellIndex];
83853
+ if (typeof rawFrom === "number" && rawFrom >= 0) {
83854
+ fromLine = rawFrom;
83855
+ }
83856
+ }
83857
+ if (hasValidToLineByCell) {
83858
+ const rawTo = partialRow.toLineByCell[cellIndex];
83859
+ if (typeof rawTo === "number") {
83860
+ toLine = rawTo === -1 ? totalLines : rawTo;
83861
+ }
83862
+ }
83863
+ }
83864
+ fromLine = Math.max(0, Math.min(fromLine, totalLines));
83865
+ toLine = Math.max(0, Math.min(toLine, totalLines));
83866
+ if (toLine < fromLine) {
83867
+ toLine = fromLine;
83868
+ }
83869
+ mergePmRange(range2, computeCellPmRange(cell2, cellMeasure, fromLine, toLine));
83870
+ }
83871
+ }
83872
+ return range2;
83873
+ }
83874
+ function applyTableFragmentPmRange(fragment, block, measure) {
83875
+ const range2 = computeTableFragmentPmRange(block, measure, fragment.fromRow, fragment.toRow, fragment.partialRow);
83876
+ if (range2.pmStart != null) {
83877
+ fragment.pmStart = range2.pmStart;
83878
+ }
83879
+ if (range2.pmEnd != null) {
83880
+ fragment.pmEnd = range2.pmEnd;
83881
+ }
83882
+ }
83540
83883
  function computePartialRow(rowIndex, blockRow, measure, availableHeight, fromLineByCell) {
83541
83884
  const row2 = measure.rows[rowIndex];
83542
83885
  if (!row2) {
@@ -83681,6 +84024,7 @@ ${l}
83681
84024
  height,
83682
84025
  metadata
83683
84026
  };
84027
+ applyTableFragmentPmRange(fragment, context.block, context.measure);
83684
84028
  state2.page.fragments.push(fragment);
83685
84029
  state2.cursorY += height;
83686
84030
  }
@@ -83759,6 +84103,7 @@ ${l}
83759
84103
  height,
83760
84104
  metadata
83761
84105
  };
84106
+ applyTableFragmentPmRange(fragment, block, measure);
83762
84107
  state2.page.fragments.push(fragment);
83763
84108
  state2.cursorY += height;
83764
84109
  return;
@@ -83822,6 +84167,7 @@ ${l}
83822
84167
  partialRow: continuationPartialRow,
83823
84168
  metadata: generateFragmentMetadata(measure)
83824
84169
  };
84170
+ applyTableFragmentPmRange(fragment2, block, measure);
83825
84171
  state2.page.fragments.push(fragment2);
83826
84172
  state2.cursorY += fragmentHeight2;
83827
84173
  }
@@ -83866,6 +84212,7 @@ ${l}
83866
84212
  partialRow: forcedPartialRow,
83867
84213
  metadata: generateFragmentMetadata(measure)
83868
84214
  };
84215
+ applyTableFragmentPmRange(fragment2, block, measure);
83869
84216
  state2.page.fragments.push(fragment2);
83870
84217
  state2.cursorY += fragmentHeight2;
83871
84218
  pendingPartialRow = forcedPartialRow;
@@ -83901,6 +84248,7 @@ ${l}
83901
84248
  partialRow: partialRow || void 0,
83902
84249
  metadata: generateFragmentMetadata(measure)
83903
84250
  };
84251
+ applyTableFragmentPmRange(fragment, block, measure);
83904
84252
  state2.page.fragments.push(fragment);
83905
84253
  state2.cursorY += fragmentHeight;
83906
84254
  if (partialRow && !partialRow.isLastPart) {
@@ -83918,7 +84266,7 @@ ${l}
83918
84266
  columnBoundaries: generateColumnBoundaries(measure),
83919
84267
  coordinateSystem: "fragment"
83920
84268
  };
83921
- return {
84269
+ const fragment = {
83922
84270
  kind: "table",
83923
84271
  blockId: block.id,
83924
84272
  fromRow: 0,
@@ -83929,6 +84277,8 @@ ${l}
83929
84277
  height: measure.totalHeight ?? 0,
83930
84278
  metadata
83931
84279
  };
84280
+ applyTableFragmentPmRange(fragment, block, measure);
84281
+ return fragment;
83932
84282
  }
83933
84283
  function isPageRelativeAnchor(block) {
83934
84284
  const vRelativeFrom = block.anchor?.vRelativeFrom;
@@ -84350,8 +84700,8 @@ ${l}
84350
84700
  header: options.margins?.header ?? options.margins?.top ?? DEFAULT_MARGINS$2.top,
84351
84701
  footer: options.margins?.footer ?? options.margins?.bottom ?? DEFAULT_MARGINS$2.bottom
84352
84702
  };
84353
- const contentWidth = pageSize.w - (margins.left + margins.right);
84354
- if (contentWidth <= 0) {
84703
+ const baseContentWidth = pageSize.w - (margins.left + margins.right);
84704
+ if (baseContentWidth <= 0) {
84355
84705
  throw new Error("layoutDocument: pageSize and margins yield non-positive content area");
84356
84706
  }
84357
84707
  const validateContentHeight = (height) => {
@@ -84381,8 +84731,12 @@ ${l}
84381
84731
  const effectiveBottomMargin = maxFooterContentHeight > 0 ? Math.max(margins.bottom, footerDistance + maxFooterContentHeight) : margins.bottom;
84382
84732
  let activeTopMargin = effectiveTopMargin;
84383
84733
  let activeBottomMargin = effectiveBottomMargin;
84734
+ let activeLeftMargin = margins.left;
84735
+ let activeRightMargin = margins.right;
84384
84736
  let pendingTopMargin = null;
84385
84737
  let pendingBottomMargin = null;
84738
+ let pendingLeftMargin = null;
84739
+ let pendingRightMargin = null;
84386
84740
  let activeHeaderDistance = margins.header ?? margins.top;
84387
84741
  let pendingHeaderDistance = null;
84388
84742
  let activeFooterDistance = margins.footer ?? margins.bottom;
@@ -84395,10 +84749,11 @@ ${l}
84395
84749
  let pendingOrientation = null;
84396
84750
  let activeVAlign = null;
84397
84751
  let pendingVAlign = null;
84752
+ const paginatorMargins = { left: activeLeftMargin, right: activeRightMargin };
84398
84753
  const floatManager = createFloatingObjectManager(
84399
- normalizeColumns(activeColumns, contentWidth),
84400
- { left: margins.left, right: margins.right },
84401
- pageSize.w
84754
+ normalizeColumns(activeColumns, activePageSize.w - (activeLeftMargin + activeRightMargin)),
84755
+ { left: activeLeftMargin, right: activeRightMargin },
84756
+ activePageSize.w
84402
84757
  );
84403
84758
  const nextSectionPropsAtBreak = computeNextSectionPropsAtBreak(blocks2);
84404
84759
  const scheduleSectionBreakCompat = (block, state2, baseMargins) => {
@@ -84415,22 +84770,38 @@ ${l}
84415
84770
  next2.activeOrientation = block.orientation;
84416
84771
  next2.pendingOrientation = null;
84417
84772
  }
84773
+ const headerDistance2 = typeof block.margins?.header === "number" ? Math.max(0, block.margins.header) : next2.activeHeaderDistance;
84774
+ const footerDistance2 = typeof block.margins?.footer === "number" ? Math.max(0, block.margins.footer) : next2.activeFooterDistance;
84775
+ const sectionTop = typeof block.margins?.top === "number" ? Math.max(0, block.margins.top) : baseMargins.top;
84776
+ const sectionBottom = typeof block.margins?.bottom === "number" ? Math.max(0, block.margins.bottom) : baseMargins.bottom;
84418
84777
  if (block.margins?.header !== void 0) {
84419
- const headerDist = Math.max(0, block.margins.header);
84420
- next2.activeHeaderDistance = headerDist;
84421
- next2.pendingHeaderDistance = headerDist;
84422
- const requiredTop = maxHeaderContentHeight > 0 ? headerDist + maxHeaderContentHeight : headerDist;
84423
- next2.activeTopMargin = Math.max(baseMargins.top, requiredTop);
84424
- next2.pendingTopMargin = next2.activeTopMargin;
84778
+ next2.activeHeaderDistance = headerDistance2;
84779
+ next2.pendingHeaderDistance = headerDistance2;
84425
84780
  }
84426
84781
  if (block.margins?.footer !== void 0) {
84427
- const footerDistance2 = Math.max(0, block.margins.footer);
84428
84782
  next2.activeFooterDistance = footerDistance2;
84429
84783
  next2.pendingFooterDistance = footerDistance2;
84784
+ }
84785
+ if (block.margins?.top !== void 0 || block.margins?.header !== void 0) {
84786
+ const requiredTop = maxHeaderContentHeight > 0 ? headerDistance2 + maxHeaderContentHeight : headerDistance2;
84787
+ next2.activeTopMargin = Math.max(sectionTop, requiredTop);
84788
+ next2.pendingTopMargin = next2.activeTopMargin;
84789
+ }
84790
+ if (block.margins?.bottom !== void 0 || block.margins?.footer !== void 0) {
84430
84791
  const requiredBottom = maxFooterContentHeight > 0 ? footerDistance2 + maxFooterContentHeight : footerDistance2;
84431
- next2.activeBottomMargin = Math.max(baseMargins.bottom, requiredBottom);
84792
+ next2.activeBottomMargin = Math.max(sectionBottom, requiredBottom);
84432
84793
  next2.pendingBottomMargin = next2.activeBottomMargin;
84433
84794
  }
84795
+ if (block.margins?.left !== void 0) {
84796
+ const leftMargin = Math.max(0, block.margins.left);
84797
+ next2.activeLeftMargin = leftMargin;
84798
+ next2.pendingLeftMargin = leftMargin;
84799
+ }
84800
+ if (block.margins?.right !== void 0) {
84801
+ const rightMargin = Math.max(0, block.margins.right);
84802
+ next2.activeRightMargin = rightMargin;
84803
+ next2.pendingRightMargin = rightMargin;
84804
+ }
84434
84805
  if (block.columns) {
84435
84806
  next2.activeColumns = { count: block.columns.count, gap: block.columns.gap };
84436
84807
  next2.pendingColumns = null;
@@ -84459,27 +84830,35 @@ ${l}
84459
84830
  const headerPx = block.margins?.header;
84460
84831
  const footerPx = block.margins?.footer;
84461
84832
  const topPx = block.margins?.top;
84833
+ const bottomPx = block.margins?.bottom;
84834
+ const leftPx = block.margins?.left;
84835
+ const rightPx = block.margins?.right;
84462
84836
  const nextTop = next2.pendingTopMargin ?? next2.activeTopMargin;
84463
84837
  const nextBottom = next2.pendingBottomMargin ?? next2.activeBottomMargin;
84838
+ const nextLeft = next2.pendingLeftMargin ?? next2.activeLeftMargin;
84839
+ const nextRight = next2.pendingRightMargin ?? next2.activeRightMargin;
84464
84840
  const nextHeader = next2.pendingHeaderDistance ?? next2.activeHeaderDistance;
84465
84841
  const nextFooter = next2.pendingFooterDistance ?? next2.activeFooterDistance;
84466
84842
  next2.pendingHeaderDistance = typeof headerPx === "number" ? Math.max(0, headerPx) : nextHeader;
84467
84843
  next2.pendingFooterDistance = typeof footerPx === "number" ? Math.max(0, footerPx) : nextFooter;
84468
84844
  if (typeof headerPx === "number" || typeof topPx === "number") {
84469
- const sectionTop = topPx ?? baseMargins.top;
84845
+ const sectionTop = typeof topPx === "number" ? Math.max(0, topPx) : baseMargins.top;
84470
84846
  const sectionHeader = next2.pendingHeaderDistance;
84471
84847
  const requiredTop = maxHeaderContentHeight > 0 ? sectionHeader + maxHeaderContentHeight : sectionHeader;
84472
84848
  next2.pendingTopMargin = Math.max(sectionTop, requiredTop);
84473
84849
  } else {
84474
84850
  next2.pendingTopMargin = nextTop;
84475
84851
  }
84476
- if (typeof footerPx === "number") {
84852
+ if (typeof footerPx === "number" || typeof bottomPx === "number") {
84477
84853
  const sectionFooter = next2.pendingFooterDistance;
84854
+ const sectionBottom = typeof bottomPx === "number" ? Math.max(0, bottomPx) : baseMargins.bottom;
84478
84855
  const requiredBottom = maxFooterContentHeight > 0 ? sectionFooter + maxFooterContentHeight : sectionFooter;
84479
- next2.pendingBottomMargin = Math.max(baseMargins.bottom, requiredBottom);
84856
+ next2.pendingBottomMargin = Math.max(sectionBottom, requiredBottom);
84480
84857
  } else {
84481
84858
  next2.pendingBottomMargin = nextBottom;
84482
84859
  }
84860
+ next2.pendingLeftMargin = typeof leftPx === "number" ? Math.max(0, leftPx) : nextLeft;
84861
+ next2.pendingRightMargin = typeof rightPx === "number" ? Math.max(0, rightPx) : nextRight;
84483
84862
  if (block.pageSize) next2.pendingPageSize = { w: block.pageSize.w, h: block.pageSize.h };
84484
84863
  if (block.orientation) next2.pendingOrientation = block.orientation;
84485
84864
  const sectionType = block.type ?? "continuous";
@@ -84564,7 +84943,7 @@ ${l}
84564
84943
  let activeSectionIndex = initialSectionMetadata?.sectionIndex ?? 0;
84565
84944
  let pendingSectionIndex = null;
84566
84945
  const paginator = createPaginator({
84567
- margins: { left: margins.left, right: margins.right },
84946
+ margins: paginatorMargins,
84568
84947
  getActiveTopMargin: () => activeTopMargin,
84569
84948
  getActiveBottomMargin: () => activeBottomMargin,
84570
84949
  getActiveHeaderDistance: () => activeHeaderDistance,
@@ -84579,8 +84958,12 @@ ${l}
84579
84958
  const applied = applyPendingToActive({
84580
84959
  activeTopMargin,
84581
84960
  activeBottomMargin,
84961
+ activeLeftMargin,
84962
+ activeRightMargin,
84582
84963
  pendingTopMargin,
84583
84964
  pendingBottomMargin,
84965
+ pendingLeftMargin,
84966
+ pendingRightMargin,
84584
84967
  activeHeaderDistance,
84585
84968
  activeFooterDistance,
84586
84969
  pendingHeaderDistance,
@@ -84595,8 +84978,12 @@ ${l}
84595
84978
  });
84596
84979
  activeTopMargin = applied.activeTopMargin;
84597
84980
  activeBottomMargin = applied.activeBottomMargin;
84981
+ activeLeftMargin = applied.activeLeftMargin;
84982
+ activeRightMargin = applied.activeRightMargin;
84598
84983
  pendingTopMargin = applied.pendingTopMargin;
84599
84984
  pendingBottomMargin = applied.pendingBottomMargin;
84985
+ pendingLeftMargin = applied.pendingLeftMargin;
84986
+ pendingRightMargin = applied.pendingRightMargin;
84600
84987
  activeHeaderDistance = applied.activeHeaderDistance;
84601
84988
  activeFooterDistance = applied.activeFooterDistance;
84602
84989
  pendingHeaderDistance = applied.pendingHeaderDistance;
@@ -84608,6 +84995,14 @@ ${l}
84608
84995
  activeOrientation = applied.activeOrientation;
84609
84996
  pendingOrientation = applied.pendingOrientation;
84610
84997
  cachedColumnsState.state = null;
84998
+ paginatorMargins.left = activeLeftMargin;
84999
+ paginatorMargins.right = activeRightMargin;
85000
+ const contentWidth = activePageSize.w - (activeLeftMargin + activeRightMargin);
85001
+ floatManager.setLayoutContext(
85002
+ normalizeColumns(activeColumns, contentWidth),
85003
+ { left: activeLeftMargin, right: activeRightMargin },
85004
+ activePageSize.w
85005
+ );
84611
85006
  if (pendingNumbering) {
84612
85007
  if (pendingNumbering.format) activeNumberFormat = pendingNumbering.format;
84613
85008
  if (typeof pendingNumbering.start === "number" && Number.isFinite(pendingNumbering.start)) {
@@ -84652,7 +85047,7 @@ ${l}
84652
85047
  const getActiveColumnsForState = paginator.getActiveColumnsForState;
84653
85048
  let cachedColumnsState = { state: null, constraintIndex: -2, contentWidth: -1, colsConfig: null, normalized: null };
84654
85049
  const getCurrentColumns = () => {
84655
- const currentContentWidth = activePageSize.w - (margins.left + margins.right);
85050
+ const currentContentWidth = activePageSize.w - (activeLeftMargin + activeRightMargin);
84656
85051
  const state2 = states[states.length - 1] ?? null;
84657
85052
  const colsConfig = state2 ? getActiveColumnsForState(state2) : activeColumns;
84658
85053
  const constraintIndex = state2 ? state2.activeConstraintIndex : -1;
@@ -84685,6 +85080,12 @@ ${l}
84685
85080
  layoutLog(` Current page: ${state2.page.number}, cursorY: ${state2.cursorY}`);
84686
85081
  activeColumns = newColumns;
84687
85082
  cachedColumnsState.state = null;
85083
+ const contentWidth = activePageSize.w - (activeLeftMargin + activeRightMargin);
85084
+ floatManager.setLayoutContext(
85085
+ normalizeColumns(activeColumns, contentWidth),
85086
+ { left: activeLeftMargin, right: activeRightMargin },
85087
+ activePageSize.w
85088
+ );
84688
85089
  };
84689
85090
  const anchoredByParagraph = collectAnchoredDrawings(blocks2, measures);
84690
85091
  const anchoredTablesByParagraph = collectAnchoredTables(blocks2, measures);
@@ -84716,10 +85117,10 @@ ${l}
84716
85117
  if (alignV === "top") {
84717
85118
  anchorY = offsetV;
84718
85119
  } else if (alignV === "bottom") {
84719
- const pageHeight = contentBottom + margins.bottom;
85120
+ const pageHeight = contentBottom + (state2.page.margins?.bottom ?? activeBottomMargin);
84720
85121
  anchorY = pageHeight - imageHeight + offsetV;
84721
85122
  } else if (alignV === "center") {
84722
- const pageHeight = contentBottom + margins.bottom;
85123
+ const pageHeight = contentBottom + (state2.page.margins?.bottom ?? activeBottomMargin);
84723
85124
  anchorY = (pageHeight - imageHeight) / 2 + offsetV;
84724
85125
  } else {
84725
85126
  anchorY = offsetV;
@@ -84730,11 +85131,11 @@ ${l}
84730
85131
  const anchorX = entry.block.anchor ? computeAnchorX(
84731
85132
  entry.block.anchor,
84732
85133
  state2.columnIndex,
84733
- normalizeColumns(activeColumns, contentWidth),
85134
+ normalizeColumns(activeColumns, activePageSize.w - (activeLeftMargin + activeRightMargin)),
84734
85135
  entry.measure.width,
84735
- { left: margins.left, right: margins.right },
85136
+ { left: activeLeftMargin, right: activeRightMargin },
84736
85137
  activePageSize.w
84737
- ) : margins.left;
85138
+ ) : activeLeftMargin;
84738
85139
  floatManager.registerDrawing(entry.block, entry.measure, anchorY, state2.columnIndex, state2.page.number);
84739
85140
  preRegisteredPositions.set(entry.block.id, { anchorX, anchorY, pageNumber: state2.page.number });
84740
85141
  }
@@ -84772,8 +85173,12 @@ ${l}
84772
85173
  const sectionState = {
84773
85174
  activeTopMargin,
84774
85175
  activeBottomMargin,
85176
+ activeLeftMargin,
85177
+ activeRightMargin,
84775
85178
  pendingTopMargin,
84776
85179
  pendingBottomMargin,
85180
+ pendingLeftMargin,
85181
+ pendingRightMargin,
84777
85182
  activeHeaderDistance,
84778
85183
  activeFooterDistance,
84779
85184
  pendingHeaderDistance,
@@ -84807,8 +85212,12 @@ ${l}
84807
85212
  layoutLog(`[Layout] ========== END SECTION BREAK ==========`);
84808
85213
  activeTopMargin = updatedState.activeTopMargin;
84809
85214
  activeBottomMargin = updatedState.activeBottomMargin;
85215
+ activeLeftMargin = updatedState.activeLeftMargin;
85216
+ activeRightMargin = updatedState.activeRightMargin;
84810
85217
  pendingTopMargin = updatedState.pendingTopMargin;
84811
85218
  pendingBottomMargin = updatedState.pendingBottomMargin;
85219
+ pendingLeftMargin = updatedState.pendingLeftMargin;
85220
+ pendingRightMargin = updatedState.pendingRightMargin;
84812
85221
  activeHeaderDistance = updatedState.activeHeaderDistance;
84813
85222
  activeFooterDistance = updatedState.activeFooterDistance;
84814
85223
  pendingHeaderDistance = updatedState.pendingHeaderDistance;
@@ -84946,8 +85355,8 @@ ${l}
84946
85355
  pageMargins: {
84947
85356
  top: activeTopMargin,
84948
85357
  bottom: activeBottomMargin,
84949
- left: margins.left,
84950
- right: margins.right
85358
+ left: activeLeftMargin,
85359
+ right: activeRightMargin
84951
85360
  },
84952
85361
  columns: getCurrentColumns(),
84953
85362
  placedAnchoredIds
@@ -84969,9 +85378,9 @@ ${l}
84969
85378
  const cols = getCurrentColumns();
84970
85379
  let maxWidth;
84971
85380
  if (relativeFrom === "page") {
84972
- maxWidth = cols.count === 1 ? activePageSize.w - margins.left - margins.right : activePageSize.w;
85381
+ maxWidth = cols.count === 1 ? activePageSize.w - (activeLeftMargin + activeRightMargin) : activePageSize.w;
84973
85382
  } else if (relativeFrom === "margin") {
84974
- maxWidth = activePageSize.w - margins.left - margins.right;
85383
+ maxWidth = activePageSize.w - (activeLeftMargin + activeRightMargin);
84975
85384
  } else {
84976
85385
  maxWidth = cols.width;
84977
85386
  }
@@ -85131,6 +85540,9 @@ ${l}
85131
85540
  if (!Number.isFinite(height) || height <= 0) {
85132
85541
  throw new Error("layoutHeaderFooter: height must be positive");
85133
85542
  }
85543
+ const maxBehindDocOverflow = Math.max(192, height * 4);
85544
+ const minBehindDocY = -maxBehindDocOverflow;
85545
+ const maxBehindDocY = height + maxBehindDocOverflow;
85134
85546
  const marginLeft = constraints.margins?.left ?? 0;
85135
85547
  const transformedBlocks = marginLeft > 0 ? blocks2.map((block) => {
85136
85548
  const hasPageRelativeAnchor = (block.kind === "image" || block.kind === "drawing") && block.anchor?.hRelativeFrom === "page" && block.anchor.offsetH != null;
@@ -85161,6 +85573,18 @@ ${l}
85161
85573
  if (idx == null) continue;
85162
85574
  const block = blocks2[idx];
85163
85575
  const measure = measures[idx];
85576
+ const isAnchoredFragment = (fragment.kind === "image" || fragment.kind === "drawing") && fragment.isAnchored === true;
85577
+ if (isAnchoredFragment) {
85578
+ if (block.kind !== "image" && block.kind !== "drawing") {
85579
+ throw new Error(
85580
+ `Type mismatch: fragment kind is ${fragment.kind} but block kind is ${block.kind} for block ${block.id}`
85581
+ );
85582
+ }
85583
+ const anchoredBlock = block;
85584
+ if (anchoredBlock.anchor?.behindDoc && (fragment.y < minBehindDocY || fragment.y > maxBehindDocY)) {
85585
+ continue;
85586
+ }
85587
+ }
85164
85588
  if (fragment.y < minY) minY = fragment.y;
85165
85589
  let bottom2 = fragment.y;
85166
85590
  if (fragment.kind === "para" && measure?.kind === "paragraph") {
@@ -86158,11 +86582,11 @@ ${l}
86158
86582
  if (text2.length === 0) return null;
86159
86583
  const clampedPos = Math.max(0, Math.min(localPos, text2.length));
86160
86584
  let wordStart = clampedPos;
86161
- while (wordStart > 0 && isWordChar(text2[wordStart - 1])) {
86585
+ while (wordStart > 0 && isWordChar$2(text2[wordStart - 1])) {
86162
86586
  wordStart--;
86163
86587
  }
86164
86588
  let wordEnd = clampedPos;
86165
- while (wordEnd < text2.length && isWordChar(text2[wordEnd])) {
86589
+ while (wordEnd < text2.length && isWordChar$2(text2[wordEnd])) {
86166
86590
  wordEnd++;
86167
86591
  }
86168
86592
  if (wordStart === wordEnd) {
@@ -86225,7 +86649,7 @@ ${l}
86225
86649
  }
86226
86650
  return null;
86227
86651
  }
86228
- function isWordChar(char) {
86652
+ function isWordChar$2(char) {
86229
86653
  return /[\p{L}\p{N}_]/u.test(char);
86230
86654
  }
86231
86655
  function isWhitespace$1(char) {
@@ -86260,6 +86684,29 @@ ${l}
86260
86684
  function runText(run2) {
86261
86685
  return "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation" ? "" : run2.text ?? "";
86262
86686
  }
86687
+ const isWordChar$1 = (char) => {
86688
+ if (!char) return false;
86689
+ const code2 = char.charCodeAt(0);
86690
+ return code2 >= 48 && code2 <= 57 || code2 >= 65 && code2 <= 90 || code2 >= 97 && code2 <= 122 || char === "'";
86691
+ };
86692
+ const capitalizeText$1 = (text2, fullText, startOffset) => {
86693
+ if (!text2) return text2;
86694
+ const hasFullText = typeof startOffset === "number" && fullText != null;
86695
+ let result = "";
86696
+ for (let i2 = 0; i2 < text2.length; i2 += 1) {
86697
+ const prevChar = hasFullText ? startOffset + i2 > 0 ? fullText[startOffset + i2 - 1] : "" : i2 > 0 ? text2[i2 - 1] : "";
86698
+ const ch = text2[i2];
86699
+ result += isWordChar$1(ch) && !isWordChar$1(prevChar) ? ch.toUpperCase() : ch;
86700
+ }
86701
+ return result;
86702
+ };
86703
+ const applyTextTransform$1 = (text2, transform, fullText, startOffset) => {
86704
+ if (!text2 || !transform || transform === "none") return text2;
86705
+ if (transform === "uppercase") return text2.toUpperCase();
86706
+ if (transform === "lowercase") return text2.toLowerCase();
86707
+ if (transform === "capitalize") return capitalizeText$1(text2, fullText, startOffset);
86708
+ return text2;
86709
+ };
86263
86710
  const DEFAULT_TAB_INTERVAL_TWIPS$1 = 720;
86264
86711
  const TWIPS_PER_INCH$4 = 1440;
86265
86712
  const PX_PER_INCH$3 = 96;
@@ -86268,6 +86715,13 @@ ${l}
86268
86715
  const WIDTH_FUDGE_PX = 0.5;
86269
86716
  const twipsToPx$2 = (twips) => twips / TWIPS_PER_PX$1;
86270
86717
  const pxToTwips$1 = (px) => Math.round(px * TWIPS_PER_PX$1);
86718
+ const markerFontString = (run2) => {
86719
+ const size2 = run2?.fontSize ?? 16;
86720
+ const family = run2?.fontFamily ?? "Arial";
86721
+ const italic = run2?.italic ? "italic " : "";
86722
+ const bold = run2?.bold ? "bold " : "";
86723
+ return `${italic}${bold}${size2}px ${family}`.trim();
86724
+ };
86271
86725
  const buildTabStopsPx$1 = (indent2, tabs, tabIntervalTwips) => {
86272
86726
  const paragraphIndentTwips = {
86273
86727
  left: pxToTwips$1(Math.max(0, indent2?.left ?? 0)),
@@ -86298,7 +86752,9 @@ ${l}
86298
86752
  };
86299
86753
  function measureRunSliceWidth(run2, fromChar, toChar) {
86300
86754
  const context = getCtx();
86301
- const text2 = runText(run2).slice(fromChar, toChar);
86755
+ const fullText = runText(run2);
86756
+ const transform = isTextRun$2(run2) ? run2.textTransform : void 0;
86757
+ const text2 = applyTextTransform$1(fullText.slice(fromChar, toChar), transform, fullText, fromChar);
86302
86758
  if (!context) {
86303
86759
  const textRun = isTextRun$2(run2) ? run2 : null;
86304
86760
  const size2 = textRun?.fontSize ?? 16;
@@ -86344,8 +86800,21 @@ ${l}
86344
86800
  const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
86345
86801
  const markerTextStartX = wordLayout?.marker?.textStartX;
86346
86802
  const textStartPx = typeof markerTextStartX === "number" && Number.isFinite(markerTextStartX) ? markerTextStartX : typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : void 0;
86347
- const treatAsHanging = textStartPx && indentLeft === 0 && indentHanging === 0;
86348
- const firstLineWidth = typeof textStartPx === "number" && textStartPx > indentLeft && !treatAsHanging ? Math.max(1, maxWidth - textStartPx - indentRight) : Math.max(1, contentWidth - rawFirstLineOffset);
86803
+ const resolvedTextStartPx = resolveListTextStartPx(
86804
+ wordLayout,
86805
+ indentLeft,
86806
+ indentFirstLine,
86807
+ indentHanging,
86808
+ (markerText, marker) => {
86809
+ const context = getCtx();
86810
+ if (!context) return 0;
86811
+ context.font = markerFontString(marker.run);
86812
+ return context.measureText(markerText).width;
86813
+ }
86814
+ );
86815
+ const effectiveTextStartPx = resolvedTextStartPx ?? textStartPx;
86816
+ const treatAsHanging = !wordLayout?.marker && effectiveTextStartPx && indentLeft === 0 && indentHanging === 0;
86817
+ const firstLineWidth = typeof effectiveTextStartPx === "number" && effectiveTextStartPx > indentLeft && !treatAsHanging ? Math.max(1, maxWidth - effectiveTextStartPx - indentRight) : Math.max(1, contentWidth - rawFirstLineOffset);
86349
86818
  const tabStops = buildTabStopsPx$1(indent2, attrs?.tabs, attrs?.tabIntervalTwips);
86350
86819
  let currentRun = 0;
86351
86820
  let currentChar = 0;
@@ -86885,7 +87354,7 @@ ${l}
86885
87354
  if (dirty.deletedBlockIds.length > 0) {
86886
87355
  measureCache.invalidate(dirty.deletedBlockIds);
86887
87356
  }
86888
- const { measurementWidth, measurementHeight } = resolveMeasurementConstraints(options);
87357
+ const { measurementWidth, measurementHeight } = resolveMeasurementConstraints(options, nextBlocks);
86889
87358
  if (measurementWidth <= 0 || measurementHeight <= 0) {
86890
87359
  throw new Error("incrementalLayout: invalid measurement constraints resolved from options");
86891
87360
  }
@@ -87154,7 +87623,7 @@ ${l}
87154
87623
  const DEFAULT_PAGE_SIZE$1 = { w: 612, h: 792 };
87155
87624
  const DEFAULT_MARGINS$1 = { top: 72, right: 72, bottom: 72, left: 72 };
87156
87625
  const normalizeMargin = (value, fallback) => Number.isFinite(value) ? value : fallback;
87157
- function resolveMeasurementConstraints(options) {
87626
+ function resolveMeasurementConstraints(options, blocks2) {
87158
87627
  const pageSize = options.pageSize ?? DEFAULT_PAGE_SIZE$1;
87159
87628
  const margins = {
87160
87629
  top: normalizeMargin(options.margins?.top, DEFAULT_MARGINS$1.top),
@@ -87162,23 +87631,41 @@ ${l}
87162
87631
  bottom: normalizeMargin(options.margins?.bottom, DEFAULT_MARGINS$1.bottom),
87163
87632
  left: normalizeMargin(options.margins?.left, DEFAULT_MARGINS$1.left)
87164
87633
  };
87165
- const contentWidth = pageSize.w - (margins.left + margins.right);
87166
- const contentHeight = pageSize.h - (margins.top + margins.bottom);
87167
- const columns = options.columns;
87168
- if (columns && columns.count > 1) {
87634
+ const baseContentWidth = pageSize.w - (margins.left + margins.right);
87635
+ const baseContentHeight = pageSize.h - (margins.top + margins.bottom);
87636
+ const computeColumnWidth = (contentWidth, columns) => {
87637
+ if (!columns || columns.count <= 1) return contentWidth;
87169
87638
  const gap = Math.max(0, columns.gap ?? 0);
87170
87639
  const totalGap = gap * (columns.count - 1);
87171
- const columnWidth = (contentWidth - totalGap) / columns.count;
87172
- if (columnWidth > 0) {
87173
- return {
87174
- measurementWidth: columnWidth,
87175
- measurementHeight: contentHeight
87640
+ return (contentWidth - totalGap) / columns.count;
87641
+ };
87642
+ let measurementWidth = computeColumnWidth(baseContentWidth, options.columns);
87643
+ let measurementHeight = baseContentHeight;
87644
+ if (blocks2 && blocks2.length > 0) {
87645
+ for (const block of blocks2) {
87646
+ if (block.kind !== "sectionBreak") continue;
87647
+ const sectionPageSize = block.pageSize ?? pageSize;
87648
+ const sectionMargins = {
87649
+ top: normalizeMargin(block.margins?.top, margins.top),
87650
+ right: normalizeMargin(block.margins?.right, margins.right),
87651
+ bottom: normalizeMargin(block.margins?.bottom, margins.bottom),
87652
+ left: normalizeMargin(block.margins?.left, margins.left)
87176
87653
  };
87654
+ const contentWidth = sectionPageSize.w - (sectionMargins.left + sectionMargins.right);
87655
+ const contentHeight = sectionPageSize.h - (sectionMargins.top + sectionMargins.bottom);
87656
+ if (contentWidth <= 0 || contentHeight <= 0) continue;
87657
+ const columnWidth = computeColumnWidth(contentWidth, block.columns ?? options.columns);
87658
+ if (columnWidth > measurementWidth) {
87659
+ measurementWidth = columnWidth;
87660
+ }
87661
+ if (contentHeight > measurementHeight) {
87662
+ measurementHeight = contentHeight;
87663
+ }
87177
87664
  }
87178
87665
  }
87179
87666
  return {
87180
- measurementWidth: contentWidth,
87181
- measurementHeight: contentHeight
87667
+ measurementWidth,
87668
+ measurementHeight
87182
87669
  };
87183
87670
  }
87184
87671
  const serializeHeaderFooterResults = (kind, batch2) => {
@@ -89245,6 +89732,7 @@ ${l}
89245
89732
  }
89246
89733
  return false;
89247
89734
  }
89735
+ const SLASH_MENU_HANDLED_FLAG = "__sdHandledBySlashMenu";
89248
89736
  class PresentationInputBridge {
89249
89737
  /**
89250
89738
  * Creates a new PresentationInputBridge that forwards user input events from the visible layout
@@ -89458,6 +89946,10 @@ ${l}
89458
89946
  __privateMethod$1(this, _PresentationInputBridge_instances, dispatchToTarget_fn).call(this, event, synthetic);
89459
89947
  };
89460
89948
  forwardContextMenu_fn = function(event) {
89949
+ const handledBySlashMenu = Boolean(event[SLASH_MENU_HANDLED_FLAG]);
89950
+ if (handledBySlashMenu) {
89951
+ return;
89952
+ }
89461
89953
  if (!__privateGet$1(this, _isEditable).call(this)) {
89462
89954
  return;
89463
89955
  }
@@ -89563,14 +90055,15 @@ ${l}
89563
90055
  if (!schema) return [];
89564
90056
  const types2 = [];
89565
90057
  try {
89566
- schema.nodes.forEach((nodeType, name) => {
90058
+ for (const name in schema.nodes) {
89567
90059
  if (name === "text") {
89568
- return;
90060
+ continue;
89569
90061
  }
89570
- if (nodeType.isAtom || nodeType.isLeaf) {
90062
+ const nodeType = schema.nodes[name];
90063
+ if (nodeType && (nodeType.isAtom || nodeType.isLeaf)) {
89571
90064
  types2.push(name);
89572
90065
  }
89573
- });
90066
+ }
89574
90067
  } catch {
89575
90068
  return [];
89576
90069
  }
@@ -90973,6 +91466,7 @@ ${l}
90973
91466
  function hasIntrinsicBoundarySignals(_2) {
90974
91467
  return false;
90975
91468
  }
91469
+ const DEFAULT_HEADER_FOOTER_MARGIN_PX = 0;
90976
91470
  function shouldIgnoreSectionBreak(paragraph2, index2, total, hasBodySectPr) {
90977
91471
  const paragraphAttrs = paragraph2.attrs ?? {};
90978
91472
  const paragraphProperties = paragraphAttrs?.paragraphProperties;
@@ -91013,14 +91507,15 @@ ${l}
91013
91507
  const sectionData = extractSectionData(item.node);
91014
91508
  if (!sectionData) return;
91015
91509
  const sectPr = getSectPrFromNode(item.node);
91510
+ const hasAnyMargin = sectionData.headerPx != null || sectionData.footerPx != null || sectionData.topPx != null || sectionData.rightPx != null || sectionData.bottomPx != null || sectionData.leftPx != null;
91016
91511
  const range2 = {
91017
91512
  sectionIndex: idx,
91018
91513
  startParagraphIndex: currentStart,
91019
91514
  endParagraphIndex: item.index,
91020
91515
  sectPr,
91021
- margins: sectionData.headerPx != null || sectionData.footerPx != null ? {
91022
- header: sectionData.headerPx ?? 0,
91023
- footer: sectionData.footerPx ?? 0,
91516
+ margins: hasAnyMargin ? {
91517
+ header: sectionData.headerPx ?? DEFAULT_HEADER_FOOTER_MARGIN_PX,
91518
+ footer: sectionData.footerPx ?? DEFAULT_HEADER_FOOTER_MARGIN_PX,
91024
91519
  top: sectionData.topPx,
91025
91520
  right: sectionData.rightPx,
91026
91521
  bottom: sectionData.bottomPx,
@@ -91062,14 +91557,15 @@ ${l}
91062
91557
  };
91063
91558
  const bodySectionData = extractSectionData(tempNode);
91064
91559
  if (!bodySectionData) return null;
91560
+ const hasAnyMargin = bodySectionData.headerPx != null || bodySectionData.footerPx != null || bodySectionData.topPx != null || bodySectionData.rightPx != null || bodySectionData.bottomPx != null || bodySectionData.leftPx != null;
91065
91561
  return {
91066
91562
  sectionIndex,
91067
91563
  startParagraphIndex: currentStart,
91068
91564
  endParagraphIndex: totalParagraphs - 1,
91069
91565
  sectPr: bodySectPr,
91070
- margins: bodySectionData.headerPx != null || bodySectionData.footerPx != null ? {
91071
- header: bodySectionData.headerPx ?? 0,
91072
- footer: bodySectionData.footerPx ?? 0,
91566
+ margins: hasAnyMargin ? {
91567
+ header: bodySectionData.headerPx ?? DEFAULT_HEADER_FOOTER_MARGIN_PX,
91568
+ footer: bodySectionData.footerPx ?? DEFAULT_HEADER_FOOTER_MARGIN_PX,
91073
91569
  top: bodySectionData.topPx,
91074
91570
  right: bodySectionData.rightPx,
91075
91571
  bottom: bodySectionData.bottomPx,
@@ -92053,11 +92549,27 @@ ${l}
92053
92549
  }, void 0);
92054
92550
  };
92055
92551
  const normalizeUnderlineStyle = (value) => {
92056
- if (value === "none") {
92057
- return void 0;
92552
+ if (value === void 0 || value === null) {
92553
+ return "single";
92058
92554
  }
92059
- if (value === "double" || value === "dotted" || value === "dashed" || value === "wavy") {
92060
- return value;
92555
+ if (typeof value === "boolean") {
92556
+ return value ? "single" : void 0;
92557
+ }
92558
+ if (typeof value === "number") {
92559
+ return value === 0 ? void 0 : "single";
92560
+ }
92561
+ if (typeof value === "string") {
92562
+ const normalized = value.trim().toLowerCase();
92563
+ if (!normalized) {
92564
+ return "single";
92565
+ }
92566
+ if (normalized === "none" || normalized === "0" || normalized === "false" || normalized === "off") {
92567
+ return void 0;
92568
+ }
92569
+ if (normalized === "double" || normalized === "dotted" || normalized === "dashed" || normalized === "wavy") {
92570
+ return normalized;
92571
+ }
92572
+ return "single";
92061
92573
  }
92062
92574
  return "single";
92063
92575
  };
@@ -92209,13 +92721,16 @@ ${l}
92209
92721
  break;
92210
92722
  }
92211
92723
  case "underline": {
92212
- const style2 = normalizeUnderlineStyle(mark2.attrs?.underlineType);
92724
+ const underlineValue = mark2.attrs?.underlineType ?? mark2.attrs?.value ?? mark2.attrs?.underline ?? mark2.attrs?.style;
92725
+ const style2 = normalizeUnderlineStyle(underlineValue);
92213
92726
  if (style2) {
92214
92727
  const underlineColor = resolveColorFromAttributes(mark2.attrs ?? {}, themeColors);
92215
92728
  run2.underline = {
92216
92729
  style: style2,
92217
92730
  color: underlineColor ?? run2.underline?.color
92218
92731
  };
92732
+ } else if (underlineValue !== void 0 && underlineValue !== null) {
92733
+ delete run2.underline;
92219
92734
  }
92220
92735
  break;
92221
92736
  }
@@ -93151,8 +93666,8 @@ ${l}
93151
93666
  }
93152
93667
  return void 0;
93153
93668
  }
93154
- const DEFAULT_LIST_HANGING_PX$1 = 18;
93155
- const LIST_MARKER_GAP$1 = 8;
93669
+ const DEFAULT_LIST_HANGING_PX = 18;
93670
+ const LIST_MARKER_GAP = 8;
93156
93671
  const DEFAULT_BULLET_GLYPH = "•";
93157
93672
  const DEFAULT_DECIMAL_PATTERN = "%1.";
93158
93673
  const ASCII_UPPERCASE_A = 65;
@@ -93563,7 +94078,7 @@ ${l}
93563
94078
  let markerBoxWidthPx;
93564
94079
  let markerX;
93565
94080
  if (hasFirstLineIndent) {
93566
- markerBoxWidthPx = glyphWidthPx != null && glyphWidthPx > 0 ? glyphWidthPx + LIST_MARKER_GAP$1 : DEFAULT_LIST_HANGING_PX$1;
94081
+ markerBoxWidthPx = glyphWidthPx != null && glyphWidthPx > 0 ? glyphWidthPx + LIST_MARKER_GAP : DEFAULT_LIST_HANGING_PX;
93567
94082
  markerX = indentLeftPx + (firstLinePx ?? 0);
93568
94083
  layout.textStartPx = markerX + markerBoxWidthPx;
93569
94084
  layout.hangingPx = 0;
@@ -93663,12 +94178,12 @@ ${l}
93663
94178
  let markerBox = Math.max(hangingPxRaw || 0, 0);
93664
94179
  if (markerBox <= 0) {
93665
94180
  if (glyphWidthPx != null && glyphWidthPx > 0) {
93666
- markerBox = glyphWidthPx + LIST_MARKER_GAP$1;
94181
+ markerBox = glyphWidthPx + LIST_MARKER_GAP;
93667
94182
  } else {
93668
- markerBox = DEFAULT_LIST_HANGING_PX$1;
94183
+ markerBox = DEFAULT_LIST_HANGING_PX;
93669
94184
  }
93670
- } else if (glyphWidthPx != null && glyphWidthPx + LIST_MARKER_GAP$1 > markerBox) {
93671
- markerBox = glyphWidthPx + LIST_MARKER_GAP$1;
94185
+ } else if (glyphWidthPx != null && glyphWidthPx + LIST_MARKER_GAP > markerBox) {
94186
+ markerBox = glyphWidthPx + LIST_MARKER_GAP;
93672
94187
  }
93673
94188
  return markerBox;
93674
94189
  };
@@ -93688,7 +94203,7 @@ ${l}
93688
94203
  textStartX: textStartPx,
93689
94204
  baselineOffsetPx: markerRun.baselineShift ?? 0,
93690
94205
  // Gutter is the small gap between marker and text, not the full marker box width
93691
- gutterWidthPx: LIST_MARKER_GAP$1,
94206
+ gutterWidthPx: LIST_MARKER_GAP,
93692
94207
  justification: numbering.lvlJc ?? "left",
93693
94208
  suffix: normalizeSuffix$1(numbering.suffix) ?? "tab",
93694
94209
  run: markerRun,
@@ -93778,7 +94293,10 @@ ${l}
93778
94293
  tabStops: cloneIfObject(resolvedExtended.tabStops),
93779
94294
  keepLines: resolvedExtended.keepLines,
93780
94295
  keepNext: resolvedExtended.keepNext,
93781
- numberingProperties: cloneIfObject(resolvedAsRecord.numberingProperties)
94296
+ numberingProperties: cloneIfObject(resolvedAsRecord.numberingProperties),
94297
+ // Extract contextualSpacing from style resolution - this is a sibling to spacing in OOXML,
94298
+ // not nested within it. When true, suppresses spacing between paragraphs of the same style.
94299
+ contextualSpacing: resolvedExtended.contextualSpacing
93782
94300
  };
93783
94301
  return hydrated;
93784
94302
  };
@@ -94380,6 +94898,31 @@ ${l}
94380
94898
  return null;
94381
94899
  }
94382
94900
  };
94901
+ const normalizeWordLayoutForIndent = (wordLayout, paragraphIndent) => {
94902
+ const resolvedIndent = wordLayout.resolvedIndent ?? paragraphIndent ?? {};
94903
+ const indentLeft = isFiniteNumber(resolvedIndent.left) ? resolvedIndent.left : 0;
94904
+ const firstLine = isFiniteNumber(resolvedIndent.firstLine) ? resolvedIndent.firstLine : 0;
94905
+ const hanging = isFiniteNumber(resolvedIndent.hanging) ? resolvedIndent.hanging : 0;
94906
+ const shouldFirstLineIndentMode = firstLine > 0 && !hanging;
94907
+ if (wordLayout.firstLineIndentMode === true && !shouldFirstLineIndentMode) {
94908
+ wordLayout.firstLineIndentMode = false;
94909
+ }
94910
+ if (wordLayout.firstLineIndentMode === true) {
94911
+ if (isFiniteNumber(wordLayout.textStartPx)) {
94912
+ if (wordLayout.marker && (!isFiniteNumber(wordLayout.marker.textStartX) || wordLayout.marker.textStartX !== wordLayout.textStartPx)) {
94913
+ wordLayout.marker.textStartX = wordLayout.textStartPx;
94914
+ }
94915
+ } else if (wordLayout.marker && isFiniteNumber(wordLayout.marker.textStartX)) {
94916
+ wordLayout.textStartPx = wordLayout.marker.textStartX;
94917
+ }
94918
+ } else {
94919
+ wordLayout.textStartPx = indentLeft;
94920
+ if (wordLayout.marker) {
94921
+ wordLayout.marker.textStartX = indentLeft;
94922
+ }
94923
+ }
94924
+ return wordLayout;
94925
+ };
94383
94926
  const computeParagraphAttrs = (para, styleContext, listCounterContext, converterContext, hydrationOverride) => {
94384
94927
  const attrs = para.attrs ?? {};
94385
94928
  const paragraphProps = typeof attrs.paragraphProperties === "object" && attrs.paragraphProperties !== null ? attrs.paragraphProperties : {};
@@ -94488,7 +95031,7 @@ ${l}
94488
95031
  paragraphAttrs.spacing.afterAutospacing = normalizedSpacing.afterAutospacing;
94489
95032
  }
94490
95033
  }
94491
- const contextualSpacingValue = normalizedSpacing?.contextualSpacing ?? safeGetProperty(paragraphProps, "contextualSpacing") ?? safeGetProperty(attrs, "contextualSpacing");
95034
+ const contextualSpacingValue = normalizedSpacing?.contextualSpacing ?? safeGetProperty(paragraphProps, "contextualSpacing") ?? safeGetProperty(attrs, "contextualSpacing") ?? hydrated?.contextualSpacing;
94492
95035
  if (contextualSpacingValue != null) {
94493
95036
  paragraphAttrs.contextualSpacing = isTruthy(contextualSpacingValue);
94494
95037
  }
@@ -94702,8 +95245,11 @@ ${l}
94702
95245
  let wordLayout = computeWordLayoutForParagraph(paragraphAttrs, enrichedNumberingProps, styleContext);
94703
95246
  if (!wordLayout && enrichedNumberingProps.resolvedLevelIndent) {
94704
95247
  const resolvedIndentPx = convertIndentTwipsToPx(enrichedNumberingProps.resolvedLevelIndent);
94705
- const firstLinePx = resolvedIndentPx?.firstLine ?? 0;
94706
- if (firstLinePx > 0) {
95248
+ const baseIndent = resolvedIndentPx ?? enrichedNumberingProps.resolvedLevelIndent;
95249
+ const mergedIndent = { ...baseIndent, ...paragraphAttrs.indent ?? {} };
95250
+ const firstLinePx = isFiniteNumber(mergedIndent.firstLine) ? mergedIndent.firstLine : 0;
95251
+ const hangingPx = isFiniteNumber(mergedIndent.hanging) ? mergedIndent.hanging : 0;
95252
+ if (firstLinePx > 0 && !hangingPx) {
94707
95253
  wordLayout = {
94708
95254
  // Treat as first-line-indent mode: text starts after the marker+firstLine offset.
94709
95255
  firstLineIndentMode: true,
@@ -94711,10 +95257,13 @@ ${l}
94711
95257
  };
94712
95258
  }
94713
95259
  }
94714
- if (wordLayout && (!wordLayout.textStartPx || !Number.isFinite(wordLayout.textStartPx)) && enrichedNumberingProps.resolvedLevelIndent) {
95260
+ if (wordLayout && !Number.isFinite(wordLayout.textStartPx) && enrichedNumberingProps.resolvedLevelIndent) {
94715
95261
  const resolvedIndentPx = convertIndentTwipsToPx(enrichedNumberingProps.resolvedLevelIndent);
94716
- const firstLinePx = resolvedIndentPx?.firstLine ?? 0;
94717
- if (firstLinePx > 0) {
95262
+ const baseIndent = resolvedIndentPx ?? enrichedNumberingProps.resolvedLevelIndent;
95263
+ const mergedIndent = { ...baseIndent, ...paragraphAttrs.indent ?? {} };
95264
+ const firstLinePx = isFiniteNumber(mergedIndent.firstLine) ? mergedIndent.firstLine : 0;
95265
+ const hangingPx = isFiniteNumber(mergedIndent.hanging) ? mergedIndent.hanging : 0;
95266
+ if (firstLinePx > 0 && !hangingPx) {
94718
95267
  wordLayout = {
94719
95268
  ...wordLayout,
94720
95269
  firstLineIndentMode: wordLayout.firstLineIndentMode ?? true,
@@ -94734,6 +95283,7 @@ ${l}
94734
95283
  wordLayout.marker.suffix = listRendering.suffix;
94735
95284
  }
94736
95285
  }
95286
+ wordLayout = normalizeWordLayoutForIndent(wordLayout, paragraphAttrs.indent);
94737
95287
  paragraphAttrs.wordLayout = wordLayout;
94738
95288
  }
94739
95289
  if (enrichedNumberingProps.resolvedLevelIndent) {
@@ -98850,11 +99400,6 @@ ${l}
98850
99400
  cleanups
98851
99401
  };
98852
99402
  }
98853
- const LIST_MARKER_GAP = 8;
98854
- const MIN_MARKER_GUTTER = 24;
98855
- const DEFAULT_LIST_INDENT_BASE_PX = 24;
98856
- const DEFAULT_LIST_INDENT_STEP_PX = 24;
98857
- const DEFAULT_LIST_HANGING_PX = 18;
98858
99403
  function calculateRotatedBounds(input2) {
98859
99404
  const width = Math.max(0, input2.width);
98860
99405
  const height = Math.max(0, input2.height);
@@ -99024,7 +99569,7 @@ ${l}
99024
99569
  return Math.max(advanceWidth, paintedWidth);
99025
99570
  }
99026
99571
  const MIN_SINGLE_LINE_PX = 12 * 96 / 72;
99027
- const LINE_HEIGHT_SAFETY_MARGIN_PX = 1;
99572
+ const WORD_SINGLE_LINE_SPACING_MULTIPLIER = 1.15;
99028
99573
  function calculateTypographyMetrics(fontSize2, spacing, fontInfo) {
99029
99574
  let ascent;
99030
99575
  let descent;
@@ -99037,7 +99582,7 @@ ${l}
99037
99582
  ascent = roundValue(fontSize2 * 0.8);
99038
99583
  descent = roundValue(fontSize2 * 0.2);
99039
99584
  }
99040
- const baseLineHeight = Math.max(ascent + descent + LINE_HEIGHT_SAFETY_MARGIN_PX, MIN_SINGLE_LINE_PX);
99585
+ const baseLineHeight = Math.max(fontSize2 * WORD_SINGLE_LINE_SPACING_MULTIPLIER, ascent + descent, MIN_SINGLE_LINE_PX);
99041
99586
  const lineHeight2 = roundValue(resolveLineHeight(spacing, baseLineHeight));
99042
99587
  return {
99043
99588
  ascent,
@@ -99118,8 +99663,25 @@ ${l}
99118
99663
  const rawTextStartPx = wordLayout?.textStartPx;
99119
99664
  const markerTextStartX = wordLayout?.marker?.textStartX;
99120
99665
  const textStartPx = typeof markerTextStartX === "number" && Number.isFinite(markerTextStartX) ? markerTextStartX : typeof rawTextStartPx === "number" && Number.isFinite(rawTextStartPx) ? rawTextStartPx : void 0;
99121
- if (typeof textStartPx === "number" && textStartPx > indentLeft) {
99122
- initialAvailableWidth = Math.max(1, maxWidth - textStartPx - indentRight);
99666
+ const resolvedTextStartPx = resolveListTextStartPx(
99667
+ wordLayout,
99668
+ indentLeft,
99669
+ firstLine,
99670
+ hanging,
99671
+ (markerText, marker) => {
99672
+ const markerRun = {
99673
+ fontFamily: toCssFontFamily(marker.run?.fontFamily) ?? marker.run?.fontFamily ?? "Arial",
99674
+ fontSize: marker.run?.fontSize ?? 16,
99675
+ bold: marker.run?.bold ?? false,
99676
+ italic: marker.run?.italic ?? false
99677
+ };
99678
+ const { font: markerFont } = buildFontString(markerRun);
99679
+ return measureText(markerText, markerFont, ctx2);
99680
+ }
99681
+ );
99682
+ const effectiveTextStartPx = resolvedTextStartPx ?? textStartPx;
99683
+ if (typeof effectiveTextStartPx === "number" && effectiveTextStartPx > indentLeft) {
99684
+ initialAvailableWidth = Math.max(1, maxWidth - effectiveTextStartPx - indentRight);
99123
99685
  } else {
99124
99686
  initialAvailableWidth = Math.max(1, contentWidth - firstLineOffset);
99125
99687
  }
@@ -99206,7 +99768,7 @@ ${l}
99206
99768
  pendingTabAlignment = null;
99207
99769
  return startX;
99208
99770
  };
99209
- const alignSegmentAtTab = (segmentText, font, runContext) => {
99771
+ const alignSegmentAtTab = (segmentText, font, runContext, segmentStartChar) => {
99210
99772
  if (!pendingTabAlignment || !currentLine) return void 0;
99211
99773
  const { val } = pendingTabAlignment;
99212
99774
  let segmentWidth = 0;
@@ -99215,11 +99777,11 @@ ${l}
99215
99777
  const idx = segmentText.indexOf(decimalSeparator);
99216
99778
  if (idx >= 0) {
99217
99779
  const beforeText = segmentText.slice(0, idx);
99218
- beforeDecimalWidth = beforeText.length > 0 ? measureRunWidth(beforeText, font, ctx2, runContext) : 0;
99780
+ beforeDecimalWidth = beforeText.length > 0 ? measureRunWidth(beforeText, font, ctx2, runContext, segmentStartChar) : 0;
99219
99781
  }
99220
- segmentWidth = segmentText.length > 0 ? measureRunWidth(segmentText, font, ctx2, runContext) : 0;
99782
+ segmentWidth = segmentText.length > 0 ? measureRunWidth(segmentText, font, ctx2, runContext, segmentStartChar) : 0;
99221
99783
  } else if (val === "end" || val === "center") {
99222
- segmentWidth = segmentText.length > 0 ? measureRunWidth(segmentText, font, ctx2, runContext) : 0;
99784
+ segmentWidth = segmentText.length > 0 ? measureRunWidth(segmentText, font, ctx2, runContext, segmentStartChar) : 0;
99223
99785
  }
99224
99786
  return alignPendingTabForWidth(segmentWidth, beforeDecimalWidth);
99225
99787
  };
@@ -99271,8 +99833,8 @@ ${l}
99271
99833
  const { font } = buildFontString(
99272
99834
  lastRun
99273
99835
  );
99274
- const fullWidth = measureRunWidth(sliceText, font, ctx2, lastRun);
99275
- const keptWidth = keptText.length > 0 ? measureRunWidth(keptText, font, ctx2, lastRun) : 0;
99836
+ const fullWidth = measureRunWidth(sliceText, font, ctx2, lastRun, sliceStart);
99837
+ const keptWidth = keptText.length > 0 ? measureRunWidth(keptText, font, ctx2, lastRun, sliceStart) : 0;
99276
99838
  const delta = Math.max(0, fullWidth - keptWidth);
99277
99839
  lineToTrim.width = roundValue(Math.max(0, lineToTrim.width - delta));
99278
99840
  lineToTrim.spaceCount = Math.max(0, lineToTrim.spaceCount - trimCount);
@@ -99483,7 +100045,8 @@ ${l}
99483
100045
  continue;
99484
100046
  }
99485
100047
  if (isFieldAnnotationRun(run2)) {
99486
- const displayText = run2.displayLabel || "";
100048
+ const rawDisplayText = run2.displayLabel || "";
100049
+ const displayText = applyTextTransform(rawDisplayText, run2);
99487
100050
  const annotationFontSize = typeof run2.fontSize === "number" ? run2.fontSize : typeof run2.fontSize === "string" ? parseFloat(run2.fontSize) || DEFAULT_FIELD_ANNOTATION_FONT_SIZE : DEFAULT_FIELD_ANNOTATION_FONT_SIZE;
99488
100051
  const annotationFontFamily = run2.fontFamily || "Arial, sans-serif";
99489
100052
  const fontWeight = run2.bold ? "bold" : "normal";
@@ -99586,7 +100149,7 @@ ${l}
99586
100149
  const spacesLength = segment.length;
99587
100150
  const spacesStartChar = charPosInRun;
99588
100151
  const spacesEndChar = charPosInRun + spacesLength;
99589
- const spacesWidth = measureRunWidth(segment, font, ctx2, run2);
100152
+ const spacesWidth = measureRunWidth(segment, font, ctx2, run2, spacesStartChar);
99590
100153
  if (!currentLine) {
99591
100154
  currentLine = {
99592
100155
  fromRun: runIndex,
@@ -99650,7 +100213,7 @@ ${l}
99650
100213
  }
99651
100214
  let segmentStartX;
99652
100215
  if (currentLine && pendingTabAlignment) {
99653
- segmentStartX = alignSegmentAtTab(segment, font, run2);
100216
+ segmentStartX = alignSegmentAtTab(segment, font, run2, charPosInRun);
99654
100217
  if (segmentStartX == null) {
99655
100218
  segmentStartX = currentLine.width;
99656
100219
  }
@@ -99660,7 +100223,7 @@ ${l}
99660
100223
  if (word2 === "") {
99661
100224
  const spaceStartChar = charPosInRun;
99662
100225
  const spaceEndChar = charPosInRun + 1;
99663
- const singleSpaceWidth = measureRunWidth(" ", font, ctx2, run2);
100226
+ const singleSpaceWidth = measureRunWidth(" ", font, ctx2, run2, spaceStartChar);
99664
100227
  if (!currentLine) {
99665
100228
  currentLine = {
99666
100229
  fromRun: runIndex,
@@ -99711,12 +100274,12 @@ ${l}
99711
100274
  charPosInRun = spaceEndChar;
99712
100275
  continue;
99713
100276
  }
99714
- const wordOnlyWidth = measureRunWidth(word2, font, ctx2, run2);
99715
- const shouldIncludeDelimiterSpace = wordIndex < lastNonEmptyWordIndex;
99716
- const spaceWidth = shouldIncludeDelimiterSpace ? measureRunWidth(" ", font, ctx2, run2) : 0;
99717
- const wordCommitWidth = wordOnlyWidth + spaceWidth;
99718
100277
  const wordStartChar = charPosInRun;
100278
+ const wordOnlyWidth = measureRunWidth(word2, font, ctx2, run2, wordStartChar);
100279
+ const shouldIncludeDelimiterSpace = wordIndex < lastNonEmptyWordIndex;
99719
100280
  const wordEndNoSpace = charPosInRun + word2.length;
100281
+ const spaceWidth = shouldIncludeDelimiterSpace ? measureRunWidth(" ", font, ctx2, run2, wordEndNoSpace) : 0;
100282
+ const wordCommitWidth = wordOnlyWidth + spaceWidth;
99720
100283
  const wordEndWithSpace = wordEndNoSpace + (shouldIncludeDelimiterSpace ? 1 : 0);
99721
100284
  const effectiveMaxWidth = currentLine ? currentLine.maxWidth : getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : contentWidth);
99722
100285
  if (wordOnlyWidth > effectiveMaxWidth && word2.length > 1) {
@@ -99735,7 +100298,7 @@ ${l}
99735
100298
  const hasTabOnlyLine = currentLine && currentLine.segments && currentLine.segments.length === 0 && currentLine.width > 0;
99736
100299
  const remainingWidthAfterTab = hasTabOnlyLine ? currentLine.maxWidth - currentLine.width : lineMaxWidth;
99737
100300
  const chunkWidth = hasTabOnlyLine ? Math.max(remainingWidthAfterTab, lineMaxWidth * 0.25) : lineMaxWidth;
99738
- const chunks = breakWordIntoChunks(word2, chunkWidth - WIDTH_FUDGE_PX2, font, ctx2, run2);
100301
+ const chunks = breakWordIntoChunks(word2, chunkWidth - WIDTH_FUDGE_PX2, font, ctx2, run2, wordStartChar);
99739
100302
  let chunkCharOffset = wordStartChar;
99740
100303
  for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {
99741
100304
  const chunk = chunks[chunkIndex];
@@ -99859,7 +100422,7 @@ ${l}
99859
100422
  if (candidateSpaces > 0) {
99860
100423
  const overflow = totalWidthWithWord - availableWidth;
99861
100424
  if (overflow > 0) {
99862
- const baseSpaceWidth = spaceWidth || measureRunWidth(" ", font, ctx2, run2) || Math.max(1, boundarySpacing);
100425
+ const baseSpaceWidth = spaceWidth || measureRunWidth(" ", font, ctx2, run2, wordEndNoSpace) || Math.max(1, boundarySpacing);
99863
100426
  const perSpaceCompression = overflow / candidateSpaces;
99864
100427
  const maxPerSpaceCompression = baseSpaceWidth * 0.25;
99865
100428
  if (perSpaceCompression <= maxPerSpaceCompression) {
@@ -100034,8 +100597,8 @@ ${l}
100034
100597
  const { font: markerFont } = buildFontString(markerRun);
100035
100598
  const markerText = wordLayout.marker.markerText ?? "";
100036
100599
  const glyphWidth = markerText ? measureText(markerText, markerFont, ctx2) : 0;
100037
- const gutter = typeof wordLayout.marker.gutterWidthPx === "number" && isFinite(wordLayout.marker.gutterWidthPx) && wordLayout.marker.gutterWidthPx >= 0 ? wordLayout.marker.gutterWidthPx : LIST_MARKER_GAP;
100038
- const markerBoxWidth = Math.max(wordLayout.marker.markerBoxWidthPx ?? 0, glyphWidth + LIST_MARKER_GAP);
100600
+ const gutter = typeof wordLayout.marker.gutterWidthPx === "number" && isFinite(wordLayout.marker.gutterWidthPx) && wordLayout.marker.gutterWidthPx >= 0 ? wordLayout.marker.gutterWidthPx : LIST_MARKER_GAP$1;
100601
+ const markerBoxWidth = Math.max(wordLayout.marker.markerBoxWidthPx ?? 0, glyphWidth + LIST_MARKER_GAP$1);
100039
100602
  markerInfo = {
100040
100603
  markerWidth: markerBoxWidth,
100041
100604
  markerTextWidth: glyphWidth,
@@ -100379,7 +100942,7 @@ ${l}
100379
100942
  markerTextWidth = markerText ? measureText(markerText, markerFont, ctx2) : 0;
100380
100943
  indentLeft = resolveIndentLeft(item);
100381
100944
  const indentHanging = resolveIndentHanging(item);
100382
- markerWidth = Math.max(MIN_MARKER_GUTTER, markerTextWidth + LIST_MARKER_GAP, indentHanging);
100945
+ markerWidth = Math.max(MIN_MARKER_GUTTER, markerTextWidth + LIST_MARKER_GAP$1, indentHanging);
100383
100946
  }
100384
100947
  const paragraphWidth = Math.max(1, constraints.maxWidth - indentLeft - markerWidth);
100385
100948
  const paragraphMeasure = await measureParagraphBlock(item.paragraph, paragraphWidth);
@@ -100405,16 +100968,46 @@ ${l}
100405
100968
  fontSize: 16
100406
100969
  };
100407
100970
  };
100408
- const measureRunWidth = (text2, font, ctx2, run2) => {
100971
+ const isWordChar = (char) => {
100972
+ if (!char) return false;
100973
+ const code2 = char.charCodeAt(0);
100974
+ return code2 >= 48 && code2 <= 57 || code2 >= 65 && code2 <= 90 || code2 >= 97 && code2 <= 122 || char === "'";
100975
+ };
100976
+ const capitalizeText = (text2, fullText, startOffset) => {
100977
+ if (!text2) return text2;
100978
+ const hasFullText = typeof startOffset === "number" && fullText != null;
100979
+ let result = "";
100980
+ for (let i2 = 0; i2 < text2.length; i2 += 1) {
100981
+ const prevChar = hasFullText ? startOffset + i2 > 0 ? fullText[startOffset + i2 - 1] : "" : i2 > 0 ? text2[i2 - 1] : "";
100982
+ const ch = text2[i2];
100983
+ result += isWordChar(ch) && !isWordChar(prevChar) ? ch.toUpperCase() : ch;
100984
+ }
100985
+ return result;
100986
+ };
100987
+ const applyTextTransform = (text2, run2, startOffset) => {
100988
+ const transform = "textTransform" in run2 ? run2.textTransform : void 0;
100989
+ if (!text2 || !transform || transform === "none") return text2;
100990
+ if (transform === "uppercase") return text2.toUpperCase();
100991
+ if (transform === "lowercase") return text2.toLowerCase();
100992
+ if (transform === "capitalize") {
100993
+ const fullText = "text" in run2 && typeof run2.text === "string" ? run2.text : text2;
100994
+ return capitalizeText(text2, fullText, startOffset);
100995
+ }
100996
+ return text2;
100997
+ };
100998
+ const measureRunWidth = (text2, font, ctx2, run2, startOffset) => {
100409
100999
  const letterSpacing = run2.kind === "text" || run2.kind === void 0 ? run2.letterSpacing || 0 : 0;
100410
- const width = getMeasuredTextWidth(text2, font, letterSpacing, ctx2);
101000
+ const displayText = applyTextTransform(text2, run2, startOffset);
101001
+ const width = getMeasuredTextWidth(displayText, font, letterSpacing, ctx2);
100411
101002
  return roundValue(width);
100412
101003
  };
100413
- const breakWordIntoChunks = (word2, maxWidth, font, ctx2, run2) => {
101004
+ const breakWordIntoChunks = (word2, maxWidth, font, ctx2, run2, startOffset) => {
100414
101005
  const chunks = [];
101006
+ const baseOffset = typeof startOffset === "number" ? startOffset : 0;
100415
101007
  if (maxWidth <= 0) {
100416
- for (const char of word2) {
100417
- const charWidth = measureRunWidth(char, font, ctx2, run2);
101008
+ for (let i2 = 0; i2 < word2.length; i2++) {
101009
+ const char = word2[i2];
101010
+ const charWidth = measureRunWidth(char, font, ctx2, run2, baseOffset + i2);
100418
101011
  chunks.push({ text: char, width: charWidth });
100419
101012
  }
100420
101013
  return chunks;
@@ -100424,11 +101017,11 @@ ${l}
100424
101017
  for (let i2 = 0; i2 < word2.length; i2++) {
100425
101018
  const char = word2[i2];
100426
101019
  const testChunk = currentChunk + char;
100427
- const testWidth = measureRunWidth(testChunk, font, ctx2, run2);
101020
+ const testWidth = measureRunWidth(testChunk, font, ctx2, run2, baseOffset);
100428
101021
  if (testWidth > maxWidth && currentChunk.length > 0) {
100429
101022
  chunks.push({ text: currentChunk, width: currentWidth });
100430
101023
  currentChunk = char;
100431
- currentWidth = measureRunWidth(char, font, ctx2, run2);
101024
+ currentWidth = measureRunWidth(char, font, ctx2, run2, baseOffset + i2);
100432
101025
  } else {
100433
101026
  currentChunk = testChunk;
100434
101027
  currentWidth = testWidth;
@@ -100482,12 +101075,13 @@ ${l}
100482
101075
  italic: run2.italic
100483
101076
  });
100484
101077
  ctx2.font = font;
100485
- const metrics = ctx2.measureText(run2.text);
101078
+ const displayText = applyTextTransform(run2.text, run2);
101079
+ const metrics = ctx2.measureText(displayText);
100486
101080
  const advanceWidth = metrics.width;
100487
101081
  const paintedWidth = (metrics.actualBoundingBoxLeft || 0) + (metrics.actualBoundingBoxRight || 0);
100488
101082
  const textWidth = Math.max(advanceWidth, paintedWidth);
100489
101083
  const width = roundValue(textWidth + DROP_CAP_PADDING_PX);
100490
- const baseLineHeight = resolveLineHeight(spacing, run2.fontSize * 1.2);
101084
+ const baseLineHeight = resolveLineHeight(spacing, run2.fontSize * WORD_SINGLE_LINE_SPACING_MULTIPLIER);
100491
101085
  const height = roundValue(baseLineHeight * lines);
100492
101086
  return {
100493
101087
  width,
@@ -100508,7 +101102,7 @@ ${l}
100508
101102
  if (indentHanging > 0) {
100509
101103
  return indentHanging;
100510
101104
  }
100511
- return DEFAULT_LIST_HANGING_PX;
101105
+ return DEFAULT_LIST_HANGING_PX$1;
100512
101106
  };
100513
101107
  const buildTabStopsPx = (indent2, tabs, tabIntervalTwips) => {
100514
101108
  const paragraphIndentTwips = {
@@ -100714,6 +101308,9 @@ ${l}
100714
101308
  if (event.button !== 0) {
100715
101309
  return;
100716
101310
  }
101311
+ if (event.ctrlKey && navigator.platform.includes("Mac")) {
101312
+ return;
101313
+ }
100717
101314
  __privateSet(this, _pendingMarginClick, null);
100718
101315
  const target = event.target;
100719
101316
  if (target?.closest?.(".superdoc-ruler-handle") != null) {
@@ -106123,6 +106720,8 @@ ${l}
106123
106720
  const cbRect = containingBlock.getBoundingClientRect();
106124
106721
  left2 -= cbRect.left;
106125
106722
  top2 -= cbRect.top;
106723
+ left2 += containingBlock.scrollLeft || 0;
106724
+ top2 += containingBlock.scrollTop || 0;
106126
106725
  } catch (error) {
106127
106726
  console.warn("SlashMenu: Failed to adjust for containing block", error);
106128
106727
  }
@@ -137461,7 +138060,7 @@ ${style2}
137461
138060
  if (open) {
137462
138061
  nextTick(() => {
137463
138062
  if (searchInput.value) {
137464
- searchInput.value.focus();
138063
+ searchInput.value.focus({ preventScroll: true });
137465
138064
  }
137466
138065
  });
137467
138066
  }
@@ -137566,15 +138165,31 @@ ${style2}
137566
138165
  };
137567
138166
  const handleGlobalOutsideClick = (event) => {
137568
138167
  if (isOpen.value && menuRef.value && !menuRef.value.contains(event.target)) {
137569
- moveCursorToMouseEvent(event, props.editor);
138168
+ const isCtrlClickOnMac = event.ctrlKey && isMacOS();
138169
+ const isLeftClick = event.button === 0 && !isCtrlClickOnMac;
138170
+ if (isLeftClick) {
138171
+ moveCursorToMouseEvent(event, props.editor);
138172
+ }
137570
138173
  closeMenu({ restoreCursor: false });
137571
138174
  }
137572
138175
  };
137573
- const handleRightClick = async (event) => {
138176
+ const shouldHandleContextMenu = (event) => {
137574
138177
  const readOnly = !props.editor?.isEditable;
137575
138178
  const contextMenuDisabled = props.editor?.options?.disableContextMenu;
137576
138179
  const bypass = shouldBypassContextMenu(event);
137577
- if (readOnly || contextMenuDisabled || bypass) {
138180
+ return !readOnly && !contextMenuDisabled && !bypass;
138181
+ };
138182
+ const handleRightClickCapture = (event) => {
138183
+ try {
138184
+ if (shouldHandleContextMenu(event)) {
138185
+ event[SLASH_MENU_HANDLED_FLAG] = true;
138186
+ }
138187
+ } catch (error) {
138188
+ console.warn("[SlashMenu] Error in capture phase context menu handler:", error);
138189
+ }
138190
+ };
138191
+ const handleRightClick = async (event) => {
138192
+ if (!shouldHandleContextMenu(event)) {
137578
138193
  return;
137579
138194
  }
137580
138195
  event.preventDefault();
@@ -137685,6 +138300,7 @@ ${style2}
137685
138300
  props.editor.on("slashMenu:open", slashMenuOpenHandler);
137686
138301
  contextMenuTarget = getEditorSurfaceElement(props.editor);
137687
138302
  if (contextMenuTarget) {
138303
+ contextMenuTarget.addEventListener("contextmenu", handleRightClickCapture, true);
137688
138304
  contextMenuTarget.addEventListener("contextmenu", handleRightClick);
137689
138305
  }
137690
138306
  slashMenuCloseHandler = () => {
@@ -137708,6 +138324,7 @@ ${style2}
137708
138324
  props.editor.off("slashMenu:close", slashMenuCloseHandler);
137709
138325
  }
137710
138326
  props.editor.off("update", handleEditorUpdate);
138327
+ contextMenuTarget?.removeEventListener("contextmenu", handleRightClickCapture, true);
137711
138328
  contextMenuTarget?.removeEventListener("contextmenu", handleRightClick);
137712
138329
  } catch (error) {
137713
138330
  console.warn("[SlashMenu] Error during cleanup:", error);
@@ -139647,6 +140264,12 @@ ${style2}
139647
140264
  if (props.options?.suppressSkeletonLoader || !props.options?.collaborationProvider) editorReady.value = true;
139648
140265
  });
139649
140266
  const handleMarginClick = (event) => {
140267
+ if (event.button !== 0) {
140268
+ return;
140269
+ }
140270
+ if (event.ctrlKey && isMacOS()) {
140271
+ return;
140272
+ }
139650
140273
  if (event.target.classList.contains("ProseMirror")) return;
139651
140274
  onMarginClickCursorChange(event, activeEditor.value);
139652
140275
  };
@@ -139785,7 +140408,7 @@ ${style2}
139785
140408
  };
139786
140409
  }
139787
140410
  });
139788
- const SuperEditor = /* @__PURE__ */ _export_sfc$1(_sfc_main$1$1, [["__scopeId", "data-v-209a1e8b"]]);
140411
+ const SuperEditor = /* @__PURE__ */ _export_sfc$1(_sfc_main$1$1, [["__scopeId", "data-v-c9a3c876"]]);
139789
140412
  const _hoisted_1$h = ["innerHTML"];
139790
140413
  const _sfc_main$i = {
139791
140414
  __name: "SuperInput",
@@ -157239,7 +157862,7 @@ ${style2}
157239
157862
  this.config.colors = shuffleArray(this.config.colors);
157240
157863
  this.userColorMap = /* @__PURE__ */ new Map();
157241
157864
  this.colorIndex = 0;
157242
- this.version = "2.0.0-next.1";
157865
+ this.version = "2.0.0-next.11";
157243
157866
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
157244
157867
  this.superdocId = config2.superdocId || v4();
157245
157868
  this.colors = this.config.colors;
@@ -159712,7 +160335,7 @@ ${style2}
159712
160335
  value && typeof value === "object" && "byteLength" in value && "byteOffset" in value
159713
160336
  );
159714
160337
  }
159715
- const indexDq6vXk74 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
160338
+ const indexBym7r582 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
159716
160339
  __proto__: null,
159717
160340
  unified
159718
160341
  }, Symbol.toStringTag, { value: "Module" }));