@harbour-enterprises/superdoc 1.3.0-next.9 → 1.3.0

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.
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  const jszip = require("./jszip-C8_CqJxM.cjs");
3
3
  const helpers$1 = require("./helpers-nOdwpmwb.cjs");
4
- const superEditor_converter = require("./SuperConverter-BuhT_Z5G.cjs");
4
+ const superEditor_converter = require("./SuperConverter-BJ-tba6U.cjs");
5
5
  const vue = require("./vue-De9wkgLl.cjs");
6
6
  require("./jszip.min-BPh2MMAa.cjs");
7
7
  const eventemitter3 = require("./eventemitter3-BQuRcMPI.cjs");
@@ -10953,6 +10953,105 @@ const setSectionHeaderFooterAtSelection = ({ headerInches, footerInches } = {})
10953
10953
  tr.setNodeMarkup(pos, void 0, nextAttrs, node.marks);
10954
10954
  return true;
10955
10955
  };
10956
+ function findGoverningSectPrParagraph(doc2, selectionPos) {
10957
+ const candidates = [];
10958
+ doc2.descendants((node, nodePos) => {
10959
+ if (node.type?.name === "paragraph" && node.attrs?.paragraphProperties?.sectPr) {
10960
+ candidates.push({ node, pos: nodePos });
10961
+ }
10962
+ });
10963
+ if (!candidates.length) return null;
10964
+ const inside = candidates.find((c2) => selectionPos >= c2.pos && selectionPos < c2.pos + c2.node.nodeSize);
10965
+ if (inside) return inside;
10966
+ const atOrAfter = candidates.find((c2) => c2.pos >= selectionPos);
10967
+ return atOrAfter ?? candidates[candidates.length - 1];
10968
+ }
10969
+ const setSectionPageMarginsAtSelection = ({ topInches, rightInches, bottomInches, leftInches } = {}) => ({ tr, state, editor }) => {
10970
+ if (!state || !editor) {
10971
+ console.warn("[setSectionPageMarginsAtSelection] Missing state or editor");
10972
+ return false;
10973
+ }
10974
+ const hasTop = typeof topInches === "number";
10975
+ const hasRight = typeof rightInches === "number";
10976
+ const hasBottom = typeof bottomInches === "number";
10977
+ const hasLeft = typeof leftInches === "number";
10978
+ if (!hasTop && !hasRight && !hasBottom && !hasLeft) {
10979
+ console.warn("[setSectionPageMarginsAtSelection] No margin values provided");
10980
+ return false;
10981
+ }
10982
+ if (hasTop && topInches < 0 || hasRight && rightInches < 0 || hasBottom && bottomInches < 0 || hasLeft && leftInches < 0) {
10983
+ console.warn("[setSectionPageMarginsAtSelection] Margin values must be >= 0");
10984
+ return false;
10985
+ }
10986
+ const updates = {};
10987
+ if (hasTop) updates.topInches = topInches;
10988
+ if (hasRight) updates.rightInches = rightInches;
10989
+ if (hasBottom) updates.bottomInches = bottomInches;
10990
+ if (hasLeft) updates.leftInches = leftInches;
10991
+ const { from: from3 } = state.selection;
10992
+ const governing = findGoverningSectPrParagraph(state.doc, from3);
10993
+ if (governing) {
10994
+ const { node, pos } = governing;
10995
+ const paraProps = node.attrs?.paragraphProperties || null;
10996
+ const existingSectPr = paraProps?.sectPr || null;
10997
+ if (!existingSectPr) {
10998
+ console.warn("[setSectionPageMarginsAtSelection] Paragraph found but has no sectPr");
10999
+ return false;
11000
+ }
11001
+ const sectPr2 = JSON.parse(JSON.stringify(existingSectPr));
11002
+ try {
11003
+ updateSectionMargins({ type: "sectPr", sectPr: sectPr2 }, updates);
11004
+ } catch (err) {
11005
+ console.error("[setSectionPageMarginsAtSelection] Failed to update sectPr:", err);
11006
+ return false;
11007
+ }
11008
+ const resolved = getSectPrMargins(sectPr2);
11009
+ const normalizedSectionMargins = {
11010
+ top: resolved.top ?? null,
11011
+ right: resolved.right ?? null,
11012
+ bottom: resolved.bottom ?? null,
11013
+ left: resolved.left ?? null,
11014
+ header: resolved.header ?? null,
11015
+ footer: resolved.footer ?? null
11016
+ };
11017
+ const newParagraphProperties = { ...paraProps || {}, sectPr: sectPr2 };
11018
+ const nextAttrs = {
11019
+ ...node.attrs,
11020
+ paragraphProperties: newParagraphProperties,
11021
+ sectionMargins: normalizedSectionMargins
11022
+ };
11023
+ tr.setNodeMarkup(pos, void 0, nextAttrs, node.marks);
11024
+ tr.setMeta("forceUpdatePagination", true);
11025
+ return true;
11026
+ }
11027
+ const docAttrs = state.doc.attrs ?? {};
11028
+ const converter = editor.converter ?? null;
11029
+ const baseBodySectPr = docAttrs.bodySectPr || converter?.bodySectPr || null;
11030
+ const sectPr = baseBodySectPr != null ? JSON.parse(JSON.stringify(baseBodySectPr)) : { type: "element", name: "w:sectPr", elements: [] };
11031
+ try {
11032
+ updateSectionMargins({ type: "sectPr", sectPr }, updates);
11033
+ } catch (err) {
11034
+ console.error("[setSectionPageMarginsAtSelection] Failed to update sectPr:", err);
11035
+ return false;
11036
+ }
11037
+ if (converter) {
11038
+ converter.bodySectPr = sectPr;
11039
+ if (!converter.pageStyles) converter.pageStyles = {};
11040
+ if (!converter.pageStyles.pageMargins) converter.pageStyles.pageMargins = {};
11041
+ const pageMargins = converter.pageStyles.pageMargins;
11042
+ const resolved = getSectPrMargins(sectPr);
11043
+ if (resolved.top != null) pageMargins.top = resolved.top;
11044
+ if (resolved.right != null) pageMargins.right = resolved.right;
11045
+ if (resolved.bottom != null) pageMargins.bottom = resolved.bottom;
11046
+ if (resolved.left != null) pageMargins.left = resolved.left;
11047
+ if (resolved.header != null) pageMargins.header = resolved.header;
11048
+ if (resolved.footer != null) pageMargins.footer = resolved.footer;
11049
+ }
11050
+ const nextDocAttrs = { ...docAttrs, bodySectPr: sectPr };
11051
+ tr.setNodeMarkup(0, void 0, nextDocAttrs);
11052
+ tr.setMeta("forceUpdatePagination", true);
11053
+ return true;
11054
+ };
10956
11055
  const insertSectionBreakAtSelection = ({ headerInches, footerInches } = {}) => ({ tr, state, editor }) => {
10957
11056
  if (!state || !editor) {
10958
11057
  console.warn("[insertSectionBreakAtSelection] Missing state or editor");
@@ -11484,6 +11583,7 @@ const commands$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
11484
11583
  setMeta,
11485
11584
  setNode,
11486
11585
  setSectionHeaderFooterAtSelection,
11586
+ setSectionPageMarginsAtSelection,
11487
11587
  setTextIndentation,
11488
11588
  setTextSelection,
11489
11589
  skipTab,
@@ -15351,7 +15451,7 @@ const canUseDOM = () => {
15351
15451
  return false;
15352
15452
  }
15353
15453
  };
15354
- const summaryVersion = "1.3.0-next.9";
15454
+ const summaryVersion = "1.3.0";
15355
15455
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
15356
15456
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
15357
15457
  function mapAttributes(attrs) {
@@ -17353,9 +17453,8 @@ class Editor extends EventEmitter {
17353
17453
  try {
17354
17454
  const jsonObj = json;
17355
17455
  const attrs = jsonObj.attrs;
17356
- const hasBody = attrs && "bodySectPr" in attrs;
17357
17456
  const converter = this.converter;
17358
- if (!hasBody && converter && converter.bodySectPr) {
17457
+ if (converter && converter.bodySectPr) {
17359
17458
  jsonObj.attrs = attrs || {};
17360
17459
  jsonObj.attrs.bodySectPr = converter.bodySectPr;
17361
17460
  }
@@ -17984,7 +18083,7 @@ class Editor extends EventEmitter {
17984
18083
  * Process collaboration migrations
17985
18084
  */
17986
18085
  processCollaborationMigrations() {
17987
- console.debug("[checkVersionMigrations] Current editor version", "1.3.0-next.9");
18086
+ console.debug("[checkVersionMigrations] Current editor version", "1.3.0");
17988
18087
  if (!this.options.ydoc) return;
17989
18088
  const metaMap = this.options.ydoc.getMap("meta");
17990
18089
  let docVersion = metaMap.get("version");
@@ -40283,6 +40382,13 @@ const applyTrackedChangesModeToRuns = (runs, config, hyperlinkConfig, applyMarks
40283
40382
  );
40284
40383
  }
40285
40384
  });
40385
+ if ((config.mode === "original" || config.mode === "final") && config.enabled) {
40386
+ filtered.forEach((run) => {
40387
+ if (isTextRun$1(run) && run.trackedChange && (run.trackedChange.kind === "insert" || run.trackedChange.kind === "delete")) {
40388
+ delete run.trackedChange;
40389
+ }
40390
+ });
40391
+ }
40286
40392
  }
40287
40393
  return filtered;
40288
40394
  };
@@ -43348,7 +43454,16 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
43348
43454
  if (!value || typeof value !== "object") return;
43349
43455
  return normalizePxIndent(value) ?? convertIndentTwipsToPx(value);
43350
43456
  };
43351
- const normalizedIndent = normalizeIndentObject(attrs.indent) ?? convertIndentTwipsToPx(paragraphProps.indent) ?? convertIndentTwipsToPx(hydrated?.indent) ?? normalizeParagraphIndent(attrs.textIndent);
43457
+ const hydratedIndentPx = convertIndentTwipsToPx(hydrated?.indent);
43458
+ const paragraphIndentPx = convertIndentTwipsToPx(paragraphProps.indent);
43459
+ const textIndentPx = normalizeParagraphIndent(attrs.textIndent);
43460
+ const attrsIndentPx = normalizeIndentObject(attrs.indent);
43461
+ const indentChain = [];
43462
+ if (hydratedIndentPx) indentChain.push({ indent: hydratedIndentPx });
43463
+ if (paragraphIndentPx) indentChain.push({ indent: paragraphIndentPx });
43464
+ if (textIndentPx) indentChain.push({ indent: textIndentPx });
43465
+ if (attrsIndentPx) indentChain.push({ indent: attrsIndentPx });
43466
+ const normalizedIndent = indentChain.length ? superEditor_converter.combineIndentProperties(indentChain).indent : void 0;
43352
43467
  const unwrapTabStops = (tabStops) => {
43353
43468
  if (!Array.isArray(tabStops)) {
43354
43469
  return void 0;
@@ -48627,10 +48742,13 @@ async function measureParagraphBlock(block, maxWidth) {
48627
48742
  };
48628
48743
  }
48629
48744
  const originX = currentLine.width;
48630
- const { target, nextIndex, stop } = getNextTabStopPx(currentLine.width, tabStops, tabStopCursor);
48745
+ const effectiveIndent = lines.length === 0 ? indentLeft + rawFirstLineOffset : indentLeft;
48746
+ const absCurrentX = currentLine.width + effectiveIndent;
48747
+ const { target, nextIndex, stop } = getNextTabStopPx(absCurrentX, tabStops, tabStopCursor);
48631
48748
  tabStopCursor = nextIndex;
48632
- const clampedTarget = Math.min(target, currentLine.maxWidth);
48633
- const tabAdvance = Math.max(0, clampedTarget - currentLine.width);
48749
+ const maxAbsWidth = currentLine.maxWidth + effectiveIndent;
48750
+ const clampedTarget = Math.min(target, maxAbsWidth);
48751
+ const tabAdvance = Math.max(0, clampedTarget - absCurrentX);
48634
48752
  currentLine.width = roundValue(currentLine.width + tabAdvance);
48635
48753
  run.width = tabAdvance;
48636
48754
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, 12);
@@ -48638,8 +48756,9 @@ async function measureParagraphBlock(block, maxWidth) {
48638
48756
  currentLine.toChar = 1;
48639
48757
  if (stop && stop.leader && stop.leader !== "none") {
48640
48758
  const leaderStyle = stop.leader;
48641
- const from3 = Math.min(originX, clampedTarget);
48642
- const to = Math.max(originX, clampedTarget);
48759
+ const relativeTarget = clampedTarget - effectiveIndent;
48760
+ const from3 = Math.min(originX, relativeTarget);
48761
+ const to = Math.max(originX, relativeTarget);
48643
48762
  if (!currentLine.leaders) currentLine.leaders = [];
48644
48763
  currentLine.leaders.push({ from: from3, to, style: leaderStyle });
48645
48764
  }
@@ -48648,27 +48767,28 @@ async function measureParagraphBlock(block, maxWidth) {
48648
48767
  if (stop.val === "end" || stop.val === "center" || stop.val === "decimal") {
48649
48768
  const groupMeasure = measureTabAlignmentGroup(runIndex + 1, runsToProcess, ctx2, decimalSeparator);
48650
48769
  if (groupMeasure.totalWidth > 0) {
48770
+ const relativeTarget = clampedTarget - effectiveIndent;
48651
48771
  let groupStartX;
48652
48772
  if (stop.val === "end") {
48653
- groupStartX = Math.max(0, clampedTarget - groupMeasure.totalWidth);
48773
+ groupStartX = Math.max(0, relativeTarget - groupMeasure.totalWidth);
48654
48774
  } else if (stop.val === "center") {
48655
- groupStartX = Math.max(0, clampedTarget - groupMeasure.totalWidth / 2);
48775
+ groupStartX = Math.max(0, relativeTarget - groupMeasure.totalWidth / 2);
48656
48776
  } else {
48657
48777
  const beforeDecimal = groupMeasure.beforeDecimalWidth ?? groupMeasure.totalWidth;
48658
- groupStartX = Math.max(0, clampedTarget - beforeDecimal);
48778
+ groupStartX = Math.max(0, relativeTarget - beforeDecimal);
48659
48779
  }
48660
48780
  activeTabGroup = {
48661
48781
  measure: groupMeasure,
48662
48782
  startX: groupStartX,
48663
48783
  currentX: groupStartX,
48664
- target: clampedTarget,
48784
+ target: relativeTarget,
48665
48785
  val: stop.val
48666
48786
  };
48667
48787
  currentLine.width = roundValue(groupStartX);
48668
48788
  }
48669
48789
  pendingTabAlignment = null;
48670
48790
  } else {
48671
- pendingTabAlignment = { target: clampedTarget, val: stop.val };
48791
+ pendingTabAlignment = { target: clampedTarget - effectiveIndent, val: stop.val };
48672
48792
  }
48673
48793
  } else {
48674
48794
  pendingTabAlignment = null;
@@ -49309,10 +49429,13 @@ async function measureParagraphBlock(block, maxWidth) {
49309
49429
  };
49310
49430
  }
49311
49431
  const originX = currentLine.width;
49312
- const { target, nextIndex, stop } = getNextTabStopPx(currentLine.width, tabStops, tabStopCursor);
49432
+ const effectiveIndent = lines.length === 0 ? indentLeft + rawFirstLineOffset : indentLeft;
49433
+ const absCurrentX = currentLine.width + effectiveIndent;
49434
+ const { target, nextIndex, stop } = getNextTabStopPx(absCurrentX, tabStops, tabStopCursor);
49313
49435
  tabStopCursor = nextIndex;
49314
- const clampedTarget = Math.min(target, currentLine.maxWidth);
49315
- const tabAdvance = Math.max(0, clampedTarget - currentLine.width);
49436
+ const maxAbsWidth = currentLine.maxWidth + effectiveIndent;
49437
+ const clampedTarget = Math.min(target, maxAbsWidth);
49438
+ const tabAdvance = Math.max(0, clampedTarget - absCurrentX);
49316
49439
  currentLine.width = roundValue(currentLine.width + tabAdvance);
49317
49440
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run);
49318
49441
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run.fontSize);
@@ -49321,14 +49444,15 @@ async function measureParagraphBlock(block, maxWidth) {
49321
49444
  charPosInRun += 1;
49322
49445
  if (stop) {
49323
49446
  validateTabStopVal(stop);
49324
- pendingTabAlignment = { target: clampedTarget, val: stop.val };
49447
+ pendingTabAlignment = { target: clampedTarget - effectiveIndent, val: stop.val };
49325
49448
  } else {
49326
49449
  pendingTabAlignment = null;
49327
49450
  }
49328
49451
  if (stop && stop.leader && stop.leader !== "none" && stop.leader !== "middleDot") {
49329
49452
  const leaderStyle = stop.leader;
49330
- const from3 = Math.min(originX, clampedTarget);
49331
- const to = Math.max(originX, clampedTarget);
49453
+ const relativeTarget = clampedTarget - effectiveIndent;
49454
+ const from3 = Math.min(originX, relativeTarget);
49455
+ const to = Math.max(originX, relativeTarget);
49332
49456
  if (!currentLine.leaders) currentLine.leaders = [];
49333
49457
  currentLine.leaders.push({ from: from3, to, style: leaderStyle });
49334
49458
  }
@@ -49604,7 +49728,11 @@ async function measureTableBlock(block, constraints) {
49604
49728
  }
49605
49729
  async function measureImageBlock(block, constraints) {
49606
49730
  const intrinsic = getIntrinsicImageSize(block, constraints.maxWidth);
49607
- const maxWidth = constraints.maxWidth > 0 ? constraints.maxWidth : intrinsic.width;
49731
+ const isBlockBehindDoc = block.anchor?.behindDoc;
49732
+ const isBlockWrapBehindDoc = block.wrap?.type === "None" && block.wrap?.behindDoc;
49733
+ const bypassWidthConstraint = isBlockBehindDoc || isBlockWrapBehindDoc;
49734
+ const isWidthConstraintBypassed = bypassWidthConstraint || constraints.maxWidth <= 0;
49735
+ const maxWidth = isWidthConstraintBypassed ? intrinsic.width : constraints.maxWidth;
49608
49736
  const hasNegativeVerticalPosition = block.anchor?.isAnchored && (typeof block.anchor?.offsetV === "number" && block.anchor.offsetV < 0 || typeof block.margin?.top === "number" && block.margin.top < 0);
49609
49737
  const maxHeight = hasNegativeVerticalPosition || !constraints.maxHeight || constraints.maxHeight <= 0 ? Infinity : constraints.maxHeight;
49610
49738
  const widthScale = maxWidth / intrinsic.width;
@@ -50771,9 +50899,10 @@ class PresentationEditor extends EventEmitter {
50771
50899
  throw new TypeError("[PresentationEditor] setTrackedChangesOverrides expects an object or undefined");
50772
50900
  }
50773
50901
  if (overrides !== void 0) {
50774
- if (overrides.mode !== void 0 && !["review", "simple", "original"].includes(overrides.mode)) {
50902
+ const validModes = ["review", "original", "final", "off"];
50903
+ if (overrides.mode !== void 0 && !validModes.includes(overrides.mode)) {
50775
50904
  throw new TypeError(
50776
- `[PresentationEditor] Invalid tracked changes mode "${overrides.mode}". Must be one of: review, simple, original`
50905
+ `[PresentationEditor] Invalid tracked changes mode "${overrides.mode}". Must be one of: ${validModes.join(", ")}`
50777
50906
  );
50778
50907
  }
50779
50908
  if (overrides.enabled !== void 0 && typeof overrides.enabled !== "boolean") {
@@ -54724,7 +54853,7 @@ class PresentationEditor extends EventEmitter {
54724
54853
  const zoom = this.#layoutOptions.zoom ?? 1;
54725
54854
  const layoutMode = this.#layoutOptions.layoutMode ?? "vertical";
54726
54855
  const pages = this.#layoutState.layout?.pages;
54727
- const pageGap = this.#layoutState.layout?.pageGap ?? this.#getEffectivePageGap();
54856
+ const pageGap = this.#getEffectivePageGap();
54728
54857
  const defaultWidth = this.#layoutOptions.pageSize?.w ?? DEFAULT_PAGE_SIZE.w;
54729
54858
  const defaultHeight = this.#layoutOptions.pageSize?.h ?? DEFAULT_PAGE_SIZE.h;
54730
54859
  let maxWidth = defaultWidth;
@@ -57835,7 +57964,11 @@ const Document = Node$1.create({
57835
57964
  */
57836
57965
  clearDocument: () => ({ commands: commands2 }) => {
57837
57966
  return commands2.setContent("<p></p>");
57838
- }
57967
+ },
57968
+ /**
57969
+ * Set section page margins (top/right/bottom/left) for the section at the current selection.
57970
+ */
57971
+ setSectionPageMarginsAtSelection
57839
57972
  };
57840
57973
  }
57841
57974
  });
@@ -58489,12 +58622,18 @@ function findParagraphContext($pos, cache2, helpers2) {
58489
58622
  return null;
58490
58623
  }
58491
58624
  function extractParagraphContext(node, startPos, helpers2, depth = 0) {
58492
- const paragraphProperties = superEditor_converter.getResolvedParagraphProperties(node) ?? {};
58625
+ const paragraphProperties = superEditor_converter.getResolvedParagraphProperties(node) ?? node.attrs?.paragraphProperties ?? {};
58493
58626
  const alignmentAliases = { left: "start", right: "end" };
58494
58627
  let tabStops = [];
58495
58628
  if (Array.isArray(paragraphProperties.tabStops)) {
58496
58629
  tabStops = paragraphProperties.tabStops.map((stop) => {
58497
58630
  const ref = stop?.tab;
58631
+ if (!ref && stop?.pos != null) {
58632
+ return {
58633
+ ...stop,
58634
+ pos: twipsToPixels(Number(stop.pos) || 0)
58635
+ };
58636
+ }
58498
58637
  if (!ref) return stop || null;
58499
58638
  const rawType = ref.tabType || "start";
58500
58639
  const mappedVal = alignmentAliases[rawType] || rawType;
@@ -59760,6 +59899,13 @@ function createLayoutRequest(doc2, paragraphPos, view, helpers2, revision, parag
59760
59899
  pos: entry.pos,
59761
59900
  nodeSize: node.nodeSize
59762
59901
  });
59902
+ } else if (node.type.name === "lineBreak" || node.type.name === "hardBreak") {
59903
+ spans.push({
59904
+ type: node.type.name,
59905
+ spanId,
59906
+ pos: entry.pos,
59907
+ nodeSize: node.nodeSize
59908
+ });
59763
59909
  } else if (node.type.name === "text") {
59764
59910
  spans.push({
59765
59911
  type: "text",
@@ -59809,6 +59955,7 @@ function calculateTabLayout(request, measurement, view) {
59809
59955
  paragraphNode
59810
59956
  } = request;
59811
59957
  const tabs = {};
59958
+ const leftIndentPx = request.indents?.left ?? 0;
59812
59959
  let currentX = indentWidth;
59813
59960
  const measureText2 = (span) => {
59814
59961
  if (view && typeof span.from === "number" && typeof span.to === "number") {
@@ -59821,6 +59968,8 @@ function calculateTabLayout(request, measurement, view) {
59821
59968
  const span = spans[i];
59822
59969
  if (span.type === "text") {
59823
59970
  currentX += measureText2(span);
59971
+ } else if (span.type === "lineBreak" || span.type === "hardBreak") {
59972
+ currentX = leftIndentPx;
59824
59973
  } else if (span.type === "tab") {
59825
59974
  const followingText = collectFollowingText(spans, i + 1);
59826
59975
  let measureTextCallback;
@@ -59916,7 +60065,7 @@ function collectFollowingText(spans, startIndex) {
59916
60065
  let text = "";
59917
60066
  for (let i = startIndex; i < spans.length; i++) {
59918
60067
  const span = spans[i];
59919
- if (span.type === "tab") break;
60068
+ if (span.type === "tab" || span.type === "lineBreak" || span.type === "hardBreak") break;
59920
60069
  if (span.type === "text") text += span.text || "";
59921
60070
  }
59922
60071
  return text;
@@ -59926,7 +60075,7 @@ function getFollowingTextRange(spans, startIndex) {
59926
60075
  let to = null;
59927
60076
  for (let i = startIndex; i < spans.length; i++) {
59928
60077
  const span = spans[i];
59929
- if (span.type === "tab") break;
60078
+ if (span.type === "tab" || span.type === "lineBreak" || span.type === "hardBreak") break;
59930
60079
  if (span.type === "text" && typeof span.from === "number" && typeof span.to === "number") {
59931
60080
  if (from3 === null) from3 = span.from;
59932
60081
  to = span.to;
@@ -64344,6 +64493,10 @@ const Image = Node$1.create({
64344
64493
  }
64345
64494
  const hasAnchorData = Boolean(anchorData);
64346
64495
  const hasMarginOffsets = marginOffset?.horizontal != null || marginOffset?.top != null;
64496
+ const isWrapBehindDoc = wrap?.attrs?.behindDoc;
64497
+ const isAnchorBehindDoc = anchorData?.behindDoc;
64498
+ const isBehindDocAnchor = wrap?.type === "None" && (isWrapBehindDoc || isAnchorBehindDoc);
64499
+ const isAbsolutelyPositioned = style2.includes("position: absolute;");
64347
64500
  if (hasAnchorData) {
64348
64501
  switch (anchorData.hRelativeFrom) {
64349
64502
  case "page":
@@ -64371,7 +64524,6 @@ const Image = Node$1.create({
64371
64524
  style2 += "float: left;";
64372
64525
  }
64373
64526
  } else if (!anchorData.alignH && marginOffset?.horizontal != null) {
64374
- const isAbsolutelyPositioned = style2.includes("position: absolute;");
64375
64527
  if (isAbsolutelyPositioned) {
64376
64528
  style2 += `left: ${baseHorizontal}px;`;
64377
64529
  style2 += "max-width: none;";
@@ -64385,7 +64537,8 @@ const Image = Node$1.create({
64385
64537
  const relativeFromPageV = anchorData?.vRelativeFrom === "page";
64386
64538
  const relativeFromMarginV = anchorData?.vRelativeFrom === "margin";
64387
64539
  const maxMarginV = 500;
64388
- const baseTop = Math.max(0, marginOffset?.top ?? 0);
64540
+ const allowNegativeTopOffset = isBehindDocAnchor;
64541
+ const baseTop = allowNegativeTopOffset ? marginOffset?.top ?? 0 : Math.max(0, marginOffset?.top ?? 0);
64389
64542
  let rotationHorizontal = 0;
64390
64543
  let rotationTop = 0;
64391
64544
  const { rotation: rotation2 } = transformData ?? {};
@@ -64404,7 +64557,10 @@ const Image = Node$1.create({
64404
64557
  margin.left += horizontal;
64405
64558
  }
64406
64559
  }
64407
- if (top2 && !relativeFromMarginV) {
64560
+ const appliedTopViaStyle = isAbsolutelyPositioned && allowNegativeTopOffset && !relativeFromMarginV;
64561
+ if (appliedTopViaStyle) {
64562
+ style2 += `top: ${top2}px;`;
64563
+ } else if (top2 && !relativeFromMarginV) {
64408
64564
  if (relativeFromPageV && top2 >= maxMarginV) margin.top += maxMarginV;
64409
64565
  else margin.top += top2;
64410
64566
  }
@@ -64417,6 +64573,9 @@ const Image = Node$1.create({
64417
64573
  }
64418
64574
  if (margin.top) style2 += `margin-top: ${margin.top}px;`;
64419
64575
  if (margin.bottom) style2 += `margin-bottom: ${margin.bottom}px;`;
64576
+ if (isBehindDocAnchor) {
64577
+ style2 += "max-width: none;";
64578
+ }
64420
64579
  const finalAttributes = { ...htmlAttributes };
64421
64580
  if (style2) {
64422
64581
  const existingStyle = finalAttributes.style || "";
@@ -78870,7 +79029,7 @@ var ResizeObserverController = (function() {
78870
79029
  };
78871
79030
  return ResizeObserverController2;
78872
79031
  })();
78873
- var ResizeObserver = (function() {
79032
+ var ResizeObserver$1 = (function() {
78874
79033
  function ResizeObserver2(callback) {
78875
79034
  if (arguments.length === 0) {
78876
79035
  throw new TypeError("Failed to construct 'ResizeObserver': 1 argument required, but only 0 present.");
@@ -78909,7 +79068,7 @@ var ResizeObserver = (function() {
78909
79068
  class ResizeObserverDelegate {
78910
79069
  constructor() {
78911
79070
  this.handleResize = this.handleResize.bind(this);
78912
- this.observer = new (typeof window !== "undefined" && window.ResizeObserver || ResizeObserver)(this.handleResize);
79071
+ this.observer = new (typeof window !== "undefined" && window.ResizeObserver || ResizeObserver$1)(this.handleResize);
78913
79072
  this.elHandlersMap = /* @__PURE__ */ new Map();
78914
79073
  }
78915
79074
  handleResize(entries) {
@@ -89778,6 +89937,31 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
89778
89937
  },
89779
89938
  { immediate: true, deep: true }
89780
89939
  );
89940
+ vue.watch(
89941
+ () => props.options?.rulerContainer,
89942
+ () => {
89943
+ vue.nextTick(() => {
89944
+ syncRulerOffset();
89945
+ setupRulerObservers();
89946
+ });
89947
+ },
89948
+ { immediate: true }
89949
+ );
89950
+ vue.watch(
89951
+ rulersVisible,
89952
+ (visible) => {
89953
+ vue.nextTick(() => {
89954
+ if (visible) {
89955
+ syncRulerOffset();
89956
+ setupRulerObservers();
89957
+ } else {
89958
+ rulerHostStyle.value = {};
89959
+ cleanupRulerObservers();
89960
+ }
89961
+ });
89962
+ },
89963
+ { immediate: true }
89964
+ );
89781
89965
  const containerStyle = vue.computed(() => {
89782
89966
  let maxWidth = 8.5 * 96;
89783
89967
  const ed = editor.value;
@@ -89802,6 +89986,71 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
89802
89986
  minWidth: `${scaledWidth}px`
89803
89987
  };
89804
89988
  });
89989
+ const rulerHostStyle = vue.ref({});
89990
+ const rulerContainerEl = vue.ref(null);
89991
+ let editorResizeObserver = null;
89992
+ let rulerContainerResizeObserver = null;
89993
+ let layoutUpdatedHandler = null;
89994
+ const resolveRulerContainer = () => {
89995
+ const container = props.options?.rulerContainer;
89996
+ if (!container) return null;
89997
+ if (typeof container === "string") {
89998
+ const doc2 = editorWrapper.value?.ownerDocument ?? document;
89999
+ return doc2.querySelector(container);
90000
+ }
90001
+ return container instanceof HTMLElement ? container : null;
90002
+ };
90003
+ const getViewportRect2 = () => {
90004
+ const host = editorWrapper.value;
90005
+ if (!host) return null;
90006
+ const viewport2 = host.querySelector(".presentation-editor__viewport");
90007
+ const target = viewport2 ?? host;
90008
+ return target.getBoundingClientRect();
90009
+ };
90010
+ const syncRulerOffset = () => {
90011
+ if (!rulersVisible.value) {
90012
+ rulerHostStyle.value = {};
90013
+ return;
90014
+ }
90015
+ rulerContainerEl.value = resolveRulerContainer();
90016
+ if (!rulerContainerEl.value) {
90017
+ rulerHostStyle.value = {};
90018
+ return;
90019
+ }
90020
+ const viewportRect = getViewportRect2();
90021
+ if (!viewportRect) return;
90022
+ const hostRect = rulerContainerEl.value.getBoundingClientRect();
90023
+ const paddingLeft = Math.max(0, viewportRect.left - hostRect.left);
90024
+ const paddingRight = Math.max(0, hostRect.right - viewportRect.right);
90025
+ rulerHostStyle.value = {
90026
+ paddingLeft: `${paddingLeft}px`,
90027
+ paddingRight: `${paddingRight}px`
90028
+ };
90029
+ };
90030
+ const cleanupRulerObservers = () => {
90031
+ if (editorResizeObserver) {
90032
+ editorResizeObserver.disconnect();
90033
+ editorResizeObserver = null;
90034
+ }
90035
+ if (rulerContainerResizeObserver) {
90036
+ rulerContainerResizeObserver.disconnect();
90037
+ rulerContainerResizeObserver = null;
90038
+ }
90039
+ };
90040
+ const setupRulerObservers = () => {
90041
+ cleanupRulerObservers();
90042
+ if (typeof ResizeObserver === "undefined") return;
90043
+ const viewportHost = editorWrapper.value;
90044
+ const rulerHost = resolveRulerContainer();
90045
+ if (viewportHost) {
90046
+ editorResizeObserver = new ResizeObserver(() => syncRulerOffset());
90047
+ editorResizeObserver.observe(viewportHost);
90048
+ }
90049
+ if (rulerHost) {
90050
+ rulerContainerResizeObserver = new ResizeObserver(() => syncRulerOffset());
90051
+ rulerContainerResizeObserver.observe(rulerHost);
90052
+ }
90053
+ };
89805
90054
  const message = useMessage();
89806
90055
  const editorWrapper = vue.ref(null);
89807
90056
  const editorElem = vue.ref(null);
@@ -90113,7 +90362,7 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
90113
90362
  presentationEditor.on("imageDeselected", () => {
90114
90363
  clearSelectedImage();
90115
90364
  });
90116
- presentationEditor.on("layoutUpdated", () => {
90365
+ layoutUpdatedHandler = () => {
90117
90366
  if (imageResizeState.visible && imageResizeState.blockId) {
90118
90367
  const escapedBlockId = CSS.escape(imageResizeState.blockId);
90119
90368
  const newElement = editorElem.value?.querySelector(
@@ -90146,13 +90395,17 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
90146
90395
  clearSelectedImage();
90147
90396
  }
90148
90397
  }
90149
- });
90398
+ vue.nextTick(() => syncRulerOffset());
90399
+ };
90400
+ presentationEditor.on("layoutUpdated", layoutUpdatedHandler);
90150
90401
  zoomChangeHandler = ({ zoom }) => {
90151
90402
  currentZoom.value = zoom;
90403
+ vue.nextTick(() => syncRulerOffset());
90152
90404
  };
90153
90405
  presentationEditor.on("zoomChange", zoomChangeHandler);
90154
90406
  if (typeof presentationEditor.zoom === "number") {
90155
90407
  currentZoom.value = presentationEditor.zoom;
90408
+ vue.nextTick(() => syncRulerOffset());
90156
90409
  }
90157
90410
  }
90158
90411
  editor.value.on("paginationUpdate", () => {
@@ -90212,6 +90465,11 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
90212
90465
  vue.onMounted(() => {
90213
90466
  initializeData();
90214
90467
  if (props.options?.suppressSkeletonLoader || !props.options?.collaborationProvider) editorReady.value = true;
90468
+ window.addEventListener("resize", syncRulerOffset, { passive: true });
90469
+ vue.nextTick(() => {
90470
+ syncRulerOffset();
90471
+ setupRulerObservers();
90472
+ });
90215
90473
  });
90216
90474
  const handleMarginClick = (event) => {
90217
90475
  if (event.button !== 0) {
@@ -90226,10 +90484,14 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
90226
90484
  const handleMarginChange = ({ side, value }) => {
90227
90485
  const base2 = activeEditor.value;
90228
90486
  if (!base2) return;
90229
- const pageStyles2 = base2.getPageStyles();
90230
- const { pageMargins } = pageStyles2;
90231
- const update = { ...pageMargins, [side]: value };
90232
- base2?.updatePageStyle({ pageMargins: update });
90487
+ const payload = side === "left" ? { leftInches: value } : side === "right" ? { rightInches: value } : side === "top" ? { topInches: value } : side === "bottom" ? { bottomInches: value } : {};
90488
+ const didUpdateSection = typeof base2.commands?.setSectionPageMarginsAtSelection === "function" ? base2.commands.setSectionPageMarginsAtSelection(payload) : false;
90489
+ if (!didUpdateSection) {
90490
+ const pageStyles2 = base2.getPageStyles();
90491
+ const { pageMargins } = pageStyles2;
90492
+ const update = { ...pageMargins, [side]: value };
90493
+ base2?.updatePageStyle({ pageMargins: update });
90494
+ }
90233
90495
  };
90234
90496
  vue.onBeforeUnmount(() => {
90235
90497
  stopPolling();
@@ -90238,6 +90500,12 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
90238
90500
  editor.value.off("zoomChange", zoomChangeHandler);
90239
90501
  zoomChangeHandler = null;
90240
90502
  }
90503
+ if (editor.value instanceof PresentationEditor && layoutUpdatedHandler) {
90504
+ editor.value.off("layoutUpdated", layoutUpdatedHandler);
90505
+ layoutUpdatedHandler = null;
90506
+ }
90507
+ cleanupRulerObservers();
90508
+ window.removeEventListener("resize", syncRulerOffset);
90241
90509
  editor.value?.destroy();
90242
90510
  editor.value = null;
90243
90511
  });
@@ -90249,18 +90517,28 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
90249
90517
  __props.options.rulerContainer && rulersVisible.value && !!activeEditor.value ? (vue.openBlock(), vue.createBlock(vue.Teleport, {
90250
90518
  key: 0,
90251
90519
  to: __props.options.rulerContainer
90520
+ }, [
90521
+ vue.createBaseVNode("div", {
90522
+ class: "ruler-host",
90523
+ style: vue.normalizeStyle(rulerHostStyle.value)
90524
+ }, [
90525
+ vue.createVNode(Ruler, {
90526
+ class: "ruler superdoc-ruler",
90527
+ editor: activeEditor.value,
90528
+ onMarginChange: handleMarginChange
90529
+ }, null, 8, ["editor"])
90530
+ ], 4)
90531
+ ], 8, ["to"])) : rulersVisible.value && !!activeEditor.value ? (vue.openBlock(), vue.createElementBlock("div", {
90532
+ key: 1,
90533
+ class: "ruler-host",
90534
+ style: vue.normalizeStyle(rulerHostStyle.value)
90252
90535
  }, [
90253
90536
  vue.createVNode(Ruler, {
90254
- class: "ruler superdoc-ruler",
90537
+ class: "ruler",
90255
90538
  editor: activeEditor.value,
90256
90539
  onMarginChange: handleMarginChange
90257
90540
  }, null, 8, ["editor"])
90258
- ], 8, ["to"])) : rulersVisible.value && !!activeEditor.value ? (vue.openBlock(), vue.createBlock(Ruler, {
90259
- key: 1,
90260
- class: "ruler",
90261
- editor: activeEditor.value,
90262
- onMarginChange: handleMarginChange
90263
- }, null, 8, ["editor"])) : vue.createCommentVNode("", true),
90541
+ ], 4)) : vue.createCommentVNode("", true),
90264
90542
  vue.createBaseVNode("div", {
90265
90543
  class: "super-editor",
90266
90544
  ref_key: "editorWrapper",
@@ -90365,7 +90643,7 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
90365
90643
  };
90366
90644
  }
90367
90645
  });
90368
- const SuperEditor = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-8dd4cf59"]]);
90646
+ const SuperEditor = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-f5c4f915"]]);
90369
90647
  const _hoisted_1 = ["innerHTML"];
90370
90648
  const _sfc_main = {
90371
90649
  __name: "SuperInput",