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

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-Cun5Zr8u.cjs → PdfViewer-BPeCb-xB.cjs} +1 -1
  2. package/dist/chunks/{PdfViewer-BDQHgDVD.es.js → PdfViewer-CEK62Xt7.es.js} +1 -1
  3. package/dist/chunks/{index-Dq6vXk74-Vm-euNb7.cjs → index-BjfjH1jR-CqVyr7iV.cjs} +1 -1
  4. package/dist/chunks/{index-Dq6vXk74-CQD7nLbH.es.js → index-BjfjH1jR-DA6bQUce.es.js} +1 -1
  5. package/dist/chunks/{index-CGAmeAEK.es.js → index-D0T8-Wdm.es.js} +3 -3
  6. package/dist/chunks/{index-if-EH8uU.cjs → index-qzVJpQrS.cjs} +3 -3
  7. package/dist/chunks/{super-editor.es-CwNpXZzP.cjs → super-editor.es-B6s3KBGi.cjs} +778 -155
  8. package/dist/chunks/{super-editor.es-DyaHVXrq.es.js → super-editor.es-DYbXag4d.es.js} +778 -155
  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-WYQ7aFni.js} +45 -3
  13. package/dist/super-editor/chunks/{docx-zipper-CLkDdGOr.js → docx-zipper-ClbA5S-4.js} +1 -1
  14. package/dist/super-editor/chunks/{editor-COH8793Z.js → editor-CxwcruHz.js} +731 -167
  15. package/dist/super-editor/chunks/{index-Dq6vXk74.js → index-BjfjH1jR.js} +1 -1
  16. package/dist/super-editor/chunks/{toolbar-Ca-BPuJ2.js → toolbar-D-4TWvLd.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 +780 -157
  29. package/dist/superdoc.umd.js.map +1 -1
  30. package/package.json +1 -1
@@ -39199,11 +39199,15 @@ const encode$1 = (params2, encodedAttrs = {}) => {
39199
39199
  }
39200
39200
  if (elements.length === 1) {
39201
39201
  text = elements[0].text;
39202
- const xmlSpace = encodedAttrs.xmlSpace ?? elements[0]?.attributes?.["xml:space"];
39202
+ const docXmlSpace = params2.converter?.documentAttributes?.["xml:space"];
39203
+ const xmlSpace = encodedAttrs.xmlSpace ?? attributes?.["xml:space"] ?? elements[0]?.attributes?.["xml:space"] ?? docXmlSpace;
39203
39204
  if (xmlSpace !== "preserve" && typeof text === "string") {
39204
39205
  text = text.replace(/^[ \t\n\r]+/, "").replace(/[ \t\n\r]+$/, "");
39205
39206
  }
39206
39207
  text = text.replace(/\[\[sdspace\]\]/g, "");
39208
+ if (xmlSpace !== "preserve" && typeof text === "string" && !text.trim()) {
39209
+ return null;
39210
+ }
39207
39211
  } else if (!elements.length && encodedAttrs.xmlSpace === "preserve") {
39208
39212
  text = " ";
39209
39213
  } else return null;
@@ -42186,8 +42190,46 @@ const _SuperConverter = class _SuperConverter2 {
42186
42190
  this.declaration = this.initialJSON?.declaration;
42187
42191
  this.resolveDocumentGuid();
42188
42192
  }
42193
+ /**
42194
+ * Parses XML content into JSON format while preserving whitespace-only text runs.
42195
+ *
42196
+ * This method wraps xml-js's xml2json parser with additional preprocessing to prevent
42197
+ * the parser from dropping whitespace-only content in <w:t> and <w:delText> elements.
42198
+ * This is critical for correctly handling documents that rely on document-level
42199
+ * xml:space="preserve" rather than per-element attributes, which is common in
42200
+ * PDF-to-DOCX converted documents.
42201
+ *
42202
+ * The whitespace preservation strategy:
42203
+ * 1. Before parsing, wraps whitespace-only content with [[sdspace]] placeholders
42204
+ * 2. xml-js parser preserves the placeholder-wrapped text
42205
+ * 3. During text node processing (t-translator.js), placeholders are removed
42206
+ *
42207
+ * @param {string} xml - The XML string to parse
42208
+ * @returns {Object} The parsed JSON representation of the XML document
42209
+ *
42210
+ * @example
42211
+ * // Handles whitespace-only text runs
42212
+ * const xml = '<w:t> </w:t>';
42213
+ * const result = parseXmlToJson(xml);
42214
+ * // Result preserves the space: { elements: [{ text: '[[sdspace]] [[sdspace]]' }] }
42215
+ *
42216
+ * @example
42217
+ * // Handles elements with attributes
42218
+ * const xml = '<w:t xml:space="preserve"> text </w:t>';
42219
+ * const result = parseXmlToJson(xml);
42220
+ * // Preserves content and attributes
42221
+ *
42222
+ * @example
42223
+ * // Handles both w:t and w:delText elements
42224
+ * const xml = '<w:delText> </w:delText>';
42225
+ * const result = parseXmlToJson(xml);
42226
+ * // Preserves whitespace in deleted text
42227
+ */
42189
42228
  parseXmlToJson(xml) {
42190
- const newXml = xml.replace(/(<w:t xml:space="preserve">)(\s+)(<\/w:t>)/g, "$1[[sdspace]]$2[[sdspace]]$3");
42229
+ const newXml = xml.replace(
42230
+ /(<w:(?:t|delText)(?:\s[^>]*)?>)(\s+)(<\/w:(?:t|delText)>)/g,
42231
+ "$1[[sdspace]]$2[[sdspace]]$3"
42232
+ );
42191
42233
  return JSON.parse(xmljs.xml2json(newXml, null, 2));
42192
42234
  }
42193
42235
  /**
@@ -42410,7 +42452,7 @@ const _SuperConverter = class _SuperConverter2 {
42410
42452
  static getStoredSuperdocVersion(docx) {
42411
42453
  return _SuperConverter2.getStoredCustomProperty(docx, "SuperdocVersion");
42412
42454
  }
42413
- static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "2.0.0-next.1") {
42455
+ static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "2.0.0-next.10") {
42414
42456
  return _SuperConverter2.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
42415
42457
  }
42416
42458
  /**
@@ -60491,7 +60533,7 @@ const isHeadless = (editor) => {
60491
60533
  const shouldSkipNodeView = (editor) => {
60492
60534
  return isHeadless(editor);
60493
60535
  };
60494
- const summaryVersion = "2.0.0-next.1";
60536
+ const summaryVersion = "2.0.0-next.10";
60495
60537
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
60496
60538
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
60497
60539
  function mapAttributes(attrs) {
@@ -61280,7 +61322,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
61280
61322
  { default: remarkStringify },
61281
61323
  { default: remarkGfm }
61282
61324
  ] = await Promise.all([
61283
- import("./index-Dq6vXk74-CQD7nLbH.es.js"),
61325
+ import("./index-BjfjH1jR-DA6bQUce.es.js"),
61284
61326
  import("./index-DRCvimau-Cw339678.es.js"),
61285
61327
  import("./index-C_x_N6Uh-DJn8hIEt.es.js"),
61286
61328
  import("./index-D_sWOSiG-DE96TaT5.es.js"),
@@ -61485,7 +61527,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
61485
61527
  * Process collaboration migrations
61486
61528
  */
61487
61529
  processCollaborationMigrations() {
61488
- console.debug("[checkVersionMigrations] Current editor version", "2.0.0-next.1");
61530
+ console.debug("[checkVersionMigrations] Current editor version", "2.0.0-next.10");
61489
61531
  if (!this.options.ydoc) return;
61490
61532
  const metaMap = this.options.ydoc.getMap("meta");
61491
61533
  let docVersion = metaMap.get("version");
@@ -68737,7 +68779,7 @@ function isMinimalWordLayout(value) {
68737
68779
  return true;
68738
68780
  }
68739
68781
  const LIST_MARKER_GAP$2 = 8;
68740
- const DEFAULT_TAB_INTERVAL_PX$1 = 48;
68782
+ const DEFAULT_TAB_INTERVAL_PX$2 = 48;
68741
68783
  const DEFAULT_PAGE_HEIGHT_PX = 1056;
68742
68784
  const DEFAULT_VIRTUALIZED_PAGE_GAP$1 = 72;
68743
68785
  const COMMENT_EXTERNAL_COLOR = "#B1124B";
@@ -69664,6 +69706,7 @@ const _DomPainter = class _DomPainter2 {
69664
69706
  const block = lookup2.block;
69665
69707
  const measure = lookup2.measure;
69666
69708
  const wordLayout = isMinimalWordLayout(block.attrs?.wordLayout) ? block.attrs.wordLayout : void 0;
69709
+ const alignment2 = block.attrs?.alignment;
69667
69710
  const fragmentEl = this.doc.createElement("div");
69668
69711
  fragmentEl.classList.add(CLASS_NAMES$1.fragment);
69669
69712
  const isTocEntry = block.attrs?.isTocEntry;
@@ -69742,7 +69785,7 @@ const _DomPainter = class _DomPainter2 {
69742
69785
  const textStart = paraIndentLeft + firstLine;
69743
69786
  tabWidth = textStart - currentPos;
69744
69787
  if (tabWidth <= 0) {
69745
- tabWidth = DEFAULT_TAB_INTERVAL_PX$1 - currentPos % DEFAULT_TAB_INTERVAL_PX$1;
69788
+ tabWidth = DEFAULT_TAB_INTERVAL_PX$2 - currentPos % DEFAULT_TAB_INTERVAL_PX$2;
69746
69789
  } else if (tabWidth < LIST_MARKER_GAP$2) {
69747
69790
  tabWidth = LIST_MARKER_GAP$2;
69748
69791
  }
@@ -69769,6 +69812,21 @@ const _DomPainter = class _DomPainter2 {
69769
69812
  let availableWidthOverride = line.maxWidth != null ? Math.min(line.maxWidth, fallbackAvailableWidth) : fallbackAvailableWidth;
69770
69813
  if (index2 === 0 && listFirstLineMarkerTabWidth != null) {
69771
69814
  availableWidthOverride = fragment.width - listFirstLineMarkerTabWidth - Math.max(0, paraIndentRight);
69815
+ if (alignment2 === "justify" || alignment2 === "both") {
69816
+ console.log(
69817
+ "[justify-debug][painter-firstline-available]",
69818
+ JSON.stringify({
69819
+ blockId: block.id,
69820
+ fragmentWidth: fragment.width,
69821
+ markerTabWidth: listFirstLineMarkerTabWidth,
69822
+ paraIndentRight,
69823
+ availableWidthOverride,
69824
+ lineMaxWidth: line.maxWidth ?? null,
69825
+ lineWidth: line.width,
69826
+ lineNaturalWidth: line.naturalWidth ?? null
69827
+ })
69828
+ );
69829
+ }
69772
69830
  }
69773
69831
  const isLastLineOfFragment = index2 === lines.length - 1;
69774
69832
  const isLastLineOfParagraph = isLastLineOfFragment && !fragment.continuesOnNext;
@@ -69894,7 +69952,7 @@ const _DomPainter = class _DomPainter2 {
69894
69952
  const textStart = paraIndentLeft + firstLine;
69895
69953
  tabWidth = textStart - currentPos;
69896
69954
  if (tabWidth <= 0) {
69897
- tabWidth = DEFAULT_TAB_INTERVAL_PX$1 - currentPos % DEFAULT_TAB_INTERVAL_PX$1;
69955
+ tabWidth = DEFAULT_TAB_INTERVAL_PX$2 - currentPos % DEFAULT_TAB_INTERVAL_PX$2;
69898
69956
  } else if (tabWidth < LIST_MARKER_GAP$2) {
69899
69957
  tabWidth = LIST_MARKER_GAP$2;
69900
69958
  }
@@ -71428,6 +71486,23 @@ const _DomPainter = class _DomPainter2 {
71428
71486
  if (spacingPerSpace !== 0) {
71429
71487
  el.style.wordSpacing = `${spacingPerSpace}px`;
71430
71488
  }
71489
+ if (justifyShouldApply && spacingPerSpace < 0) {
71490
+ console.log(
71491
+ "[justify-debug][painter-wordspacing-negative]",
71492
+ JSON.stringify({
71493
+ blockId: block.id,
71494
+ lineIndex: lineIndex ?? null,
71495
+ alignment: alignment2 ?? null,
71496
+ availableWidth,
71497
+ lineWidth,
71498
+ lineMaxWidth: line.maxWidth ?? null,
71499
+ lineNaturalWidth: line.naturalWidth ?? null,
71500
+ spaceCount,
71501
+ hasExplicitPositioning: Boolean(hasExplicitPositioning),
71502
+ skipJustify: Boolean(skipJustify)
71503
+ })
71504
+ );
71505
+ }
71431
71506
  if (hasExplicitPositioning && line.segments) {
71432
71507
  const paraIndent = block.attrs?.indent;
71433
71508
  const indentLeft = paraIndent?.left ?? 0;
@@ -73621,6 +73696,28 @@ let measurementCtx = null;
73621
73696
  const TAB_CHAR_LENGTH = 1;
73622
73697
  const SPACE_CHARS = SPACE_CHARS$1;
73623
73698
  const isTabRun$1 = (run2) => run2?.kind === "tab";
73699
+ const isWordChar$3 = (char) => {
73700
+ if (!char) return false;
73701
+ const code = char.charCodeAt(0);
73702
+ return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || char === "'";
73703
+ };
73704
+ const capitalizeText$2 = (text) => {
73705
+ if (!text) return text;
73706
+ let result = "";
73707
+ for (let i = 0; i < text.length; i += 1) {
73708
+ const prevChar = i > 0 ? text[i - 1] : "";
73709
+ const ch = text[i];
73710
+ result += isWordChar$3(ch) && !isWordChar$3(prevChar) ? ch.toUpperCase() : ch;
73711
+ }
73712
+ return result;
73713
+ };
73714
+ const applyTextTransform$2 = (text, transform) => {
73715
+ if (!text || !transform || transform === "none") return text;
73716
+ if (transform === "uppercase") return text.toUpperCase();
73717
+ if (transform === "lowercase") return text.toLowerCase();
73718
+ if (transform === "capitalize") return capitalizeText$2(text);
73719
+ return text;
73720
+ };
73624
73721
  function getMeasurementContext() {
73625
73722
  if (measurementCtx) return measurementCtx;
73626
73723
  if (typeof document === "undefined") {
@@ -73796,17 +73893,19 @@ function measureCharacterX(block, line, charOffset, availableWidthOverride, alig
73796
73893
  }
73797
73894
  const text = "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation" ? "" : run2.text ?? "";
73798
73895
  const runLength = text.length;
73896
+ const transform = isTabRun$1(run2) || "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation" ? void 0 : run2.textTransform;
73897
+ const displayText = applyTextTransform$2(text, transform);
73799
73898
  if (currentCharOffset + runLength >= charOffset) {
73800
73899
  const offsetInRun = charOffset - currentCharOffset;
73801
73900
  ctx2.font = getRunFontString(run2);
73802
- const textUpToTarget = text.slice(0, offsetInRun);
73901
+ const textUpToTarget = displayText.slice(0, offsetInRun);
73803
73902
  const measured2 = ctx2.measureText(textUpToTarget);
73804
73903
  const spacingWidth = computeLetterSpacingWidth(run2, offsetInRun, runLength);
73805
- const spacesInPortion = justify.extraPerSpace !== 0 ? countSpaces(textUpToTarget) : 0;
73904
+ const spacesInPortion = justify.extraPerSpace !== 0 ? countSpaces(text.slice(0, offsetInRun)) : 0;
73806
73905
  return alignmentOffset + currentX + measured2.width + spacingWidth + justify.extraPerSpace * (spaceTally + spacesInPortion);
73807
73906
  }
73808
73907
  ctx2.font = getRunFontString(run2);
73809
- const measured = ctx2.measureText(text);
73908
+ const measured = ctx2.measureText(displayText);
73810
73909
  const runLetterSpacing = computeLetterSpacingWidth(run2, runLength, runLength);
73811
73910
  const spacesInRun = justify.extraPerSpace !== 0 ? countSpaces(text) : 0;
73812
73911
  currentX += measured.width + runLetterSpacing + justify.extraPerSpace * spacesInRun;
@@ -73845,8 +73944,10 @@ function measureCharacterXSegmentBased(block, line, charOffset, ctx2) {
73845
73944
  return segmentBaseX + (offsetInSegment >= segmentChars ? segment.width ?? 0 : 0);
73846
73945
  }
73847
73946
  const text = run2.text ?? "";
73848
- const segmentText = text.slice(segment.fromChar, segment.toChar);
73849
- const textUpToTarget = segmentText.slice(0, offsetInSegment);
73947
+ const transform = "textTransform" in run2 ? run2.textTransform : void 0;
73948
+ const displayText = applyTextTransform$2(text, transform);
73949
+ const displaySegmentText = displayText.slice(segment.fromChar, segment.toChar);
73950
+ const textUpToTarget = displaySegmentText.slice(0, offsetInSegment);
73850
73951
  ctx2.font = getRunFontString(run2);
73851
73952
  const measured = ctx2.measureText(textUpToTarget);
73852
73953
  const spacingWidth = computeLetterSpacingWidth(run2, offsetInSegment, segmentChars);
@@ -73942,12 +74043,14 @@ function findCharacterAtX(block, line, x2, pmStart, availableWidthOverride, alig
73942
74043
  }
73943
74044
  const text = "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation" ? "" : run2.text ?? "";
73944
74045
  const runLength = text.length;
74046
+ const transform = isTabRun$1(run2) || "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation" ? void 0 : run2.textTransform;
74047
+ const displayText = applyTextTransform$2(text, transform);
73945
74048
  if (runLength === 0) continue;
73946
74049
  ctx2.font = getRunFontString(run2);
73947
74050
  for (let i = 0; i <= runLength; i++) {
73948
- const textUpToChar = text.slice(0, i);
74051
+ const textUpToChar = displayText.slice(0, i);
73949
74052
  const measured2 = ctx2.measureText(textUpToChar);
73950
- const spacesInPortion = justify.extraPerSpace > 0 ? countSpaces(textUpToChar) : 0;
74053
+ const spacesInPortion = justify.extraPerSpace > 0 ? countSpaces(text.slice(0, i)) : 0;
73951
74054
  const charX = currentX + measured2.width + computeLetterSpacingWidth(run2, i, runLength) + justify.extraPerSpace * (spaceTally + spacesInPortion);
73952
74055
  if (charX >= safeX) {
73953
74056
  if (i === 0) {
@@ -73957,7 +74060,7 @@ function findCharacterAtX(block, line, x2, pmStart, availableWidthOverride, alig
73957
74060
  pmPosition: pmPosition3
73958
74061
  };
73959
74062
  }
73960
- const prevText = text.slice(0, i - 1);
74063
+ const prevText = displayText.slice(0, i - 1);
73961
74064
  const prevMeasured = ctx2.measureText(prevText);
73962
74065
  const prevX = currentX + prevMeasured.width + computeLetterSpacingWidth(run2, i - 1, runLength);
73963
74066
  const distToPrev = Math.abs(safeX - prevX);
@@ -73970,7 +74073,7 @@ function findCharacterAtX(block, line, x2, pmStart, availableWidthOverride, alig
73970
74073
  };
73971
74074
  }
73972
74075
  }
73973
- const measured = ctx2.measureText(text);
74076
+ const measured = ctx2.measureText(displayText);
73974
74077
  const runLetterSpacing = computeLetterSpacingWidth(run2, runLength, runLength);
73975
74078
  const spacesInRun = justify.extraPerSpace > 0 ? countSpaces(text) : 0;
73976
74079
  currentX += measured.width + runLetterSpacing + justify.extraPerSpace * spacesInRun;
@@ -74401,6 +74504,83 @@ function findCharIndexAtX(textNode, container, targetX) {
74401
74504
  }
74402
74505
  return index2;
74403
74506
  }
74507
+ const LIST_MARKER_GAP$1 = 8;
74508
+ const MIN_MARKER_GUTTER = 24;
74509
+ const DEFAULT_LIST_INDENT_BASE_PX = 24;
74510
+ const DEFAULT_LIST_INDENT_STEP_PX = 24;
74511
+ const DEFAULT_LIST_HANGING_PX$1 = 18;
74512
+ const SPACE_SUFFIX_GAP_PX = 4;
74513
+ const DEFAULT_TAB_INTERVAL_PX$1 = 48;
74514
+ function resolveListTextStartPx(wordLayout, indentLeft, firstLine, hanging, measureMarkerText) {
74515
+ const marker = wordLayout?.marker;
74516
+ if (!marker) {
74517
+ const textStartPx = wordLayout?.firstLineIndentMode === true && typeof wordLayout.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : void 0;
74518
+ return textStartPx;
74519
+ }
74520
+ const markerBoxWidth = typeof marker.markerBoxWidthPx === "number" && Number.isFinite(marker.markerBoxWidthPx) ? marker.markerBoxWidthPx : 0;
74521
+ let markerTextWidth = typeof marker.glyphWidthPx === "number" && Number.isFinite(marker.glyphWidthPx) ? marker.glyphWidthPx : void 0;
74522
+ if (markerTextWidth == null && marker.markerText) {
74523
+ markerTextWidth = measureMarkerText(marker.markerText, marker);
74524
+ }
74525
+ if (!Number.isFinite(markerTextWidth) || markerTextWidth !== void 0 && markerTextWidth < 0) {
74526
+ markerTextWidth = markerBoxWidth;
74527
+ }
74528
+ const finalMarkerTextWidth = Math.max(0, markerTextWidth ?? 0);
74529
+ let markerStartPos;
74530
+ if (wordLayout?.firstLineIndentMode === true && typeof marker.markerX === "number" && Number.isFinite(marker.markerX)) {
74531
+ markerStartPos = marker.markerX;
74532
+ } else {
74533
+ markerStartPos = indentLeft - hanging + firstLine;
74534
+ }
74535
+ if (!Number.isFinite(markerStartPos)) {
74536
+ markerStartPos = 0;
74537
+ }
74538
+ const currentPos = markerStartPos + finalMarkerTextWidth;
74539
+ const suffix2 = marker.suffix ?? "tab";
74540
+ if (suffix2 === "space") {
74541
+ return markerStartPos + finalMarkerTextWidth + SPACE_SUFFIX_GAP_PX;
74542
+ }
74543
+ if (suffix2 === "nothing") {
74544
+ return markerStartPos + finalMarkerTextWidth;
74545
+ }
74546
+ const markerJustification = marker.justification ?? "left";
74547
+ if (markerJustification !== "left") {
74548
+ const gutterWidth = typeof marker.gutterWidthPx === "number" && Number.isFinite(marker.gutterWidthPx) && marker.gutterWidthPx > 0 ? marker.gutterWidthPx : LIST_MARKER_GAP$1;
74549
+ return markerStartPos + finalMarkerTextWidth + Math.max(gutterWidth, LIST_MARKER_GAP$1);
74550
+ }
74551
+ if (wordLayout?.firstLineIndentMode === true) {
74552
+ let targetTabStop;
74553
+ if (Array.isArray(wordLayout.tabsPx)) {
74554
+ for (const tab of wordLayout.tabsPx) {
74555
+ if (typeof tab === "number" && tab > currentPos) {
74556
+ targetTabStop = tab;
74557
+ break;
74558
+ }
74559
+ }
74560
+ }
74561
+ const textStartTarget = typeof marker.textStartX === "number" && Number.isFinite(marker.textStartX) ? marker.textStartX : wordLayout.textStartPx;
74562
+ let tabWidth2;
74563
+ if (targetTabStop !== void 0) {
74564
+ tabWidth2 = targetTabStop - currentPos;
74565
+ } else if (textStartTarget !== void 0 && Number.isFinite(textStartTarget) && textStartTarget > currentPos) {
74566
+ tabWidth2 = textStartTarget - currentPos;
74567
+ } else {
74568
+ tabWidth2 = LIST_MARKER_GAP$1;
74569
+ }
74570
+ if (tabWidth2 < LIST_MARKER_GAP$1) {
74571
+ tabWidth2 = LIST_MARKER_GAP$1;
74572
+ }
74573
+ return markerStartPos + finalMarkerTextWidth + tabWidth2;
74574
+ }
74575
+ const textStart = indentLeft + firstLine;
74576
+ let tabWidth = textStart - currentPos;
74577
+ if (tabWidth <= 0) {
74578
+ tabWidth = DEFAULT_TAB_INTERVAL_PX$1 - currentPos % DEFAULT_TAB_INTERVAL_PX$1;
74579
+ } else if (tabWidth < LIST_MARKER_GAP$1) {
74580
+ tabWidth = LIST_MARKER_GAP$1;
74581
+ }
74582
+ return markerStartPos + finalMarkerTextWidth + tabWidth;
74583
+ }
74404
74584
  function getWordLayoutConfig(block) {
74405
74585
  if (!block || block.kind !== "paragraph") {
74406
74586
  return void 0;
@@ -74433,9 +74613,16 @@ function calculateTextStartIndent(params2) {
74433
74613
  const isFirstLineIndentMode = wordLayout?.firstLineIndentMode === true;
74434
74614
  let indentAdjust = paraIndentLeft;
74435
74615
  if (isListItem2 && isFirstLine && isFirstLineIndentMode) {
74616
+ const resolvedTextStart = resolveListTextStartPx(
74617
+ wordLayout,
74618
+ paraIndentLeft,
74619
+ Math.max(firstLineIndent, 0),
74620
+ Math.max(hangingIndent, 0),
74621
+ () => markerWidth
74622
+ // Use provided markerWidth since we don't have canvas access here
74623
+ );
74436
74624
  const textStartFallback = paraIndentLeft + Math.max(firstLineIndent, 0) + markerWidth;
74437
- const markerTextStartX = wordLayout?.marker?.textStartX;
74438
- indentAdjust = typeof markerTextStartX === "number" && Number.isFinite(markerTextStartX) ? markerTextStartX : typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : textStartFallback;
74625
+ indentAdjust = typeof resolvedTextStart === "number" && Number.isFinite(resolvedTextStart) ? resolvedTextStart : textStartFallback;
74439
74626
  } else if (isFirstLine && !isListItem2) {
74440
74627
  indentAdjust += firstLineOffset;
74441
74628
  }
@@ -74591,7 +74778,10 @@ function getHeaderFooterTypeForSection(pageNumber, sectionIndex, identifier, opt
74591
74778
  }
74592
74779
  function createFloatingObjectManager(columns, margins, pageWidth) {
74593
74780
  const zones = [];
74594
- const marginLeft = Math.max(0, margins?.left ?? 0);
74781
+ let currentColumns = columns;
74782
+ let currentMargins = margins;
74783
+ let currentPageWidth = pageWidth;
74784
+ let marginLeft = Math.max(0, currentMargins?.left ?? 0);
74595
74785
  return {
74596
74786
  registerDrawing(drawingBlock, measure, anchorY, columnIndex, pageNumber) {
74597
74787
  if (!drawingBlock.anchor?.isAnchored) {
@@ -74604,7 +74794,7 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
74604
74794
  }
74605
74795
  const objectWidth = measure.width ?? 0;
74606
74796
  const objectHeight = measure.height ?? 0;
74607
- const x2 = computeAnchorX(anchor, columnIndex, columns, objectWidth, margins, pageWidth);
74797
+ const x2 = computeAnchorX(anchor, columnIndex, currentColumns, objectWidth, currentMargins, currentPageWidth);
74608
74798
  const y2 = anchorY + (anchor.offsetV ?? 0);
74609
74799
  const zone = {
74610
74800
  imageBlockId: drawingBlock.id,
@@ -74638,7 +74828,7 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
74638
74828
  }
74639
74829
  const tableWidth = measure.totalWidth ?? 0;
74640
74830
  const tableHeight = measure.totalHeight ?? 0;
74641
- const x2 = computeTableAnchorX(anchor, columnIndex, columns, tableWidth, margins, pageWidth);
74831
+ const x2 = computeTableAnchorX(anchor, columnIndex, currentColumns, tableWidth, currentMargins, currentPageWidth);
74642
74832
  const y2 = anchorY + (anchor.offsetV ?? 0);
74643
74833
  const zone = {
74644
74834
  imageBlockId: tableBlock.id,
@@ -74686,7 +74876,7 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
74686
74876
  }
74687
74877
  const leftFloats = [];
74688
74878
  const rightFloats = [];
74689
- const columnOrigin = marginLeft + columnIndex * (columns.width + columns.gap);
74879
+ const columnOrigin = marginLeft + columnIndex * (currentColumns.width + currentColumns.gap);
74690
74880
  const columnCenter = columnOrigin + baseWidth / 2;
74691
74881
  for (const zone of wrappingZones) {
74692
74882
  if (zone.wrapMode === "left") {
@@ -74725,6 +74915,22 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
74725
74915
  },
74726
74916
  clear() {
74727
74917
  zones.length = 0;
74918
+ },
74919
+ /**
74920
+ * Update layout context used for positioning and wrapping (columns, margins, page width).
74921
+ * This method should be called when the layout configuration changes (e.g., section breaks,
74922
+ * column changes, page size changes) to ensure floating objects are positioned and wrapped
74923
+ * correctly relative to the new layout boundaries.
74924
+ *
74925
+ * @param nextColumns - Column layout configuration (width, gap, count)
74926
+ * @param nextMargins - Optional page margins (left, right) in pixels
74927
+ * @param nextPageWidth - Optional total page width in pixels
74928
+ */
74929
+ setLayoutContext(nextColumns, nextMargins, nextPageWidth) {
74930
+ currentColumns = nextColumns;
74931
+ currentMargins = nextMargins;
74932
+ currentPageWidth = nextPageWidth;
74933
+ marginLeft = Math.max(0, currentMargins?.left ?? 0);
74728
74934
  }
74729
74935
  };
74730
74936
  }
@@ -74824,7 +75030,14 @@ function computeNextSectionPropsAtBreak(blocks) {
74824
75030
  const props = {};
74825
75031
  if (source.kind !== "sectionBreak") return props;
74826
75032
  if (source.margins) {
74827
- props.margins = { header: source.margins.header, footer: source.margins.footer };
75033
+ props.margins = {
75034
+ header: source.margins.header,
75035
+ footer: source.margins.footer,
75036
+ top: source.margins.top,
75037
+ right: source.margins.right,
75038
+ bottom: source.margins.bottom,
75039
+ left: source.margins.left
75040
+ };
74828
75041
  }
74829
75042
  if (source.pageSize) {
74830
75043
  props.pageSize = { w: source.pageSize.w, h: source.pageSize.h };
@@ -74872,20 +75085,36 @@ function scheduleSectionBreak(block, state2, baseMargins, maxHeaderContentHeight
74872
75085
  next.activeOrientation = block.orientation;
74873
75086
  next.pendingOrientation = null;
74874
75087
  }
75088
+ const headerDistance = typeof block.margins?.header === "number" ? Math.max(0, block.margins.header) : next.activeHeaderDistance;
75089
+ const footerDistance = typeof block.margins?.footer === "number" ? Math.max(0, block.margins.footer) : next.activeFooterDistance;
75090
+ const sectionTop = typeof block.margins?.top === "number" ? Math.max(0, block.margins.top) : baseMargins.top;
75091
+ const sectionBottom = typeof block.margins?.bottom === "number" ? Math.max(0, block.margins.bottom) : baseMargins.bottom;
74875
75092
  if (block.margins?.header !== void 0) {
74876
- const headerDistance = Math.max(0, block.margins.header);
74877
75093
  next.activeHeaderDistance = headerDistance;
74878
75094
  next.pendingHeaderDistance = headerDistance;
74879
- next.activeTopMargin = calcRequiredTopMargin(headerDistance, baseMargins.top);
74880
- next.pendingTopMargin = next.activeTopMargin;
74881
75095
  }
74882
75096
  if (block.margins?.footer !== void 0) {
74883
- const footerDistance = Math.max(0, block.margins.footer);
74884
75097
  next.activeFooterDistance = footerDistance;
74885
75098
  next.pendingFooterDistance = footerDistance;
74886
- next.activeBottomMargin = calcRequiredBottomMargin(footerDistance, baseMargins.bottom);
75099
+ }
75100
+ if (block.margins?.top !== void 0 || block.margins?.header !== void 0) {
75101
+ next.activeTopMargin = calcRequiredTopMargin(headerDistance, sectionTop);
75102
+ next.pendingTopMargin = next.activeTopMargin;
75103
+ }
75104
+ if (block.margins?.bottom !== void 0 || block.margins?.footer !== void 0) {
75105
+ next.activeBottomMargin = calcRequiredBottomMargin(footerDistance, sectionBottom);
74887
75106
  next.pendingBottomMargin = next.activeBottomMargin;
74888
75107
  }
75108
+ if (block.margins?.left !== void 0) {
75109
+ const leftMargin = Math.max(0, block.margins.left);
75110
+ next.activeLeftMargin = leftMargin;
75111
+ next.pendingLeftMargin = leftMargin;
75112
+ }
75113
+ if (block.margins?.right !== void 0) {
75114
+ const rightMargin = Math.max(0, block.margins.right);
75115
+ next.activeRightMargin = rightMargin;
75116
+ next.pendingRightMargin = rightMargin;
75117
+ }
74889
75118
  if (block.columns) {
74890
75119
  next.activeColumns = { count: block.columns.count, gap: block.columns.gap };
74891
75120
  next.pendingColumns = null;
@@ -74894,26 +75123,42 @@ function scheduleSectionBreak(block, state2, baseMargins, maxHeaderContentHeight
74894
75123
  }
74895
75124
  const headerPx = block.margins?.header;
74896
75125
  const footerPx = block.margins?.footer;
75126
+ const topPx = block.margins?.top;
75127
+ const bottomPx = block.margins?.bottom;
74897
75128
  const nextTop = next.pendingTopMargin ?? next.activeTopMargin;
74898
75129
  const nextBottom = next.pendingBottomMargin ?? next.activeBottomMargin;
75130
+ const nextLeft = next.pendingLeftMargin ?? next.activeLeftMargin;
75131
+ const nextRight = next.pendingRightMargin ?? next.activeRightMargin;
74899
75132
  const nextHeader = next.pendingHeaderDistance ?? next.activeHeaderDistance;
74900
75133
  const nextFooter = next.pendingFooterDistance ?? next.activeFooterDistance;
74901
- if (typeof headerPx === "number") {
74902
- const newHeaderDist = Math.max(0, headerPx);
75134
+ if (typeof headerPx === "number" || typeof topPx === "number") {
75135
+ const newHeaderDist = typeof headerPx === "number" ? Math.max(0, headerPx) : nextHeader;
75136
+ const sectionTop = typeof topPx === "number" ? Math.max(0, topPx) : baseMargins.top;
74903
75137
  next.pendingHeaderDistance = newHeaderDist;
74904
- next.pendingTopMargin = calcRequiredTopMargin(newHeaderDist, baseMargins.top);
75138
+ next.pendingTopMargin = calcRequiredTopMargin(newHeaderDist, sectionTop);
74905
75139
  } else {
74906
75140
  next.pendingTopMargin = nextTop;
74907
75141
  next.pendingHeaderDistance = nextHeader;
74908
75142
  }
74909
- if (typeof footerPx === "number") {
74910
- const newFooterDist = Math.max(0, footerPx);
75143
+ if (typeof footerPx === "number" || typeof bottomPx === "number") {
75144
+ const newFooterDist = typeof footerPx === "number" ? Math.max(0, footerPx) : nextFooter;
75145
+ const sectionBottom = typeof bottomPx === "number" ? Math.max(0, bottomPx) : baseMargins.bottom;
74911
75146
  next.pendingFooterDistance = newFooterDist;
74912
- next.pendingBottomMargin = calcRequiredBottomMargin(newFooterDist, baseMargins.bottom);
75147
+ next.pendingBottomMargin = calcRequiredBottomMargin(newFooterDist, sectionBottom);
74913
75148
  } else {
74914
75149
  next.pendingBottomMargin = nextBottom;
74915
75150
  next.pendingFooterDistance = nextFooter;
74916
75151
  }
75152
+ if (typeof block.margins?.left === "number") {
75153
+ next.pendingLeftMargin = Math.max(0, block.margins.left);
75154
+ } else {
75155
+ next.pendingLeftMargin = nextLeft;
75156
+ }
75157
+ if (typeof block.margins?.right === "number") {
75158
+ next.pendingRightMargin = Math.max(0, block.margins.right);
75159
+ } else {
75160
+ next.pendingRightMargin = nextRight;
75161
+ }
74917
75162
  if (block.pageSize) {
74918
75163
  next.pendingPageSize = { w: block.pageSize.w, h: block.pageSize.h };
74919
75164
  }
@@ -74973,6 +75218,12 @@ function applyPendingToActive(state2) {
74973
75218
  if (next.pendingBottomMargin != null) {
74974
75219
  next.activeBottomMargin = next.pendingBottomMargin;
74975
75220
  }
75221
+ if (next.pendingLeftMargin != null) {
75222
+ next.activeLeftMargin = next.pendingLeftMargin;
75223
+ }
75224
+ if (next.pendingRightMargin != null) {
75225
+ next.activeRightMargin = next.pendingRightMargin;
75226
+ }
74976
75227
  if (next.pendingHeaderDistance != null) {
74977
75228
  next.activeHeaderDistance = next.pendingHeaderDistance;
74978
75229
  }
@@ -74990,6 +75241,8 @@ function applyPendingToActive(state2) {
74990
75241
  }
74991
75242
  next.pendingTopMargin = null;
74992
75243
  next.pendingBottomMargin = null;
75244
+ next.pendingLeftMargin = null;
75245
+ next.pendingRightMargin = null;
74993
75246
  next.pendingHeaderDistance = null;
74994
75247
  next.pendingFooterDistance = null;
74995
75248
  next.pendingPageSize = null;
@@ -75218,7 +75471,8 @@ function layoutParagraphBlock(ctx2, anchors) {
75218
75471
  if (typeof remeasureParagraph2 === "function" && typeof measurementWidth === "number" && measurementWidth > remeasureWidth) {
75219
75472
  const firstLineIndent = calculateFirstLineIndent(block, measure);
75220
75473
  const newMeasure = remeasureParagraph2(block, columnWidth, firstLineIndent);
75221
- lines = normalizeLines(newMeasure);
75474
+ const newLines = normalizeLines(newMeasure);
75475
+ lines = newLines;
75222
75476
  didRemeasureForColumnWidth = true;
75223
75477
  }
75224
75478
  let fromLine = 0;
@@ -75300,7 +75554,8 @@ function layoutParagraphBlock(ctx2, anchors) {
75300
75554
  if (narrowestRemeasureWidth < remeasureWidth) {
75301
75555
  const firstLineIndent = calculateFirstLineIndent(block, measure);
75302
75556
  const newMeasure = remeasureParagraph2(block, narrowestRemeasureWidth, firstLineIndent);
75303
- lines = normalizeLines(newMeasure);
75557
+ const newLines = normalizeLines(newMeasure);
75558
+ lines = newLines;
75304
75559
  didRemeasureForFloats = true;
75305
75560
  }
75306
75561
  }
@@ -75644,6 +75899,94 @@ function getCellPadding(cellIdx, blockRow) {
75644
75899
  function getCellTotalLines(cell) {
75645
75900
  return getCellLines(cell).length;
75646
75901
  }
75902
+ function mergePmRange(target, range2) {
75903
+ if (typeof range2.pmStart === "number") {
75904
+ target.pmStart = target.pmStart == null ? range2.pmStart : Math.min(target.pmStart, range2.pmStart);
75905
+ }
75906
+ if (typeof range2.pmEnd === "number") {
75907
+ target.pmEnd = target.pmEnd == null ? range2.pmEnd : Math.max(target.pmEnd, range2.pmEnd);
75908
+ }
75909
+ }
75910
+ function computeCellPmRange(cell, cellMeasure, fromLine, toLine) {
75911
+ const range2 = {};
75912
+ if (!cell || !cellMeasure) return range2;
75913
+ const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
75914
+ const blockMeasures = cellMeasure.blocks ?? (cellMeasure.paragraph ? [cellMeasure.paragraph] : []);
75915
+ const maxBlocks = Math.min(cellBlocks.length, blockMeasures.length);
75916
+ let cumulativeLineCount = 0;
75917
+ for (let i = 0; i < maxBlocks; i++) {
75918
+ const block = cellBlocks[i];
75919
+ const blockMeasure = blockMeasures[i];
75920
+ if (blockMeasure.kind === "paragraph" && block?.kind === "paragraph") {
75921
+ const paraMeasure = blockMeasure;
75922
+ const lines = paraMeasure.lines;
75923
+ const blockLineCount = lines?.length ?? 0;
75924
+ const blockStartGlobal = cumulativeLineCount;
75925
+ const blockEndGlobal = cumulativeLineCount + blockLineCount;
75926
+ const localFrom = Math.max(fromLine, blockStartGlobal) - blockStartGlobal;
75927
+ const localTo = Math.min(toLine, blockEndGlobal) - blockStartGlobal;
75928
+ if (lines && lines.length > 0 && localFrom < localTo) {
75929
+ mergePmRange(range2, computeFragmentPmRange(block, lines, localFrom, localTo));
75930
+ } else {
75931
+ mergePmRange(range2, extractBlockPmRange(block));
75932
+ }
75933
+ cumulativeLineCount += blockLineCount;
75934
+ continue;
75935
+ }
75936
+ mergePmRange(range2, extractBlockPmRange(block));
75937
+ }
75938
+ return range2;
75939
+ }
75940
+ function computeTableFragmentPmRange(block, measure, fromRow, toRow, partialRow) {
75941
+ const range2 = {};
75942
+ for (let rowIndex = fromRow; rowIndex < toRow; rowIndex++) {
75943
+ const row = block.rows[rowIndex];
75944
+ const rowMeasure = measure.rows[rowIndex];
75945
+ if (!row || !rowMeasure) continue;
75946
+ const isPartial = partialRow?.rowIndex === rowIndex;
75947
+ const cellCount = Math.min(row.cells.length, rowMeasure.cells.length);
75948
+ for (let cellIndex = 0; cellIndex < cellCount; cellIndex++) {
75949
+ const cell = row.cells[cellIndex];
75950
+ const cellMeasure = rowMeasure.cells[cellIndex];
75951
+ if (!cell || !cellMeasure) continue;
75952
+ const totalLines = getCellTotalLines(cellMeasure);
75953
+ let fromLine = 0;
75954
+ let toLine = totalLines;
75955
+ if (isPartial) {
75956
+ const hasValidFromLineByCell = partialRow?.fromLineByCell && cellIndex < partialRow.fromLineByCell.length;
75957
+ const hasValidToLineByCell = partialRow?.toLineByCell && cellIndex < partialRow.toLineByCell.length;
75958
+ if (hasValidFromLineByCell) {
75959
+ const rawFrom = partialRow.fromLineByCell[cellIndex];
75960
+ if (typeof rawFrom === "number" && rawFrom >= 0) {
75961
+ fromLine = rawFrom;
75962
+ }
75963
+ }
75964
+ if (hasValidToLineByCell) {
75965
+ const rawTo = partialRow.toLineByCell[cellIndex];
75966
+ if (typeof rawTo === "number") {
75967
+ toLine = rawTo === -1 ? totalLines : rawTo;
75968
+ }
75969
+ }
75970
+ }
75971
+ fromLine = Math.max(0, Math.min(fromLine, totalLines));
75972
+ toLine = Math.max(0, Math.min(toLine, totalLines));
75973
+ if (toLine < fromLine) {
75974
+ toLine = fromLine;
75975
+ }
75976
+ mergePmRange(range2, computeCellPmRange(cell, cellMeasure, fromLine, toLine));
75977
+ }
75978
+ }
75979
+ return range2;
75980
+ }
75981
+ function applyTableFragmentPmRange(fragment, block, measure) {
75982
+ const range2 = computeTableFragmentPmRange(block, measure, fragment.fromRow, fragment.toRow, fragment.partialRow);
75983
+ if (range2.pmStart != null) {
75984
+ fragment.pmStart = range2.pmStart;
75985
+ }
75986
+ if (range2.pmEnd != null) {
75987
+ fragment.pmEnd = range2.pmEnd;
75988
+ }
75989
+ }
75647
75990
  function computePartialRow(rowIndex, blockRow, measure, availableHeight, fromLineByCell) {
75648
75991
  const row = measure.rows[rowIndex];
75649
75992
  if (!row) {
@@ -75788,6 +76131,7 @@ function layoutMonolithicTable(context) {
75788
76131
  height,
75789
76132
  metadata
75790
76133
  };
76134
+ applyTableFragmentPmRange(fragment, context.block, context.measure);
75791
76135
  state2.page.fragments.push(fragment);
75792
76136
  state2.cursorY += height;
75793
76137
  }
@@ -75866,6 +76210,7 @@ function layoutTableBlock({
75866
76210
  height,
75867
76211
  metadata
75868
76212
  };
76213
+ applyTableFragmentPmRange(fragment, block, measure);
75869
76214
  state2.page.fragments.push(fragment);
75870
76215
  state2.cursorY += height;
75871
76216
  return;
@@ -75929,6 +76274,7 @@ function layoutTableBlock({
75929
76274
  partialRow: continuationPartialRow,
75930
76275
  metadata: generateFragmentMetadata(measure)
75931
76276
  };
76277
+ applyTableFragmentPmRange(fragment2, block, measure);
75932
76278
  state2.page.fragments.push(fragment2);
75933
76279
  state2.cursorY += fragmentHeight2;
75934
76280
  }
@@ -75973,6 +76319,7 @@ function layoutTableBlock({
75973
76319
  partialRow: forcedPartialRow,
75974
76320
  metadata: generateFragmentMetadata(measure)
75975
76321
  };
76322
+ applyTableFragmentPmRange(fragment2, block, measure);
75976
76323
  state2.page.fragments.push(fragment2);
75977
76324
  state2.cursorY += fragmentHeight2;
75978
76325
  pendingPartialRow = forcedPartialRow;
@@ -76008,6 +76355,7 @@ function layoutTableBlock({
76008
76355
  partialRow: partialRow || void 0,
76009
76356
  metadata: generateFragmentMetadata(measure)
76010
76357
  };
76358
+ applyTableFragmentPmRange(fragment, block, measure);
76011
76359
  state2.page.fragments.push(fragment);
76012
76360
  state2.cursorY += fragmentHeight;
76013
76361
  if (partialRow && !partialRow.isLastPart) {
@@ -76025,7 +76373,7 @@ function createAnchoredTableFragment(block, measure, x2, y2) {
76025
76373
  columnBoundaries: generateColumnBoundaries(measure),
76026
76374
  coordinateSystem: "fragment"
76027
76375
  };
76028
- return {
76376
+ const fragment = {
76029
76377
  kind: "table",
76030
76378
  blockId: block.id,
76031
76379
  fromRow: 0,
@@ -76036,6 +76384,8 @@ function createAnchoredTableFragment(block, measure, x2, y2) {
76036
76384
  height: measure.totalHeight ?? 0,
76037
76385
  metadata
76038
76386
  };
76387
+ applyTableFragmentPmRange(fragment, block, measure);
76388
+ return fragment;
76039
76389
  }
76040
76390
  function isPageRelativeAnchor(block) {
76041
76391
  const vRelativeFrom = block.anchor?.vRelativeFrom;
@@ -76457,8 +76807,8 @@ function layoutDocument(blocks, measures, options = {}) {
76457
76807
  header: options.margins?.header ?? options.margins?.top ?? DEFAULT_MARGINS$2.top,
76458
76808
  footer: options.margins?.footer ?? options.margins?.bottom ?? DEFAULT_MARGINS$2.bottom
76459
76809
  };
76460
- const contentWidth = pageSize.w - (margins.left + margins.right);
76461
- if (contentWidth <= 0) {
76810
+ const baseContentWidth = pageSize.w - (margins.left + margins.right);
76811
+ if (baseContentWidth <= 0) {
76462
76812
  throw new Error("layoutDocument: pageSize and margins yield non-positive content area");
76463
76813
  }
76464
76814
  const validateContentHeight = (height) => {
@@ -76488,8 +76838,12 @@ function layoutDocument(blocks, measures, options = {}) {
76488
76838
  const effectiveBottomMargin = maxFooterContentHeight > 0 ? Math.max(margins.bottom, footerDistance + maxFooterContentHeight) : margins.bottom;
76489
76839
  let activeTopMargin = effectiveTopMargin;
76490
76840
  let activeBottomMargin = effectiveBottomMargin;
76841
+ let activeLeftMargin = margins.left;
76842
+ let activeRightMargin = margins.right;
76491
76843
  let pendingTopMargin = null;
76492
76844
  let pendingBottomMargin = null;
76845
+ let pendingLeftMargin = null;
76846
+ let pendingRightMargin = null;
76493
76847
  let activeHeaderDistance = margins.header ?? margins.top;
76494
76848
  let pendingHeaderDistance = null;
76495
76849
  let activeFooterDistance = margins.footer ?? margins.bottom;
@@ -76502,10 +76856,11 @@ function layoutDocument(blocks, measures, options = {}) {
76502
76856
  let pendingOrientation = null;
76503
76857
  let activeVAlign = null;
76504
76858
  let pendingVAlign = null;
76859
+ const paginatorMargins = { left: activeLeftMargin, right: activeRightMargin };
76505
76860
  const floatManager = createFloatingObjectManager(
76506
- normalizeColumns(activeColumns, contentWidth),
76507
- { left: margins.left, right: margins.right },
76508
- pageSize.w
76861
+ normalizeColumns(activeColumns, activePageSize.w - (activeLeftMargin + activeRightMargin)),
76862
+ { left: activeLeftMargin, right: activeRightMargin },
76863
+ activePageSize.w
76509
76864
  );
76510
76865
  const nextSectionPropsAtBreak = computeNextSectionPropsAtBreak(blocks);
76511
76866
  const scheduleSectionBreakCompat = (block, state2, baseMargins) => {
@@ -76522,22 +76877,38 @@ function layoutDocument(blocks, measures, options = {}) {
76522
76877
  next.activeOrientation = block.orientation;
76523
76878
  next.pendingOrientation = null;
76524
76879
  }
76880
+ const headerDistance2 = typeof block.margins?.header === "number" ? Math.max(0, block.margins.header) : next.activeHeaderDistance;
76881
+ const footerDistance2 = typeof block.margins?.footer === "number" ? Math.max(0, block.margins.footer) : next.activeFooterDistance;
76882
+ const sectionTop = typeof block.margins?.top === "number" ? Math.max(0, block.margins.top) : baseMargins.top;
76883
+ const sectionBottom = typeof block.margins?.bottom === "number" ? Math.max(0, block.margins.bottom) : baseMargins.bottom;
76525
76884
  if (block.margins?.header !== void 0) {
76526
- const headerDist = Math.max(0, block.margins.header);
76527
- next.activeHeaderDistance = headerDist;
76528
- next.pendingHeaderDistance = headerDist;
76529
- const requiredTop = maxHeaderContentHeight > 0 ? headerDist + maxHeaderContentHeight : headerDist;
76530
- next.activeTopMargin = Math.max(baseMargins.top, requiredTop);
76531
- next.pendingTopMargin = next.activeTopMargin;
76885
+ next.activeHeaderDistance = headerDistance2;
76886
+ next.pendingHeaderDistance = headerDistance2;
76532
76887
  }
76533
76888
  if (block.margins?.footer !== void 0) {
76534
- const footerDistance2 = Math.max(0, block.margins.footer);
76535
76889
  next.activeFooterDistance = footerDistance2;
76536
76890
  next.pendingFooterDistance = footerDistance2;
76891
+ }
76892
+ if (block.margins?.top !== void 0 || block.margins?.header !== void 0) {
76893
+ const requiredTop = maxHeaderContentHeight > 0 ? headerDistance2 + maxHeaderContentHeight : headerDistance2;
76894
+ next.activeTopMargin = Math.max(sectionTop, requiredTop);
76895
+ next.pendingTopMargin = next.activeTopMargin;
76896
+ }
76897
+ if (block.margins?.bottom !== void 0 || block.margins?.footer !== void 0) {
76537
76898
  const requiredBottom = maxFooterContentHeight > 0 ? footerDistance2 + maxFooterContentHeight : footerDistance2;
76538
- next.activeBottomMargin = Math.max(baseMargins.bottom, requiredBottom);
76899
+ next.activeBottomMargin = Math.max(sectionBottom, requiredBottom);
76539
76900
  next.pendingBottomMargin = next.activeBottomMargin;
76540
76901
  }
76902
+ if (block.margins?.left !== void 0) {
76903
+ const leftMargin = Math.max(0, block.margins.left);
76904
+ next.activeLeftMargin = leftMargin;
76905
+ next.pendingLeftMargin = leftMargin;
76906
+ }
76907
+ if (block.margins?.right !== void 0) {
76908
+ const rightMargin = Math.max(0, block.margins.right);
76909
+ next.activeRightMargin = rightMargin;
76910
+ next.pendingRightMargin = rightMargin;
76911
+ }
76541
76912
  if (block.columns) {
76542
76913
  next.activeColumns = { count: block.columns.count, gap: block.columns.gap };
76543
76914
  next.pendingColumns = null;
@@ -76566,27 +76937,35 @@ function layoutDocument(blocks, measures, options = {}) {
76566
76937
  const headerPx = block.margins?.header;
76567
76938
  const footerPx = block.margins?.footer;
76568
76939
  const topPx = block.margins?.top;
76940
+ const bottomPx = block.margins?.bottom;
76941
+ const leftPx = block.margins?.left;
76942
+ const rightPx = block.margins?.right;
76569
76943
  const nextTop = next.pendingTopMargin ?? next.activeTopMargin;
76570
76944
  const nextBottom = next.pendingBottomMargin ?? next.activeBottomMargin;
76945
+ const nextLeft = next.pendingLeftMargin ?? next.activeLeftMargin;
76946
+ const nextRight = next.pendingRightMargin ?? next.activeRightMargin;
76571
76947
  const nextHeader = next.pendingHeaderDistance ?? next.activeHeaderDistance;
76572
76948
  const nextFooter = next.pendingFooterDistance ?? next.activeFooterDistance;
76573
76949
  next.pendingHeaderDistance = typeof headerPx === "number" ? Math.max(0, headerPx) : nextHeader;
76574
76950
  next.pendingFooterDistance = typeof footerPx === "number" ? Math.max(0, footerPx) : nextFooter;
76575
76951
  if (typeof headerPx === "number" || typeof topPx === "number") {
76576
- const sectionTop = topPx ?? baseMargins.top;
76952
+ const sectionTop = typeof topPx === "number" ? Math.max(0, topPx) : baseMargins.top;
76577
76953
  const sectionHeader = next.pendingHeaderDistance;
76578
76954
  const requiredTop = maxHeaderContentHeight > 0 ? sectionHeader + maxHeaderContentHeight : sectionHeader;
76579
76955
  next.pendingTopMargin = Math.max(sectionTop, requiredTop);
76580
76956
  } else {
76581
76957
  next.pendingTopMargin = nextTop;
76582
76958
  }
76583
- if (typeof footerPx === "number") {
76959
+ if (typeof footerPx === "number" || typeof bottomPx === "number") {
76584
76960
  const sectionFooter = next.pendingFooterDistance;
76961
+ const sectionBottom = typeof bottomPx === "number" ? Math.max(0, bottomPx) : baseMargins.bottom;
76585
76962
  const requiredBottom = maxFooterContentHeight > 0 ? sectionFooter + maxFooterContentHeight : sectionFooter;
76586
- next.pendingBottomMargin = Math.max(baseMargins.bottom, requiredBottom);
76963
+ next.pendingBottomMargin = Math.max(sectionBottom, requiredBottom);
76587
76964
  } else {
76588
76965
  next.pendingBottomMargin = nextBottom;
76589
76966
  }
76967
+ next.pendingLeftMargin = typeof leftPx === "number" ? Math.max(0, leftPx) : nextLeft;
76968
+ next.pendingRightMargin = typeof rightPx === "number" ? Math.max(0, rightPx) : nextRight;
76590
76969
  if (block.pageSize) next.pendingPageSize = { w: block.pageSize.w, h: block.pageSize.h };
76591
76970
  if (block.orientation) next.pendingOrientation = block.orientation;
76592
76971
  const sectionType = block.type ?? "continuous";
@@ -76671,7 +77050,7 @@ function layoutDocument(blocks, measures, options = {}) {
76671
77050
  let activeSectionIndex = initialSectionMetadata?.sectionIndex ?? 0;
76672
77051
  let pendingSectionIndex = null;
76673
77052
  const paginator = createPaginator({
76674
- margins: { left: margins.left, right: margins.right },
77053
+ margins: paginatorMargins,
76675
77054
  getActiveTopMargin: () => activeTopMargin,
76676
77055
  getActiveBottomMargin: () => activeBottomMargin,
76677
77056
  getActiveHeaderDistance: () => activeHeaderDistance,
@@ -76686,8 +77065,12 @@ function layoutDocument(blocks, measures, options = {}) {
76686
77065
  const applied = applyPendingToActive({
76687
77066
  activeTopMargin,
76688
77067
  activeBottomMargin,
77068
+ activeLeftMargin,
77069
+ activeRightMargin,
76689
77070
  pendingTopMargin,
76690
77071
  pendingBottomMargin,
77072
+ pendingLeftMargin,
77073
+ pendingRightMargin,
76691
77074
  activeHeaderDistance,
76692
77075
  activeFooterDistance,
76693
77076
  pendingHeaderDistance,
@@ -76702,8 +77085,12 @@ function layoutDocument(blocks, measures, options = {}) {
76702
77085
  });
76703
77086
  activeTopMargin = applied.activeTopMargin;
76704
77087
  activeBottomMargin = applied.activeBottomMargin;
77088
+ activeLeftMargin = applied.activeLeftMargin;
77089
+ activeRightMargin = applied.activeRightMargin;
76705
77090
  pendingTopMargin = applied.pendingTopMargin;
76706
77091
  pendingBottomMargin = applied.pendingBottomMargin;
77092
+ pendingLeftMargin = applied.pendingLeftMargin;
77093
+ pendingRightMargin = applied.pendingRightMargin;
76707
77094
  activeHeaderDistance = applied.activeHeaderDistance;
76708
77095
  activeFooterDistance = applied.activeFooterDistance;
76709
77096
  pendingHeaderDistance = applied.pendingHeaderDistance;
@@ -76715,6 +77102,14 @@ function layoutDocument(blocks, measures, options = {}) {
76715
77102
  activeOrientation = applied.activeOrientation;
76716
77103
  pendingOrientation = applied.pendingOrientation;
76717
77104
  cachedColumnsState.state = null;
77105
+ paginatorMargins.left = activeLeftMargin;
77106
+ paginatorMargins.right = activeRightMargin;
77107
+ const contentWidth = activePageSize.w - (activeLeftMargin + activeRightMargin);
77108
+ floatManager.setLayoutContext(
77109
+ normalizeColumns(activeColumns, contentWidth),
77110
+ { left: activeLeftMargin, right: activeRightMargin },
77111
+ activePageSize.w
77112
+ );
76718
77113
  if (pendingNumbering) {
76719
77114
  if (pendingNumbering.format) activeNumberFormat = pendingNumbering.format;
76720
77115
  if (typeof pendingNumbering.start === "number" && Number.isFinite(pendingNumbering.start)) {
@@ -76759,7 +77154,7 @@ function layoutDocument(blocks, measures, options = {}) {
76759
77154
  const getActiveColumnsForState = paginator.getActiveColumnsForState;
76760
77155
  let cachedColumnsState = { state: null, constraintIndex: -2, contentWidth: -1, colsConfig: null, normalized: null };
76761
77156
  const getCurrentColumns = () => {
76762
- const currentContentWidth = activePageSize.w - (margins.left + margins.right);
77157
+ const currentContentWidth = activePageSize.w - (activeLeftMargin + activeRightMargin);
76763
77158
  const state2 = states[states.length - 1] ?? null;
76764
77159
  const colsConfig = state2 ? getActiveColumnsForState(state2) : activeColumns;
76765
77160
  const constraintIndex = state2 ? state2.activeConstraintIndex : -1;
@@ -76792,6 +77187,12 @@ function layoutDocument(blocks, measures, options = {}) {
76792
77187
  layoutLog(` Current page: ${state2.page.number}, cursorY: ${state2.cursorY}`);
76793
77188
  activeColumns = newColumns;
76794
77189
  cachedColumnsState.state = null;
77190
+ const contentWidth = activePageSize.w - (activeLeftMargin + activeRightMargin);
77191
+ floatManager.setLayoutContext(
77192
+ normalizeColumns(activeColumns, contentWidth),
77193
+ { left: activeLeftMargin, right: activeRightMargin },
77194
+ activePageSize.w
77195
+ );
76795
77196
  };
76796
77197
  const anchoredByParagraph = collectAnchoredDrawings(blocks, measures);
76797
77198
  const anchoredTablesByParagraph = collectAnchoredTables(blocks, measures);
@@ -76823,10 +77224,10 @@ function layoutDocument(blocks, measures, options = {}) {
76823
77224
  if (alignV === "top") {
76824
77225
  anchorY = offsetV;
76825
77226
  } else if (alignV === "bottom") {
76826
- const pageHeight = contentBottom + margins.bottom;
77227
+ const pageHeight = contentBottom + (state2.page.margins?.bottom ?? activeBottomMargin);
76827
77228
  anchorY = pageHeight - imageHeight + offsetV;
76828
77229
  } else if (alignV === "center") {
76829
- const pageHeight = contentBottom + margins.bottom;
77230
+ const pageHeight = contentBottom + (state2.page.margins?.bottom ?? activeBottomMargin);
76830
77231
  anchorY = (pageHeight - imageHeight) / 2 + offsetV;
76831
77232
  } else {
76832
77233
  anchorY = offsetV;
@@ -76837,11 +77238,11 @@ function layoutDocument(blocks, measures, options = {}) {
76837
77238
  const anchorX = entry.block.anchor ? computeAnchorX(
76838
77239
  entry.block.anchor,
76839
77240
  state2.columnIndex,
76840
- normalizeColumns(activeColumns, contentWidth),
77241
+ normalizeColumns(activeColumns, activePageSize.w - (activeLeftMargin + activeRightMargin)),
76841
77242
  entry.measure.width,
76842
- { left: margins.left, right: margins.right },
77243
+ { left: activeLeftMargin, right: activeRightMargin },
76843
77244
  activePageSize.w
76844
- ) : margins.left;
77245
+ ) : activeLeftMargin;
76845
77246
  floatManager.registerDrawing(entry.block, entry.measure, anchorY, state2.columnIndex, state2.page.number);
76846
77247
  preRegisteredPositions.set(entry.block.id, { anchorX, anchorY, pageNumber: state2.page.number });
76847
77248
  }
@@ -76879,8 +77280,12 @@ function layoutDocument(blocks, measures, options = {}) {
76879
77280
  const sectionState = {
76880
77281
  activeTopMargin,
76881
77282
  activeBottomMargin,
77283
+ activeLeftMargin,
77284
+ activeRightMargin,
76882
77285
  pendingTopMargin,
76883
77286
  pendingBottomMargin,
77287
+ pendingLeftMargin,
77288
+ pendingRightMargin,
76884
77289
  activeHeaderDistance,
76885
77290
  activeFooterDistance,
76886
77291
  pendingHeaderDistance,
@@ -76914,8 +77319,12 @@ function layoutDocument(blocks, measures, options = {}) {
76914
77319
  layoutLog(`[Layout] ========== END SECTION BREAK ==========`);
76915
77320
  activeTopMargin = updatedState.activeTopMargin;
76916
77321
  activeBottomMargin = updatedState.activeBottomMargin;
77322
+ activeLeftMargin = updatedState.activeLeftMargin;
77323
+ activeRightMargin = updatedState.activeRightMargin;
76917
77324
  pendingTopMargin = updatedState.pendingTopMargin;
76918
77325
  pendingBottomMargin = updatedState.pendingBottomMargin;
77326
+ pendingLeftMargin = updatedState.pendingLeftMargin;
77327
+ pendingRightMargin = updatedState.pendingRightMargin;
76919
77328
  activeHeaderDistance = updatedState.activeHeaderDistance;
76920
77329
  activeFooterDistance = updatedState.activeFooterDistance;
76921
77330
  pendingHeaderDistance = updatedState.pendingHeaderDistance;
@@ -77053,8 +77462,8 @@ function layoutDocument(blocks, measures, options = {}) {
77053
77462
  pageMargins: {
77054
77463
  top: activeTopMargin,
77055
77464
  bottom: activeBottomMargin,
77056
- left: margins.left,
77057
- right: margins.right
77465
+ left: activeLeftMargin,
77466
+ right: activeRightMargin
77058
77467
  },
77059
77468
  columns: getCurrentColumns(),
77060
77469
  placedAnchoredIds
@@ -77076,9 +77485,9 @@ function layoutDocument(blocks, measures, options = {}) {
77076
77485
  const cols = getCurrentColumns();
77077
77486
  let maxWidth;
77078
77487
  if (relativeFrom === "page") {
77079
- maxWidth = cols.count === 1 ? activePageSize.w - margins.left - margins.right : activePageSize.w;
77488
+ maxWidth = cols.count === 1 ? activePageSize.w - (activeLeftMargin + activeRightMargin) : activePageSize.w;
77080
77489
  } else if (relativeFrom === "margin") {
77081
- maxWidth = activePageSize.w - margins.left - margins.right;
77490
+ maxWidth = activePageSize.w - (activeLeftMargin + activeRightMargin);
77082
77491
  } else {
77083
77492
  maxWidth = cols.width;
77084
77493
  }
@@ -77238,6 +77647,9 @@ function layoutHeaderFooter(blocks, measures, constraints) {
77238
77647
  if (!Number.isFinite(height) || height <= 0) {
77239
77648
  throw new Error("layoutHeaderFooter: height must be positive");
77240
77649
  }
77650
+ const maxBehindDocOverflow = Math.max(192, height * 4);
77651
+ const minBehindDocY = -maxBehindDocOverflow;
77652
+ const maxBehindDocY = height + maxBehindDocOverflow;
77241
77653
  const marginLeft = constraints.margins?.left ?? 0;
77242
77654
  const transformedBlocks = marginLeft > 0 ? blocks.map((block) => {
77243
77655
  const hasPageRelativeAnchor = (block.kind === "image" || block.kind === "drawing") && block.anchor?.hRelativeFrom === "page" && block.anchor.offsetH != null;
@@ -77268,6 +77680,18 @@ function layoutHeaderFooter(blocks, measures, constraints) {
77268
77680
  if (idx == null) continue;
77269
77681
  const block = blocks[idx];
77270
77682
  const measure = measures[idx];
77683
+ const isAnchoredFragment = (fragment.kind === "image" || fragment.kind === "drawing") && fragment.isAnchored === true;
77684
+ if (isAnchoredFragment) {
77685
+ if (block.kind !== "image" && block.kind !== "drawing") {
77686
+ throw new Error(
77687
+ `Type mismatch: fragment kind is ${fragment.kind} but block kind is ${block.kind} for block ${block.id}`
77688
+ );
77689
+ }
77690
+ const anchoredBlock = block;
77691
+ if (anchoredBlock.anchor?.behindDoc && (fragment.y < minBehindDocY || fragment.y > maxBehindDocY)) {
77692
+ continue;
77693
+ }
77694
+ }
77271
77695
  if (fragment.y < minY) minY = fragment.y;
77272
77696
  let bottom2 = fragment.y;
77273
77697
  if (fragment.kind === "para" && measure?.kind === "paragraph") {
@@ -78265,11 +78689,11 @@ function findWordBoundaries(blocks, pos) {
78265
78689
  if (text.length === 0) return null;
78266
78690
  const clampedPos = Math.max(0, Math.min(localPos, text.length));
78267
78691
  let wordStart = clampedPos;
78268
- while (wordStart > 0 && isWordChar(text[wordStart - 1])) {
78692
+ while (wordStart > 0 && isWordChar$2(text[wordStart - 1])) {
78269
78693
  wordStart--;
78270
78694
  }
78271
78695
  let wordEnd = clampedPos;
78272
- while (wordEnd < text.length && isWordChar(text[wordEnd])) {
78696
+ while (wordEnd < text.length && isWordChar$2(text[wordEnd])) {
78273
78697
  wordEnd++;
78274
78698
  }
78275
78699
  if (wordStart === wordEnd) {
@@ -78332,7 +78756,7 @@ function findBlockAtPosition(blocks, pos) {
78332
78756
  }
78333
78757
  return null;
78334
78758
  }
78335
- function isWordChar(char) {
78759
+ function isWordChar$2(char) {
78336
78760
  return /[\p{L}\p{N}_]/u.test(char);
78337
78761
  }
78338
78762
  function isWhitespace(char) {
@@ -78367,6 +78791,29 @@ function fontString(run2) {
78367
78791
  function runText(run2) {
78368
78792
  return "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation" ? "" : run2.text ?? "";
78369
78793
  }
78794
+ const isWordChar$1 = (char) => {
78795
+ if (!char) return false;
78796
+ const code = char.charCodeAt(0);
78797
+ return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || char === "'";
78798
+ };
78799
+ const capitalizeText$1 = (text, fullText, startOffset) => {
78800
+ if (!text) return text;
78801
+ const hasFullText = typeof startOffset === "number" && fullText != null;
78802
+ let result = "";
78803
+ for (let i = 0; i < text.length; i += 1) {
78804
+ const prevChar = hasFullText ? startOffset + i > 0 ? fullText[startOffset + i - 1] : "" : i > 0 ? text[i - 1] : "";
78805
+ const ch = text[i];
78806
+ result += isWordChar$1(ch) && !isWordChar$1(prevChar) ? ch.toUpperCase() : ch;
78807
+ }
78808
+ return result;
78809
+ };
78810
+ const applyTextTransform$1 = (text, transform, fullText, startOffset) => {
78811
+ if (!text || !transform || transform === "none") return text;
78812
+ if (transform === "uppercase") return text.toUpperCase();
78813
+ if (transform === "lowercase") return text.toLowerCase();
78814
+ if (transform === "capitalize") return capitalizeText$1(text, fullText, startOffset);
78815
+ return text;
78816
+ };
78370
78817
  const DEFAULT_TAB_INTERVAL_TWIPS$1 = 720;
78371
78818
  const TWIPS_PER_INCH$4 = 1440;
78372
78819
  const PX_PER_INCH$3 = 96;
@@ -78375,6 +78822,13 @@ const TAB_EPSILON$1 = 0.1;
78375
78822
  const WIDTH_FUDGE_PX = 0.5;
78376
78823
  const twipsToPx$2 = (twips) => twips / TWIPS_PER_PX$1;
78377
78824
  const pxToTwips$1 = (px) => Math.round(px * TWIPS_PER_PX$1);
78825
+ const markerFontString = (run2) => {
78826
+ const size2 = run2?.fontSize ?? 16;
78827
+ const family = run2?.fontFamily ?? "Arial";
78828
+ const italic = run2?.italic ? "italic " : "";
78829
+ const bold = run2?.bold ? "bold " : "";
78830
+ return `${italic}${bold}${size2}px ${family}`.trim();
78831
+ };
78378
78832
  const buildTabStopsPx$1 = (indent, tabs, tabIntervalTwips) => {
78379
78833
  const paragraphIndentTwips = {
78380
78834
  left: pxToTwips$1(Math.max(0, indent?.left ?? 0)),
@@ -78405,7 +78859,9 @@ const getNextTabStopPx$1 = (currentX, tabStops, startIndex) => {
78405
78859
  };
78406
78860
  function measureRunSliceWidth(run2, fromChar, toChar) {
78407
78861
  const context = getCtx();
78408
- const text = runText(run2).slice(fromChar, toChar);
78862
+ const fullText = runText(run2);
78863
+ const transform = isTextRun$2(run2) ? run2.textTransform : void 0;
78864
+ const text = applyTextTransform$1(fullText.slice(fromChar, toChar), transform, fullText, fromChar);
78409
78865
  if (!context) {
78410
78866
  const textRun = isTextRun$2(run2) ? run2 : null;
78411
78867
  const size2 = textRun?.fontSize ?? 16;
@@ -78451,8 +78907,21 @@ function remeasureParagraph(block, maxWidth, firstLineIndent = 0) {
78451
78907
  const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
78452
78908
  const markerTextStartX = wordLayout?.marker?.textStartX;
78453
78909
  const textStartPx = typeof markerTextStartX === "number" && Number.isFinite(markerTextStartX) ? markerTextStartX : typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : void 0;
78454
- const treatAsHanging = textStartPx && indentLeft === 0 && indentHanging === 0;
78455
- const firstLineWidth = typeof textStartPx === "number" && textStartPx > indentLeft && !treatAsHanging ? Math.max(1, maxWidth - textStartPx - indentRight) : Math.max(1, contentWidth - rawFirstLineOffset);
78910
+ const resolvedTextStartPx = resolveListTextStartPx(
78911
+ wordLayout,
78912
+ indentLeft,
78913
+ indentFirstLine,
78914
+ indentHanging,
78915
+ (markerText, marker) => {
78916
+ const context = getCtx();
78917
+ if (!context) return 0;
78918
+ context.font = markerFontString(marker.run);
78919
+ return context.measureText(markerText).width;
78920
+ }
78921
+ );
78922
+ const effectiveTextStartPx = resolvedTextStartPx ?? textStartPx;
78923
+ const treatAsHanging = !wordLayout?.marker && effectiveTextStartPx && indentLeft === 0 && indentHanging === 0;
78924
+ const firstLineWidth = typeof effectiveTextStartPx === "number" && effectiveTextStartPx > indentLeft && !treatAsHanging ? Math.max(1, maxWidth - effectiveTextStartPx - indentRight) : Math.max(1, contentWidth - rawFirstLineOffset);
78456
78925
  const tabStops = buildTabStopsPx$1(indent, attrs?.tabs, attrs?.tabIntervalTwips);
78457
78926
  let currentRun = 0;
78458
78927
  let currentChar = 0;
@@ -78992,7 +79461,7 @@ async function incrementalLayout(previousBlocks, _previousLayout, nextBlocks, op
78992
79461
  if (dirty.deletedBlockIds.length > 0) {
78993
79462
  measureCache.invalidate(dirty.deletedBlockIds);
78994
79463
  }
78995
- const { measurementWidth, measurementHeight } = resolveMeasurementConstraints(options);
79464
+ const { measurementWidth, measurementHeight } = resolveMeasurementConstraints(options, nextBlocks);
78996
79465
  if (measurementWidth <= 0 || measurementHeight <= 0) {
78997
79466
  throw new Error("incrementalLayout: invalid measurement constraints resolved from options");
78998
79467
  }
@@ -79261,7 +79730,7 @@ async function incrementalLayout(previousBlocks, _previousLayout, nextBlocks, op
79261
79730
  const DEFAULT_PAGE_SIZE$1 = { w: 612, h: 792 };
79262
79731
  const DEFAULT_MARGINS$1 = { top: 72, right: 72, bottom: 72, left: 72 };
79263
79732
  const normalizeMargin = (value, fallback) => Number.isFinite(value) ? value : fallback;
79264
- function resolveMeasurementConstraints(options) {
79733
+ function resolveMeasurementConstraints(options, blocks) {
79265
79734
  const pageSize = options.pageSize ?? DEFAULT_PAGE_SIZE$1;
79266
79735
  const margins = {
79267
79736
  top: normalizeMargin(options.margins?.top, DEFAULT_MARGINS$1.top),
@@ -79269,23 +79738,41 @@ function resolveMeasurementConstraints(options) {
79269
79738
  bottom: normalizeMargin(options.margins?.bottom, DEFAULT_MARGINS$1.bottom),
79270
79739
  left: normalizeMargin(options.margins?.left, DEFAULT_MARGINS$1.left)
79271
79740
  };
79272
- const contentWidth = pageSize.w - (margins.left + margins.right);
79273
- const contentHeight = pageSize.h - (margins.top + margins.bottom);
79274
- const columns = options.columns;
79275
- if (columns && columns.count > 1) {
79741
+ const baseContentWidth = pageSize.w - (margins.left + margins.right);
79742
+ const baseContentHeight = pageSize.h - (margins.top + margins.bottom);
79743
+ const computeColumnWidth = (contentWidth, columns) => {
79744
+ if (!columns || columns.count <= 1) return contentWidth;
79276
79745
  const gap = Math.max(0, columns.gap ?? 0);
79277
79746
  const totalGap = gap * (columns.count - 1);
79278
- const columnWidth = (contentWidth - totalGap) / columns.count;
79279
- if (columnWidth > 0) {
79280
- return {
79281
- measurementWidth: columnWidth,
79282
- measurementHeight: contentHeight
79747
+ return (contentWidth - totalGap) / columns.count;
79748
+ };
79749
+ let measurementWidth = computeColumnWidth(baseContentWidth, options.columns);
79750
+ let measurementHeight = baseContentHeight;
79751
+ if (blocks && blocks.length > 0) {
79752
+ for (const block of blocks) {
79753
+ if (block.kind !== "sectionBreak") continue;
79754
+ const sectionPageSize = block.pageSize ?? pageSize;
79755
+ const sectionMargins = {
79756
+ top: normalizeMargin(block.margins?.top, margins.top),
79757
+ right: normalizeMargin(block.margins?.right, margins.right),
79758
+ bottom: normalizeMargin(block.margins?.bottom, margins.bottom),
79759
+ left: normalizeMargin(block.margins?.left, margins.left)
79283
79760
  };
79761
+ const contentWidth = sectionPageSize.w - (sectionMargins.left + sectionMargins.right);
79762
+ const contentHeight = sectionPageSize.h - (sectionMargins.top + sectionMargins.bottom);
79763
+ if (contentWidth <= 0 || contentHeight <= 0) continue;
79764
+ const columnWidth = computeColumnWidth(contentWidth, block.columns ?? options.columns);
79765
+ if (columnWidth > measurementWidth) {
79766
+ measurementWidth = columnWidth;
79767
+ }
79768
+ if (contentHeight > measurementHeight) {
79769
+ measurementHeight = contentHeight;
79770
+ }
79284
79771
  }
79285
79772
  }
79286
79773
  return {
79287
- measurementWidth: contentWidth,
79288
- measurementHeight: contentHeight
79774
+ measurementWidth,
79775
+ measurementHeight
79289
79776
  };
79290
79777
  }
79291
79778
  const serializeHeaderFooterResults = (kind, batch) => {
@@ -81352,6 +81839,7 @@ function isInRegisteredSurface(event) {
81352
81839
  }
81353
81840
  return false;
81354
81841
  }
81842
+ const SLASH_MENU_HANDLED_FLAG = "__sdHandledBySlashMenu";
81355
81843
  class PresentationInputBridge {
81356
81844
  /**
81357
81845
  * Creates a new PresentationInputBridge that forwards user input events from the visible layout
@@ -81565,6 +82053,10 @@ forwardCompositionEvent_fn = function(event) {
81565
82053
  __privateMethod$1(this, _PresentationInputBridge_instances, dispatchToTarget_fn).call(this, event, synthetic);
81566
82054
  };
81567
82055
  forwardContextMenu_fn = function(event) {
82056
+ const handledBySlashMenu = Boolean(event[SLASH_MENU_HANDLED_FLAG]);
82057
+ if (handledBySlashMenu) {
82058
+ return;
82059
+ }
81568
82060
  if (!__privateGet$1(this, _isEditable).call(this)) {
81569
82061
  return;
81570
82062
  }
@@ -81670,14 +82162,15 @@ function getAtomNodeTypes(schema) {
81670
82162
  if (!schema) return [];
81671
82163
  const types2 = [];
81672
82164
  try {
81673
- schema.nodes.forEach((nodeType, name) => {
82165
+ for (const name in schema.nodes) {
81674
82166
  if (name === "text") {
81675
- return;
82167
+ continue;
81676
82168
  }
81677
- if (nodeType.isAtom || nodeType.isLeaf) {
82169
+ const nodeType = schema.nodes[name];
82170
+ if (nodeType && (nodeType.isAtom || nodeType.isLeaf)) {
81678
82171
  types2.push(name);
81679
82172
  }
81680
- });
82173
+ }
81681
82174
  } catch {
81682
82175
  return [];
81683
82176
  }
@@ -83080,6 +83573,7 @@ function shouldRequirePageBoundary(current, next) {
83080
83573
  function hasIntrinsicBoundarySignals(_2) {
83081
83574
  return false;
83082
83575
  }
83576
+ const DEFAULT_HEADER_FOOTER_MARGIN_PX = 0;
83083
83577
  function shouldIgnoreSectionBreak(paragraph, index2, total, hasBodySectPr) {
83084
83578
  const paragraphAttrs = paragraph.attrs ?? {};
83085
83579
  const paragraphProperties = paragraphAttrs?.paragraphProperties;
@@ -83120,14 +83614,15 @@ function buildSectionRangesFromParagraphs(paragraphs, hasBodySectPr) {
83120
83614
  const sectionData = extractSectionData(item.node);
83121
83615
  if (!sectionData) return;
83122
83616
  const sectPr = getSectPrFromNode(item.node);
83617
+ const hasAnyMargin = sectionData.headerPx != null || sectionData.footerPx != null || sectionData.topPx != null || sectionData.rightPx != null || sectionData.bottomPx != null || sectionData.leftPx != null;
83123
83618
  const range2 = {
83124
83619
  sectionIndex: idx,
83125
83620
  startParagraphIndex: currentStart,
83126
83621
  endParagraphIndex: item.index,
83127
83622
  sectPr,
83128
- margins: sectionData.headerPx != null || sectionData.footerPx != null ? {
83129
- header: sectionData.headerPx ?? 0,
83130
- footer: sectionData.footerPx ?? 0,
83623
+ margins: hasAnyMargin ? {
83624
+ header: sectionData.headerPx ?? DEFAULT_HEADER_FOOTER_MARGIN_PX,
83625
+ footer: sectionData.footerPx ?? DEFAULT_HEADER_FOOTER_MARGIN_PX,
83131
83626
  top: sectionData.topPx,
83132
83627
  right: sectionData.rightPx,
83133
83628
  bottom: sectionData.bottomPx,
@@ -83169,14 +83664,15 @@ function createFinalSectionFromBodySectPr(bodySectPr, currentStart, totalParagra
83169
83664
  };
83170
83665
  const bodySectionData = extractSectionData(tempNode);
83171
83666
  if (!bodySectionData) return null;
83667
+ const hasAnyMargin = bodySectionData.headerPx != null || bodySectionData.footerPx != null || bodySectionData.topPx != null || bodySectionData.rightPx != null || bodySectionData.bottomPx != null || bodySectionData.leftPx != null;
83172
83668
  return {
83173
83669
  sectionIndex,
83174
83670
  startParagraphIndex: currentStart,
83175
83671
  endParagraphIndex: totalParagraphs - 1,
83176
83672
  sectPr: bodySectPr,
83177
- margins: bodySectionData.headerPx != null || bodySectionData.footerPx != null ? {
83178
- header: bodySectionData.headerPx ?? 0,
83179
- footer: bodySectionData.footerPx ?? 0,
83673
+ margins: hasAnyMargin ? {
83674
+ header: bodySectionData.headerPx ?? DEFAULT_HEADER_FOOTER_MARGIN_PX,
83675
+ footer: bodySectionData.footerPx ?? DEFAULT_HEADER_FOOTER_MARGIN_PX,
83180
83676
  top: bodySectionData.topPx,
83181
83677
  right: bodySectionData.rightPx,
83182
83678
  bottom: bodySectionData.bottomPx,
@@ -84160,11 +84656,27 @@ const collectTrackedChangeFromMarks = (marks) => {
84160
84656
  }, void 0);
84161
84657
  };
84162
84658
  const normalizeUnderlineStyle = (value) => {
84163
- if (value === "none") {
84164
- return void 0;
84659
+ if (value === void 0 || value === null) {
84660
+ return "single";
84165
84661
  }
84166
- if (value === "double" || value === "dotted" || value === "dashed" || value === "wavy") {
84167
- return value;
84662
+ if (typeof value === "boolean") {
84663
+ return value ? "single" : void 0;
84664
+ }
84665
+ if (typeof value === "number") {
84666
+ return value === 0 ? void 0 : "single";
84667
+ }
84668
+ if (typeof value === "string") {
84669
+ const normalized = value.trim().toLowerCase();
84670
+ if (!normalized) {
84671
+ return "single";
84672
+ }
84673
+ if (normalized === "none" || normalized === "0" || normalized === "false" || normalized === "off") {
84674
+ return void 0;
84675
+ }
84676
+ if (normalized === "double" || normalized === "dotted" || normalized === "dashed" || normalized === "wavy") {
84677
+ return normalized;
84678
+ }
84679
+ return "single";
84168
84680
  }
84169
84681
  return "single";
84170
84682
  };
@@ -84316,13 +84828,16 @@ const applyMarksToRun = (run2, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG
84316
84828
  break;
84317
84829
  }
84318
84830
  case "underline": {
84319
- const style2 = normalizeUnderlineStyle(mark.attrs?.underlineType);
84831
+ const underlineValue = mark.attrs?.underlineType ?? mark.attrs?.value ?? mark.attrs?.underline ?? mark.attrs?.style;
84832
+ const style2 = normalizeUnderlineStyle(underlineValue);
84320
84833
  if (style2) {
84321
84834
  const underlineColor = resolveColorFromAttributes(mark.attrs ?? {}, themeColors);
84322
84835
  run2.underline = {
84323
84836
  style: style2,
84324
84837
  color: underlineColor ?? run2.underline?.color
84325
84838
  };
84839
+ } else if (underlineValue !== void 0 && underlineValue !== null) {
84840
+ delete run2.underline;
84326
84841
  }
84327
84842
  break;
84328
84843
  }
@@ -85258,8 +85773,8 @@ function buildSdtCacheKey(nodeType, attrs, explicitKey) {
85258
85773
  }
85259
85774
  return void 0;
85260
85775
  }
85261
- const DEFAULT_LIST_HANGING_PX$1 = 18;
85262
- const LIST_MARKER_GAP$1 = 8;
85776
+ const DEFAULT_LIST_HANGING_PX = 18;
85777
+ const LIST_MARKER_GAP = 8;
85263
85778
  const DEFAULT_BULLET_GLYPH = "•";
85264
85779
  const DEFAULT_DECIMAL_PATTERN = "%1.";
85265
85780
  const ASCII_UPPERCASE_A = 65;
@@ -85670,7 +86185,7 @@ function computeWordParagraphLayout(input) {
85670
86185
  let markerBoxWidthPx;
85671
86186
  let markerX;
85672
86187
  if (hasFirstLineIndent) {
85673
- markerBoxWidthPx = glyphWidthPx != null && glyphWidthPx > 0 ? glyphWidthPx + LIST_MARKER_GAP$1 : DEFAULT_LIST_HANGING_PX$1;
86188
+ markerBoxWidthPx = glyphWidthPx != null && glyphWidthPx > 0 ? glyphWidthPx + LIST_MARKER_GAP : DEFAULT_LIST_HANGING_PX;
85674
86189
  markerX = indentLeftPx + (firstLinePx ?? 0);
85675
86190
  layout.textStartPx = markerX + markerBoxWidthPx;
85676
86191
  layout.hangingPx = 0;
@@ -85770,12 +86285,12 @@ const resolveMarkerBoxWidth = (hangingPxRaw, glyphWidthPx) => {
85770
86285
  let markerBox = Math.max(hangingPxRaw || 0, 0);
85771
86286
  if (markerBox <= 0) {
85772
86287
  if (glyphWidthPx != null && glyphWidthPx > 0) {
85773
- markerBox = glyphWidthPx + LIST_MARKER_GAP$1;
86288
+ markerBox = glyphWidthPx + LIST_MARKER_GAP;
85774
86289
  } else {
85775
- markerBox = DEFAULT_LIST_HANGING_PX$1;
86290
+ markerBox = DEFAULT_LIST_HANGING_PX;
85776
86291
  }
85777
- } else if (glyphWidthPx != null && glyphWidthPx + LIST_MARKER_GAP$1 > markerBox) {
85778
- markerBox = glyphWidthPx + LIST_MARKER_GAP$1;
86292
+ } else if (glyphWidthPx != null && glyphWidthPx + LIST_MARKER_GAP > markerBox) {
86293
+ markerBox = glyphWidthPx + LIST_MARKER_GAP;
85779
86294
  }
85780
86295
  return markerBox;
85781
86296
  };
@@ -85795,7 +86310,7 @@ const buildMarkerLayout = ({
85795
86310
  textStartX: textStartPx,
85796
86311
  baselineOffsetPx: markerRun.baselineShift ?? 0,
85797
86312
  // Gutter is the small gap between marker and text, not the full marker box width
85798
- gutterWidthPx: LIST_MARKER_GAP$1,
86313
+ gutterWidthPx: LIST_MARKER_GAP,
85799
86314
  justification: numbering.lvlJc ?? "left",
85800
86315
  suffix: normalizeSuffix$1(numbering.suffix) ?? "tab",
85801
86316
  run: markerRun,
@@ -85885,7 +86400,10 @@ const hydrateParagraphStyleAttrs = (para, context, preResolved) => {
85885
86400
  tabStops: cloneIfObject(resolvedExtended.tabStops),
85886
86401
  keepLines: resolvedExtended.keepLines,
85887
86402
  keepNext: resolvedExtended.keepNext,
85888
- numberingProperties: cloneIfObject(resolvedAsRecord.numberingProperties)
86403
+ numberingProperties: cloneIfObject(resolvedAsRecord.numberingProperties),
86404
+ // Extract contextualSpacing from style resolution - this is a sibling to spacing in OOXML,
86405
+ // not nested within it. When true, suppresses spacing between paragraphs of the same style.
86406
+ contextualSpacing: resolvedExtended.contextualSpacing
85889
86407
  };
85890
86408
  return hydrated;
85891
86409
  };
@@ -86487,6 +87005,31 @@ const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleCont
86487
87005
  return null;
86488
87006
  }
86489
87007
  };
87008
+ const normalizeWordLayoutForIndent = (wordLayout, paragraphIndent) => {
87009
+ const resolvedIndent = wordLayout.resolvedIndent ?? paragraphIndent ?? {};
87010
+ const indentLeft = isFiniteNumber(resolvedIndent.left) ? resolvedIndent.left : 0;
87011
+ const firstLine = isFiniteNumber(resolvedIndent.firstLine) ? resolvedIndent.firstLine : 0;
87012
+ const hanging = isFiniteNumber(resolvedIndent.hanging) ? resolvedIndent.hanging : 0;
87013
+ const shouldFirstLineIndentMode = firstLine > 0 && !hanging;
87014
+ if (wordLayout.firstLineIndentMode === true && !shouldFirstLineIndentMode) {
87015
+ wordLayout.firstLineIndentMode = false;
87016
+ }
87017
+ if (wordLayout.firstLineIndentMode === true) {
87018
+ if (isFiniteNumber(wordLayout.textStartPx)) {
87019
+ if (wordLayout.marker && (!isFiniteNumber(wordLayout.marker.textStartX) || wordLayout.marker.textStartX !== wordLayout.textStartPx)) {
87020
+ wordLayout.marker.textStartX = wordLayout.textStartPx;
87021
+ }
87022
+ } else if (wordLayout.marker && isFiniteNumber(wordLayout.marker.textStartX)) {
87023
+ wordLayout.textStartPx = wordLayout.marker.textStartX;
87024
+ }
87025
+ } else {
87026
+ wordLayout.textStartPx = indentLeft;
87027
+ if (wordLayout.marker) {
87028
+ wordLayout.marker.textStartX = indentLeft;
87029
+ }
87030
+ }
87031
+ return wordLayout;
87032
+ };
86490
87033
  const computeParagraphAttrs = (para, styleContext, listCounterContext, converterContext, hydrationOverride) => {
86491
87034
  const attrs = para.attrs ?? {};
86492
87035
  const paragraphProps = typeof attrs.paragraphProperties === "object" && attrs.paragraphProperties !== null ? attrs.paragraphProperties : {};
@@ -86595,7 +87138,7 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
86595
87138
  paragraphAttrs.spacing.afterAutospacing = normalizedSpacing.afterAutospacing;
86596
87139
  }
86597
87140
  }
86598
- const contextualSpacingValue = normalizedSpacing?.contextualSpacing ?? safeGetProperty(paragraphProps, "contextualSpacing") ?? safeGetProperty(attrs, "contextualSpacing");
87141
+ const contextualSpacingValue = normalizedSpacing?.contextualSpacing ?? safeGetProperty(paragraphProps, "contextualSpacing") ?? safeGetProperty(attrs, "contextualSpacing") ?? hydrated?.contextualSpacing;
86599
87142
  if (contextualSpacingValue != null) {
86600
87143
  paragraphAttrs.contextualSpacing = isTruthy(contextualSpacingValue);
86601
87144
  }
@@ -86809,8 +87352,11 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
86809
87352
  let wordLayout = computeWordLayoutForParagraph(paragraphAttrs, enrichedNumberingProps, styleContext);
86810
87353
  if (!wordLayout && enrichedNumberingProps.resolvedLevelIndent) {
86811
87354
  const resolvedIndentPx = convertIndentTwipsToPx(enrichedNumberingProps.resolvedLevelIndent);
86812
- const firstLinePx = resolvedIndentPx?.firstLine ?? 0;
86813
- if (firstLinePx > 0) {
87355
+ const baseIndent = resolvedIndentPx ?? enrichedNumberingProps.resolvedLevelIndent;
87356
+ const mergedIndent = { ...baseIndent, ...paragraphAttrs.indent ?? {} };
87357
+ const firstLinePx = isFiniteNumber(mergedIndent.firstLine) ? mergedIndent.firstLine : 0;
87358
+ const hangingPx = isFiniteNumber(mergedIndent.hanging) ? mergedIndent.hanging : 0;
87359
+ if (firstLinePx > 0 && !hangingPx) {
86814
87360
  wordLayout = {
86815
87361
  // Treat as first-line-indent mode: text starts after the marker+firstLine offset.
86816
87362
  firstLineIndentMode: true,
@@ -86818,10 +87364,13 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
86818
87364
  };
86819
87365
  }
86820
87366
  }
86821
- if (wordLayout && (!wordLayout.textStartPx || !Number.isFinite(wordLayout.textStartPx)) && enrichedNumberingProps.resolvedLevelIndent) {
87367
+ if (wordLayout && !Number.isFinite(wordLayout.textStartPx) && enrichedNumberingProps.resolvedLevelIndent) {
86822
87368
  const resolvedIndentPx = convertIndentTwipsToPx(enrichedNumberingProps.resolvedLevelIndent);
86823
- const firstLinePx = resolvedIndentPx?.firstLine ?? 0;
86824
- if (firstLinePx > 0) {
87369
+ const baseIndent = resolvedIndentPx ?? enrichedNumberingProps.resolvedLevelIndent;
87370
+ const mergedIndent = { ...baseIndent, ...paragraphAttrs.indent ?? {} };
87371
+ const firstLinePx = isFiniteNumber(mergedIndent.firstLine) ? mergedIndent.firstLine : 0;
87372
+ const hangingPx = isFiniteNumber(mergedIndent.hanging) ? mergedIndent.hanging : 0;
87373
+ if (firstLinePx > 0 && !hangingPx) {
86825
87374
  wordLayout = {
86826
87375
  ...wordLayout,
86827
87376
  firstLineIndentMode: wordLayout.firstLineIndentMode ?? true,
@@ -86841,6 +87390,7 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
86841
87390
  wordLayout.marker.suffix = listRendering.suffix;
86842
87391
  }
86843
87392
  }
87393
+ wordLayout = normalizeWordLayoutForIndent(wordLayout, paragraphAttrs.indent);
86844
87394
  paragraphAttrs.wordLayout = wordLayout;
86845
87395
  }
86846
87396
  if (enrichedNumberingProps.resolvedLevelIndent) {
@@ -90957,11 +91507,6 @@ function initHeaderFooterRegistry({
90957
91507
  cleanups
90958
91508
  };
90959
91509
  }
90960
- const LIST_MARKER_GAP = 8;
90961
- const MIN_MARKER_GUTTER = 24;
90962
- const DEFAULT_LIST_INDENT_BASE_PX = 24;
90963
- const DEFAULT_LIST_INDENT_STEP_PX = 24;
90964
- const DEFAULT_LIST_HANGING_PX = 18;
90965
91510
  function calculateRotatedBounds(input) {
90966
91511
  const width = Math.max(0, input.width);
90967
91512
  const height = Math.max(0, input.height);
@@ -91225,8 +91770,25 @@ async function measureParagraphBlock(block, maxWidth) {
91225
91770
  const rawTextStartPx = wordLayout?.textStartPx;
91226
91771
  const markerTextStartX = wordLayout?.marker?.textStartX;
91227
91772
  const textStartPx = typeof markerTextStartX === "number" && Number.isFinite(markerTextStartX) ? markerTextStartX : typeof rawTextStartPx === "number" && Number.isFinite(rawTextStartPx) ? rawTextStartPx : void 0;
91228
- if (typeof textStartPx === "number" && textStartPx > indentLeft) {
91229
- initialAvailableWidth = Math.max(1, maxWidth - textStartPx - indentRight);
91773
+ const resolvedTextStartPx = resolveListTextStartPx(
91774
+ wordLayout,
91775
+ indentLeft,
91776
+ firstLine,
91777
+ hanging,
91778
+ (markerText, marker) => {
91779
+ const markerRun = {
91780
+ fontFamily: toCssFontFamily(marker.run?.fontFamily) ?? marker.run?.fontFamily ?? "Arial",
91781
+ fontSize: marker.run?.fontSize ?? 16,
91782
+ bold: marker.run?.bold ?? false,
91783
+ italic: marker.run?.italic ?? false
91784
+ };
91785
+ const { font: markerFont } = buildFontString(markerRun);
91786
+ return measureText(markerText, markerFont, ctx2);
91787
+ }
91788
+ );
91789
+ const effectiveTextStartPx = resolvedTextStartPx ?? textStartPx;
91790
+ if (typeof effectiveTextStartPx === "number" && effectiveTextStartPx > indentLeft) {
91791
+ initialAvailableWidth = Math.max(1, maxWidth - effectiveTextStartPx - indentRight);
91230
91792
  } else {
91231
91793
  initialAvailableWidth = Math.max(1, contentWidth - firstLineOffset);
91232
91794
  }
@@ -91313,7 +91875,7 @@ async function measureParagraphBlock(block, maxWidth) {
91313
91875
  pendingTabAlignment = null;
91314
91876
  return startX;
91315
91877
  };
91316
- const alignSegmentAtTab = (segmentText, font, runContext) => {
91878
+ const alignSegmentAtTab = (segmentText, font, runContext, segmentStartChar) => {
91317
91879
  if (!pendingTabAlignment || !currentLine) return void 0;
91318
91880
  const { val } = pendingTabAlignment;
91319
91881
  let segmentWidth = 0;
@@ -91322,11 +91884,11 @@ async function measureParagraphBlock(block, maxWidth) {
91322
91884
  const idx = segmentText.indexOf(decimalSeparator);
91323
91885
  if (idx >= 0) {
91324
91886
  const beforeText = segmentText.slice(0, idx);
91325
- beforeDecimalWidth = beforeText.length > 0 ? measureRunWidth(beforeText, font, ctx2, runContext) : 0;
91887
+ beforeDecimalWidth = beforeText.length > 0 ? measureRunWidth(beforeText, font, ctx2, runContext, segmentStartChar) : 0;
91326
91888
  }
91327
- segmentWidth = segmentText.length > 0 ? measureRunWidth(segmentText, font, ctx2, runContext) : 0;
91889
+ segmentWidth = segmentText.length > 0 ? measureRunWidth(segmentText, font, ctx2, runContext, segmentStartChar) : 0;
91328
91890
  } else if (val === "end" || val === "center") {
91329
- segmentWidth = segmentText.length > 0 ? measureRunWidth(segmentText, font, ctx2, runContext) : 0;
91891
+ segmentWidth = segmentText.length > 0 ? measureRunWidth(segmentText, font, ctx2, runContext, segmentStartChar) : 0;
91330
91892
  }
91331
91893
  return alignPendingTabForWidth(segmentWidth, beforeDecimalWidth);
91332
91894
  };
@@ -91378,8 +91940,8 @@ async function measureParagraphBlock(block, maxWidth) {
91378
91940
  const { font } = buildFontString(
91379
91941
  lastRun
91380
91942
  );
91381
- const fullWidth = measureRunWidth(sliceText, font, ctx2, lastRun);
91382
- const keptWidth = keptText.length > 0 ? measureRunWidth(keptText, font, ctx2, lastRun) : 0;
91943
+ const fullWidth = measureRunWidth(sliceText, font, ctx2, lastRun, sliceStart);
91944
+ const keptWidth = keptText.length > 0 ? measureRunWidth(keptText, font, ctx2, lastRun, sliceStart) : 0;
91383
91945
  const delta = Math.max(0, fullWidth - keptWidth);
91384
91946
  lineToTrim.width = roundValue(Math.max(0, lineToTrim.width - delta));
91385
91947
  lineToTrim.spaceCount = Math.max(0, lineToTrim.spaceCount - trimCount);
@@ -91590,7 +92152,8 @@ async function measureParagraphBlock(block, maxWidth) {
91590
92152
  continue;
91591
92153
  }
91592
92154
  if (isFieldAnnotationRun(run2)) {
91593
- const displayText = run2.displayLabel || "";
92155
+ const rawDisplayText = run2.displayLabel || "";
92156
+ const displayText = applyTextTransform(rawDisplayText, run2);
91594
92157
  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;
91595
92158
  const annotationFontFamily = run2.fontFamily || "Arial, sans-serif";
91596
92159
  const fontWeight = run2.bold ? "bold" : "normal";
@@ -91693,7 +92256,7 @@ async function measureParagraphBlock(block, maxWidth) {
91693
92256
  const spacesLength = segment.length;
91694
92257
  const spacesStartChar = charPosInRun;
91695
92258
  const spacesEndChar = charPosInRun + spacesLength;
91696
- const spacesWidth = measureRunWidth(segment, font, ctx2, run2);
92259
+ const spacesWidth = measureRunWidth(segment, font, ctx2, run2, spacesStartChar);
91697
92260
  if (!currentLine) {
91698
92261
  currentLine = {
91699
92262
  fromRun: runIndex,
@@ -91757,7 +92320,7 @@ async function measureParagraphBlock(block, maxWidth) {
91757
92320
  }
91758
92321
  let segmentStartX;
91759
92322
  if (currentLine && pendingTabAlignment) {
91760
- segmentStartX = alignSegmentAtTab(segment, font, run2);
92323
+ segmentStartX = alignSegmentAtTab(segment, font, run2, charPosInRun);
91761
92324
  if (segmentStartX == null) {
91762
92325
  segmentStartX = currentLine.width;
91763
92326
  }
@@ -91767,7 +92330,7 @@ async function measureParagraphBlock(block, maxWidth) {
91767
92330
  if (word2 === "") {
91768
92331
  const spaceStartChar = charPosInRun;
91769
92332
  const spaceEndChar = charPosInRun + 1;
91770
- const singleSpaceWidth = measureRunWidth(" ", font, ctx2, run2);
92333
+ const singleSpaceWidth = measureRunWidth(" ", font, ctx2, run2, spaceStartChar);
91771
92334
  if (!currentLine) {
91772
92335
  currentLine = {
91773
92336
  fromRun: runIndex,
@@ -91818,12 +92381,12 @@ async function measureParagraphBlock(block, maxWidth) {
91818
92381
  charPosInRun = spaceEndChar;
91819
92382
  continue;
91820
92383
  }
91821
- const wordOnlyWidth = measureRunWidth(word2, font, ctx2, run2);
91822
- const shouldIncludeDelimiterSpace = wordIndex < lastNonEmptyWordIndex;
91823
- const spaceWidth = shouldIncludeDelimiterSpace ? measureRunWidth(" ", font, ctx2, run2) : 0;
91824
- const wordCommitWidth = wordOnlyWidth + spaceWidth;
91825
92384
  const wordStartChar = charPosInRun;
92385
+ const wordOnlyWidth = measureRunWidth(word2, font, ctx2, run2, wordStartChar);
92386
+ const shouldIncludeDelimiterSpace = wordIndex < lastNonEmptyWordIndex;
91826
92387
  const wordEndNoSpace = charPosInRun + word2.length;
92388
+ const spaceWidth = shouldIncludeDelimiterSpace ? measureRunWidth(" ", font, ctx2, run2, wordEndNoSpace) : 0;
92389
+ const wordCommitWidth = wordOnlyWidth + spaceWidth;
91827
92390
  const wordEndWithSpace = wordEndNoSpace + (shouldIncludeDelimiterSpace ? 1 : 0);
91828
92391
  const effectiveMaxWidth = currentLine ? currentLine.maxWidth : getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : contentWidth);
91829
92392
  if (wordOnlyWidth > effectiveMaxWidth && word2.length > 1) {
@@ -91842,7 +92405,7 @@ async function measureParagraphBlock(block, maxWidth) {
91842
92405
  const hasTabOnlyLine = currentLine && currentLine.segments && currentLine.segments.length === 0 && currentLine.width > 0;
91843
92406
  const remainingWidthAfterTab = hasTabOnlyLine ? currentLine.maxWidth - currentLine.width : lineMaxWidth;
91844
92407
  const chunkWidth = hasTabOnlyLine ? Math.max(remainingWidthAfterTab, lineMaxWidth * 0.25) : lineMaxWidth;
91845
- const chunks = breakWordIntoChunks(word2, chunkWidth - WIDTH_FUDGE_PX2, font, ctx2, run2);
92408
+ const chunks = breakWordIntoChunks(word2, chunkWidth - WIDTH_FUDGE_PX2, font, ctx2, run2, wordStartChar);
91846
92409
  let chunkCharOffset = wordStartChar;
91847
92410
  for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {
91848
92411
  const chunk = chunks[chunkIndex];
@@ -91966,7 +92529,7 @@ async function measureParagraphBlock(block, maxWidth) {
91966
92529
  if (candidateSpaces > 0) {
91967
92530
  const overflow = totalWidthWithWord - availableWidth;
91968
92531
  if (overflow > 0) {
91969
- const baseSpaceWidth = spaceWidth || measureRunWidth(" ", font, ctx2, run2) || Math.max(1, boundarySpacing);
92532
+ const baseSpaceWidth = spaceWidth || measureRunWidth(" ", font, ctx2, run2, wordEndNoSpace) || Math.max(1, boundarySpacing);
91970
92533
  const perSpaceCompression = overflow / candidateSpaces;
91971
92534
  const maxPerSpaceCompression = baseSpaceWidth * 0.25;
91972
92535
  if (perSpaceCompression <= maxPerSpaceCompression) {
@@ -92141,8 +92704,8 @@ async function measureParagraphBlock(block, maxWidth) {
92141
92704
  const { font: markerFont } = buildFontString(markerRun);
92142
92705
  const markerText = wordLayout.marker.markerText ?? "";
92143
92706
  const glyphWidth = markerText ? measureText(markerText, markerFont, ctx2) : 0;
92144
- const gutter = typeof wordLayout.marker.gutterWidthPx === "number" && isFinite(wordLayout.marker.gutterWidthPx) && wordLayout.marker.gutterWidthPx >= 0 ? wordLayout.marker.gutterWidthPx : LIST_MARKER_GAP;
92145
- const markerBoxWidth = Math.max(wordLayout.marker.markerBoxWidthPx ?? 0, glyphWidth + LIST_MARKER_GAP);
92707
+ const gutter = typeof wordLayout.marker.gutterWidthPx === "number" && isFinite(wordLayout.marker.gutterWidthPx) && wordLayout.marker.gutterWidthPx >= 0 ? wordLayout.marker.gutterWidthPx : LIST_MARKER_GAP$1;
92708
+ const markerBoxWidth = Math.max(wordLayout.marker.markerBoxWidthPx ?? 0, glyphWidth + LIST_MARKER_GAP$1);
92146
92709
  markerInfo = {
92147
92710
  markerWidth: markerBoxWidth,
92148
92711
  markerTextWidth: glyphWidth,
@@ -92486,7 +93049,7 @@ async function measureListBlock(block, constraints) {
92486
93049
  markerTextWidth = markerText ? measureText(markerText, markerFont, ctx2) : 0;
92487
93050
  indentLeft = resolveIndentLeft(item);
92488
93051
  const indentHanging = resolveIndentHanging(item);
92489
- markerWidth = Math.max(MIN_MARKER_GUTTER, markerTextWidth + LIST_MARKER_GAP, indentHanging);
93052
+ markerWidth = Math.max(MIN_MARKER_GUTTER, markerTextWidth + LIST_MARKER_GAP$1, indentHanging);
92490
93053
  }
92491
93054
  const paragraphWidth = Math.max(1, constraints.maxWidth - indentLeft - markerWidth);
92492
93055
  const paragraphMeasure = await measureParagraphBlock(item.paragraph, paragraphWidth);
@@ -92512,16 +93075,46 @@ const getPrimaryRun = (paragraph) => {
92512
93075
  fontSize: 16
92513
93076
  };
92514
93077
  };
92515
- const measureRunWidth = (text, font, ctx2, run2) => {
93078
+ const isWordChar = (char) => {
93079
+ if (!char) return false;
93080
+ const code = char.charCodeAt(0);
93081
+ return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || char === "'";
93082
+ };
93083
+ const capitalizeText = (text, fullText, startOffset) => {
93084
+ if (!text) return text;
93085
+ const hasFullText = typeof startOffset === "number" && fullText != null;
93086
+ let result = "";
93087
+ for (let i = 0; i < text.length; i += 1) {
93088
+ const prevChar = hasFullText ? startOffset + i > 0 ? fullText[startOffset + i - 1] : "" : i > 0 ? text[i - 1] : "";
93089
+ const ch = text[i];
93090
+ result += isWordChar(ch) && !isWordChar(prevChar) ? ch.toUpperCase() : ch;
93091
+ }
93092
+ return result;
93093
+ };
93094
+ const applyTextTransform = (text, run2, startOffset) => {
93095
+ const transform = "textTransform" in run2 ? run2.textTransform : void 0;
93096
+ if (!text || !transform || transform === "none") return text;
93097
+ if (transform === "uppercase") return text.toUpperCase();
93098
+ if (transform === "lowercase") return text.toLowerCase();
93099
+ if (transform === "capitalize") {
93100
+ const fullText = "text" in run2 && typeof run2.text === "string" ? run2.text : text;
93101
+ return capitalizeText(text, fullText, startOffset);
93102
+ }
93103
+ return text;
93104
+ };
93105
+ const measureRunWidth = (text, font, ctx2, run2, startOffset) => {
92516
93106
  const letterSpacing = run2.kind === "text" || run2.kind === void 0 ? run2.letterSpacing || 0 : 0;
92517
- const width = getMeasuredTextWidth(text, font, letterSpacing, ctx2);
93107
+ const displayText = applyTextTransform(text, run2, startOffset);
93108
+ const width = getMeasuredTextWidth(displayText, font, letterSpacing, ctx2);
92518
93109
  return roundValue(width);
92519
93110
  };
92520
- const breakWordIntoChunks = (word2, maxWidth, font, ctx2, run2) => {
93111
+ const breakWordIntoChunks = (word2, maxWidth, font, ctx2, run2, startOffset) => {
92521
93112
  const chunks = [];
93113
+ const baseOffset = typeof startOffset === "number" ? startOffset : 0;
92522
93114
  if (maxWidth <= 0) {
92523
- for (const char of word2) {
92524
- const charWidth = measureRunWidth(char, font, ctx2, run2);
93115
+ for (let i = 0; i < word2.length; i++) {
93116
+ const char = word2[i];
93117
+ const charWidth = measureRunWidth(char, font, ctx2, run2, baseOffset + i);
92525
93118
  chunks.push({ text: char, width: charWidth });
92526
93119
  }
92527
93120
  return chunks;
@@ -92531,11 +93124,11 @@ const breakWordIntoChunks = (word2, maxWidth, font, ctx2, run2) => {
92531
93124
  for (let i = 0; i < word2.length; i++) {
92532
93125
  const char = word2[i];
92533
93126
  const testChunk = currentChunk + char;
92534
- const testWidth = measureRunWidth(testChunk, font, ctx2, run2);
93127
+ const testWidth = measureRunWidth(testChunk, font, ctx2, run2, baseOffset);
92535
93128
  if (testWidth > maxWidth && currentChunk.length > 0) {
92536
93129
  chunks.push({ text: currentChunk, width: currentWidth });
92537
93130
  currentChunk = char;
92538
- currentWidth = measureRunWidth(char, font, ctx2, run2);
93131
+ currentWidth = measureRunWidth(char, font, ctx2, run2, baseOffset + i);
92539
93132
  } else {
92540
93133
  currentChunk = testChunk;
92541
93134
  currentWidth = testWidth;
@@ -92589,7 +93182,8 @@ const measureDropCap = (ctx2, descriptor, spacing) => {
92589
93182
  italic: run2.italic
92590
93183
  });
92591
93184
  ctx2.font = font;
92592
- const metrics = ctx2.measureText(run2.text);
93185
+ const displayText = applyTextTransform(run2.text, run2);
93186
+ const metrics = ctx2.measureText(displayText);
92593
93187
  const advanceWidth = metrics.width;
92594
93188
  const paintedWidth = (metrics.actualBoundingBoxLeft || 0) + (metrics.actualBoundingBoxRight || 0);
92595
93189
  const textWidth = Math.max(advanceWidth, paintedWidth);
@@ -92615,7 +93209,7 @@ const resolveIndentHanging = (item) => {
92615
93209
  if (indentHanging > 0) {
92616
93210
  return indentHanging;
92617
93211
  }
92618
- return DEFAULT_LIST_HANGING_PX;
93212
+ return DEFAULT_LIST_HANGING_PX$1;
92619
93213
  };
92620
93214
  const buildTabStopsPx = (indent, tabs, tabIntervalTwips) => {
92621
93215
  const paragraphIndentTwips = {
@@ -92821,6 +93415,9 @@ const _PresentationEditor = class _PresentationEditor2 extends EventEmitter$1 {
92821
93415
  if (event.button !== 0) {
92822
93416
  return;
92823
93417
  }
93418
+ if (event.ctrlKey && navigator.platform.includes("Mac")) {
93419
+ return;
93420
+ }
92824
93421
  __privateSet(this, _pendingMarginClick, null);
92825
93422
  const target = event.target;
92826
93423
  if (target?.closest?.(".superdoc-ruler-handle") != null) {
@@ -98230,6 +98827,8 @@ const SlashMenu = Extension.create({
98230
98827
  const cbRect = containingBlock.getBoundingClientRect();
98231
98828
  left2 -= cbRect.left;
98232
98829
  top2 -= cbRect.top;
98830
+ left2 += containingBlock.scrollLeft || 0;
98831
+ top2 += containingBlock.scrollTop || 0;
98233
98832
  } catch (error) {
98234
98833
  console.warn("SlashMenu: Failed to adjust for containing block", error);
98235
98834
  }
@@ -129568,7 +130167,7 @@ const _sfc_main$8 = {
129568
130167
  if (open) {
129569
130168
  nextTick(() => {
129570
130169
  if (searchInput.value) {
129571
- searchInput.value.focus();
130170
+ searchInput.value.focus({ preventScroll: true });
129572
130171
  }
129573
130172
  });
129574
130173
  }
@@ -129673,15 +130272,31 @@ const _sfc_main$8 = {
129673
130272
  };
129674
130273
  const handleGlobalOutsideClick = (event) => {
129675
130274
  if (isOpen.value && menuRef.value && !menuRef.value.contains(event.target)) {
129676
- moveCursorToMouseEvent(event, props.editor);
130275
+ const isCtrlClickOnMac = event.ctrlKey && isMacOS();
130276
+ const isLeftClick = event.button === 0 && !isCtrlClickOnMac;
130277
+ if (isLeftClick) {
130278
+ moveCursorToMouseEvent(event, props.editor);
130279
+ }
129677
130280
  closeMenu({ restoreCursor: false });
129678
130281
  }
129679
130282
  };
129680
- const handleRightClick = async (event) => {
130283
+ const shouldHandleContextMenu = (event) => {
129681
130284
  const readOnly = !props.editor?.isEditable;
129682
130285
  const contextMenuDisabled = props.editor?.options?.disableContextMenu;
129683
130286
  const bypass = shouldBypassContextMenu(event);
129684
- if (readOnly || contextMenuDisabled || bypass) {
130287
+ return !readOnly && !contextMenuDisabled && !bypass;
130288
+ };
130289
+ const handleRightClickCapture = (event) => {
130290
+ try {
130291
+ if (shouldHandleContextMenu(event)) {
130292
+ event[SLASH_MENU_HANDLED_FLAG] = true;
130293
+ }
130294
+ } catch (error) {
130295
+ console.warn("[SlashMenu] Error in capture phase context menu handler:", error);
130296
+ }
130297
+ };
130298
+ const handleRightClick = async (event) => {
130299
+ if (!shouldHandleContextMenu(event)) {
129685
130300
  return;
129686
130301
  }
129687
130302
  event.preventDefault();
@@ -129792,6 +130407,7 @@ const _sfc_main$8 = {
129792
130407
  props.editor.on("slashMenu:open", slashMenuOpenHandler);
129793
130408
  contextMenuTarget = getEditorSurfaceElement(props.editor);
129794
130409
  if (contextMenuTarget) {
130410
+ contextMenuTarget.addEventListener("contextmenu", handleRightClickCapture, true);
129795
130411
  contextMenuTarget.addEventListener("contextmenu", handleRightClick);
129796
130412
  }
129797
130413
  slashMenuCloseHandler = () => {
@@ -129815,6 +130431,7 @@ const _sfc_main$8 = {
129815
130431
  props.editor.off("slashMenu:close", slashMenuCloseHandler);
129816
130432
  }
129817
130433
  props.editor.off("update", handleEditorUpdate);
130434
+ contextMenuTarget?.removeEventListener("contextmenu", handleRightClickCapture, true);
129818
130435
  contextMenuTarget?.removeEventListener("contextmenu", handleRightClick);
129819
130436
  } catch (error) {
129820
130437
  console.warn("[SlashMenu] Error during cleanup:", error);
@@ -131781,6 +132398,12 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
131781
132398
  if (props.options?.suppressSkeletonLoader || !props.options?.collaborationProvider) editorReady.value = true;
131782
132399
  });
131783
132400
  const handleMarginClick = (event) => {
132401
+ if (event.button !== 0) {
132402
+ return;
132403
+ }
132404
+ if (event.ctrlKey && isMacOS()) {
132405
+ return;
132406
+ }
131784
132407
  if (event.target.classList.contains("ProseMirror")) return;
131785
132408
  onMarginClickCursorChange(event, activeEditor.value);
131786
132409
  };
@@ -131919,7 +132542,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
131919
132542
  };
131920
132543
  }
131921
132544
  });
131922
- const SuperEditor = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-209a1e8b"]]);
132545
+ const SuperEditor = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-c9a3c876"]]);
131923
132546
  const _hoisted_1 = ["innerHTML"];
131924
132547
  const _sfc_main = {
131925
132548
  __name: "SuperInput",