@harbour-enterprises/superdoc 1.0.0-beta.87 → 1.0.0-beta.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/chunks/{PdfViewer-Cwmc4rak.cjs → PdfViewer-64l7m5Lq.cjs} +1 -1
  2. package/dist/chunks/{PdfViewer-DAayAt76.es.js → PdfViewer-Dj0ADYo6.es.js} +1 -1
  3. package/dist/chunks/{index-huIbWXSg.cjs → index-Cnq_7qcp.cjs} +3 -3
  4. package/dist/chunks/{index-BV2SxVfK.es.js → index-DXKu3E-3.es.js} +3 -3
  5. package/dist/chunks/{index-rv7o9043-DVlRSGhv.es.js → index-DcTrJ8db-9XJOggtC.es.js} +1 -1
  6. package/dist/chunks/{index-rv7o9043-DD5SvBoC.cjs → index-DcTrJ8db-kUMXGs8M.cjs} +1 -1
  7. package/dist/chunks/{super-editor.es-BuujpqOr.es.js → super-editor.es-D0fgEP38.es.js} +297 -68
  8. package/dist/chunks/{super-editor.es-C43B4f8Z.cjs → super-editor.es-D8F0msfn.cjs} +297 -68
  9. package/dist/super-editor/ai-writer.es.js +2 -2
  10. package/dist/super-editor/chunks/{converter-G519mwN2.js → converter-DPyEmTPY.js} +1 -1
  11. package/dist/super-editor/chunks/{docx-zipper-CHfjJ_h-.js → docx-zipper-BTkZSGvz.js} +1 -1
  12. package/dist/super-editor/chunks/{editor-BQsR9BR1.js → editor-4iR-p-_J.js} +293 -64
  13. package/dist/super-editor/chunks/{index-rv7o9043.js → index-DcTrJ8db.js} +1 -1
  14. package/dist/super-editor/chunks/{toolbar-DNfQq2Cl.js → toolbar-Dx7gHXE2.js} +2 -2
  15. package/dist/super-editor/converter.es.js +1 -1
  16. package/dist/super-editor/docx-zipper.es.js +2 -2
  17. package/dist/super-editor/editor.es.js +3 -3
  18. package/dist/super-editor/file-zipper.es.js +1 -1
  19. package/dist/super-editor/super-editor.es.js +6 -6
  20. package/dist/super-editor/toolbar.es.js +2 -2
  21. package/dist/super-editor.cjs +1 -1
  22. package/dist/super-editor.es.js +1 -1
  23. package/dist/superdoc.cjs +2 -2
  24. package/dist/superdoc.es.js +2 -2
  25. package/dist/superdoc.umd.js +299 -70
  26. package/dist/superdoc.umd.js.map +1 -1
  27. package/package.json +1 -1
@@ -19614,9 +19614,9 @@ function encodeCSSFromPPr(paragraphProperties, hasPreviousParagraph, nextParagra
19614
19614
  const { spacing, indent, borders, justification } = paragraphProperties;
19615
19615
  const nextStyleId = nextParagraphProps?.styleId;
19616
19616
  if (spacing) {
19617
- const getEffectiveBefore = (nextSpacing, isListItem) => {
19617
+ const getEffectiveBefore = (nextSpacing, isListItem2) => {
19618
19618
  if (!nextSpacing) return 0;
19619
- if (nextSpacing.beforeAutospacing && isListItem) {
19619
+ if (nextSpacing.beforeAutospacing && isListItem2) {
19620
19620
  return 0;
19621
19621
  }
19622
19622
  return nextSpacing.before || 0;
@@ -19997,7 +19997,7 @@ function addTextDecorationEntries(targetSet, value) {
19997
19997
  }
19998
19998
  String(value).split(/\s+/).map((entry) => entry.trim()).filter(Boolean).forEach((entry) => targetSet.add(entry));
19999
19999
  }
20000
- const getSpacingStyle = (spacing, isListItem) => {
20000
+ const getSpacingStyle = (spacing, isListItem2) => {
20001
20001
  let { before, after, line, lineRule, beforeAutospacing, afterAutospacing } = spacing;
20002
20002
  line = twipsToLines(line);
20003
20003
  if (line != null && line < 1) {
@@ -20008,13 +20008,13 @@ const getSpacingStyle = (spacing, isListItem) => {
20008
20008
  }
20009
20009
  before = twipsToPixels$2(before);
20010
20010
  if (beforeAutospacing) {
20011
- if (isListItem) {
20011
+ if (isListItem2) {
20012
20012
  before = 0;
20013
20013
  }
20014
20014
  }
20015
20015
  after = twipsToPixels$2(after);
20016
20016
  if (afterAutospacing) {
20017
- if (isListItem) {
20017
+ if (isListItem2) {
20018
20018
  after = 0;
20019
20019
  }
20020
20020
  }
@@ -42380,7 +42380,7 @@ const _SuperConverter = class _SuperConverter2 {
42380
42380
  static getStoredSuperdocVersion(docx) {
42381
42381
  return _SuperConverter2.getStoredCustomProperty(docx, "SuperdocVersion");
42382
42382
  }
42383
- static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.87") {
42383
+ static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.89") {
42384
42384
  return _SuperConverter2.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
42385
42385
  }
42386
42386
  /**
@@ -59586,7 +59586,7 @@ const isHeadless = (editor) => {
59586
59586
  const shouldSkipNodeView = (editor) => {
59587
59587
  return isHeadless(editor);
59588
59588
  };
59589
- const summaryVersion = "1.0.0-beta.87";
59589
+ const summaryVersion = "1.0.0-beta.89";
59590
59590
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
59591
59591
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
59592
59592
  function mapAttributes(attrs) {
@@ -60375,7 +60375,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
60375
60375
  { default: remarkStringify },
60376
60376
  { default: remarkGfm }
60377
60377
  ] = await Promise.all([
60378
- import("./index-rv7o9043-DVlRSGhv.es.js"),
60378
+ import("./index-DcTrJ8db-9XJOggtC.es.js"),
60379
60379
  import("./index-DRCvimau-Cw339678.es.js"),
60380
60380
  import("./index-C_x_N6Uh-DJn8hIEt.es.js"),
60381
60381
  import("./index-D_sWOSiG-DE96TaT5.es.js"),
@@ -60580,7 +60580,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
60580
60580
  * Process collaboration migrations
60581
60581
  */
60582
60582
  processCollaborationMigrations() {
60583
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.87");
60583
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.89");
60584
60584
  if (!this.options.ydoc) return;
60585
60585
  const metaMap = this.options.ydoc.getMap("meta");
60586
60586
  let docVersion = metaMap.get("version");
@@ -73492,7 +73492,14 @@ const renderTableCell = (deps) => {
73492
73492
  let renderedHeight = 0;
73493
73493
  for (let lineIdx = localStartLine; lineIdx < localEndLine && lineIdx < lines.length; lineIdx++) {
73494
73494
  const line = lines[lineIdx];
73495
- const lineEl = renderLine(block, line, { ...context, section: "body" });
73495
+ const isLastLine = lineIdx === lines.length - 1;
73496
+ const lineEl = renderLine(
73497
+ block,
73498
+ line,
73499
+ { ...context, section: "body" },
73500
+ lineIdx,
73501
+ isLastLine
73502
+ );
73496
73503
  lineEl.style.paddingLeft = "";
73497
73504
  lineEl.style.paddingRight = "";
73498
73505
  lineEl.style.textIndent = "";
@@ -76124,8 +76131,11 @@ const _DomPainter = class _DomPainter2 {
76124
76131
  const applyFragmentFrameWithSection = (el, frag) => {
76125
76132
  this.applyFragmentFrame(el, frag, context.section);
76126
76133
  };
76127
- const renderLineForTableCell = (block, line, ctx2) => {
76128
- return this.renderLine(block, line, ctx2, void 0, void 0, true);
76134
+ const renderLineForTableCell = (block, line, ctx2, lineIndex, isLastLine) => {
76135
+ const lastRun = block.runs.length > 0 ? block.runs[block.runs.length - 1] : null;
76136
+ const paragraphEndsWithLineBreak = lastRun?.kind === "lineBreak";
76137
+ const shouldSkipJustify = isLastLine && !paragraphEndsWithLineBreak;
76138
+ return this.renderLine(block, line, ctx2, void 0, lineIndex, shouldSkipJustify);
76129
76139
  };
76130
76140
  const renderDrawingContentForTableCell = (block) => {
76131
76141
  if (block.drawingKind === "image") {
@@ -76734,9 +76744,10 @@ const _DomPainter = class _DomPainter2 {
76734
76744
  el.setAttribute("styleid", styleId);
76735
76745
  }
76736
76746
  const alignment2 = block.attrs?.alignment;
76737
- if (alignment2 === "center" || alignment2 === "right") {
76738
- el.style.textAlign = alignment2;
76739
- } else if (alignment2 === "justify") {
76747
+ const effectiveAlignment = alignment2;
76748
+ if (effectiveAlignment === "center" || effectiveAlignment === "right") {
76749
+ el.style.textAlign = effectiveAlignment;
76750
+ } else if (effectiveAlignment === "justify") {
76740
76751
  el.style.textAlign = "left";
76741
76752
  } else {
76742
76753
  el.style.textAlign = "left";
@@ -76798,16 +76809,16 @@ const _DomPainter = class _DomPainter2 {
76798
76809
  }
76799
76810
  const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
76800
76811
  const availableWidth = availableWidthOverride ?? line.maxWidth ?? line.width;
76801
- const shouldJustify = !skipJustify && alignment2 === "justify" && !hasExplicitPositioning;
76812
+ const shouldJustify = !skipJustify && effectiveAlignment === "justify" && !hasExplicitPositioning;
76802
76813
  if (shouldJustify) {
76803
76814
  const spaceCount = textSlices.reduce(
76804
76815
  (sum, s2) => sum + Array.from(s2).filter((ch) => ch === " " || ch === " ").length,
76805
76816
  0
76806
76817
  );
76807
- const slack = Math.max(0, availableWidth - line.width);
76808
- if (spaceCount > 0 && slack > 0) {
76809
- const extraPerSpace = slack / spaceCount;
76810
- el.style.wordSpacing = `${extraPerSpace}px`;
76818
+ const slack = availableWidth - line.width;
76819
+ if (spaceCount > 0 && slack !== 0) {
76820
+ const spacingPerSpace = slack / spaceCount;
76821
+ el.style.wordSpacing = `${spacingPerSpace}px`;
76811
76822
  }
76812
76823
  }
76813
76824
  if (hasExplicitPositioning && line.segments) {
@@ -78268,6 +78279,50 @@ function findCharIndexAtX(textNode, container, targetX) {
78268
78279
  }
78269
78280
  return index2;
78270
78281
  }
78282
+ function getWordLayoutConfig(block) {
78283
+ if (!block || block.kind !== "paragraph") {
78284
+ return void 0;
78285
+ }
78286
+ return block.attrs?.wordLayout;
78287
+ }
78288
+ function isListItem(markerWidth, block) {
78289
+ const hasMarkerWidth = markerWidth > 0;
78290
+ if (hasMarkerWidth) {
78291
+ return true;
78292
+ }
78293
+ if (!block || block.kind !== "paragraph") {
78294
+ return false;
78295
+ }
78296
+ const wordLayout = getWordLayoutConfig(block);
78297
+ const hasListAttrs = block.attrs?.listItem != null || wordLayout?.marker != null;
78298
+ if (hasListAttrs) {
78299
+ return true;
78300
+ }
78301
+ const hangingIndent = block.attrs?.indent?.hanging ?? 0;
78302
+ const paraIndentLeft = block.attrs?.indent?.left ?? 0;
78303
+ const hasHangingIndentPattern = hangingIndent > 0 && paraIndentLeft > 0;
78304
+ return hasHangingIndentPattern;
78305
+ }
78306
+ function calculateTextStartIndent(params2) {
78307
+ const { isFirstLine, isListItem: isListItem2, markerWidth, paraIndentLeft, firstLineIndent, hangingIndent, wordLayout } = params2;
78308
+ const firstLineOffset = firstLineIndent - hangingIndent;
78309
+ const isFirstLineIndentMode = wordLayout?.firstLineIndentMode === true;
78310
+ let indentAdjust = paraIndentLeft;
78311
+ if (isListItem2 && isFirstLine && isFirstLineIndentMode) {
78312
+ const textStartFallback = paraIndentLeft + Math.max(firstLineIndent, 0) + markerWidth;
78313
+ indentAdjust = typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : textStartFallback;
78314
+ } else if (isFirstLine && !isListItem2) {
78315
+ indentAdjust += firstLineOffset;
78316
+ }
78317
+ return indentAdjust;
78318
+ }
78319
+ function extractParagraphIndent(indent) {
78320
+ const left2 = typeof indent?.left === "number" && Number.isFinite(indent.left) ? indent.left : 0;
78321
+ const right2 = typeof indent?.right === "number" && Number.isFinite(indent.right) ? indent.right : 0;
78322
+ const firstLine = typeof indent?.firstLine === "number" && Number.isFinite(indent.firstLine) ? indent.firstLine : 0;
78323
+ const hanging = typeof indent?.hanging === "number" && Number.isFinite(indent.hanging) ? indent.hanging : 0;
78324
+ return { left: left2, right: right2, firstLine, hanging };
78325
+ }
78271
78326
  const defaultHeaderFooterIdentifier = () => ({
78272
78327
  headerIds: { default: null, first: null, even: null, odd: null },
78273
78328
  footerIds: { default: null, first: null, even: null, odd: null },
@@ -83279,8 +83334,8 @@ function clickToPosition(layout, blocks, measures, containerPoint, domContainer,
83279
83334
  );
83280
83335
  }
83281
83336
  const markerWidth = fragment.markerWidth ?? measure.marker?.markerWidth ?? 0;
83282
- const isListItem = markerWidth > 0;
83283
- const alignmentOverride = isListItem ? "left" : void 0;
83337
+ const isListItem3 = markerWidth > 0;
83338
+ const alignmentOverride = isListItem3 ? "left" : void 0;
83284
83339
  const pos = mapPointToPm(block, line, pageRelativePoint.x - fragment.x, isRTL, availableWidth, alignmentOverride);
83285
83340
  if (pos == null) {
83286
83341
  logClickStage("warn", "no-position", {
@@ -83324,8 +83379,8 @@ function clickToPosition(layout, blocks, measures, containerPoint, domContainer,
83324
83379
  );
83325
83380
  }
83326
83381
  const cellMarkerWidth = cellMeasure.marker?.markerWidth ?? 0;
83327
- const isListItem = cellMarkerWidth > 0;
83328
- const alignmentOverride = isListItem ? "left" : void 0;
83382
+ const isListItem3 = cellMarkerWidth > 0;
83383
+ const alignmentOverride = isListItem3 ? "left" : void 0;
83329
83384
  const pos = mapPointToPm(cellBlock, line, localX, isRTL, availableWidth, alignmentOverride);
83330
83385
  if (pos != null) {
83331
83386
  logClickStage("log", "success", {
@@ -83483,17 +83538,22 @@ function selectionToRects(layout, blocks, measures, from2, to) {
83483
83538
  const charOffsetFrom = pmPosToCharOffset(block, line, sliceFrom);
83484
83539
  const charOffsetTo = pmPosToCharOffset(block, line, sliceTo);
83485
83540
  const markerWidth = fragment.markerWidth ?? measure.marker?.markerWidth ?? 0;
83486
- const isListItem = markerWidth > 0;
83487
- const alignmentOverride = isListItem ? "left" : void 0;
83541
+ const isListItemFlag = isListItem(markerWidth, block);
83542
+ const alignmentOverride = isListItemFlag ? "left" : void 0;
83488
83543
  const startX = mapPmToX(block, line, charOffsetFrom, fragment.width, alignmentOverride);
83489
83544
  const endX = mapPmToX(block, line, charOffsetTo, fragment.width, alignmentOverride);
83490
- const paraIndentLeft = block.attrs?.indent?.left ?? 0;
83491
- const firstLineOffset = (block.attrs?.indent?.firstLine ?? 0) - (block.attrs?.indent?.hanging ?? 0);
83545
+ const indent = extractParagraphIndent(block.attrs?.indent);
83546
+ const wordLayout = getWordLayoutConfig(block);
83492
83547
  const isFirstLine = index2 === fragment.fromLine;
83493
- let indentAdjust = paraIndentLeft;
83494
- if (isFirstLine && !isListItem) {
83495
- indentAdjust += firstLineOffset;
83496
- }
83548
+ const indentAdjust = calculateTextStartIndent({
83549
+ isFirstLine,
83550
+ isListItem: isListItemFlag,
83551
+ markerWidth,
83552
+ paraIndentLeft: indent.left,
83553
+ firstLineIndent: indent.firstLine,
83554
+ hangingIndent: indent.hanging,
83555
+ wordLayout
83556
+ });
83497
83557
  const rectX = fragment.x + indentAdjust + Math.min(startX, endX);
83498
83558
  const rectWidth = Math.max(1, Math.abs(endX - startX));
83499
83559
  const lineOffset = lineHeightBeforeIndex(measure, index2) - lineHeightBeforeIndex(measure, fragment.fromLine);
@@ -83596,9 +83656,12 @@ function selectionToRects(layout, blocks, measures, from2, to) {
83596
83656
  let blockTopCursor = padding.top + verticalOffset;
83597
83657
  renderedBlocks.forEach((info) => {
83598
83658
  const paragraphMarkerWidth = info.measure.marker?.markerWidth ?? 0;
83599
- const isListItem = paragraphMarkerWidth > 0;
83600
- const alignmentOverride = isListItem ? "left" : void 0;
83601
- const paraIndentLeft = info.block.kind === "paragraph" ? info.block.attrs?.indent?.left ?? 0 : 0;
83659
+ const cellIsListItem = isListItem(paragraphMarkerWidth, info.block);
83660
+ const alignmentOverride = cellIsListItem ? "left" : void 0;
83661
+ const cellIndent = extractParagraphIndent(
83662
+ info.block.kind === "paragraph" ? info.block.attrs?.indent : void 0
83663
+ );
83664
+ const cellWordLayout = getWordLayoutConfig(info.block);
83602
83665
  const intersectingLines = findLinesIntersectingRange(info.block, info.measure, from2, to);
83603
83666
  intersectingLines.forEach(({ line, index: index2 }) => {
83604
83667
  if (index2 < info.startLine || index2 >= info.endLine) {
@@ -83614,7 +83677,17 @@ function selectionToRects(layout, blocks, measures, from2, to) {
83614
83677
  const availableWidth = Math.max(1, cellMeasure.width - padding.left - padding.right);
83615
83678
  const startX = mapPmToX(info.block, line, charOffsetFrom, availableWidth, alignmentOverride);
83616
83679
  const endX = mapPmToX(info.block, line, charOffsetTo, availableWidth, alignmentOverride);
83617
- const rectX = fragment.x + cellX + padding.left + paraIndentLeft + Math.min(startX, endX);
83680
+ const isFirstLine = index2 === info.startLine;
83681
+ const textIndentAdjust = calculateTextStartIndent({
83682
+ isFirstLine,
83683
+ isListItem: cellIsListItem,
83684
+ markerWidth: paragraphMarkerWidth,
83685
+ paraIndentLeft: cellIndent.left,
83686
+ firstLineIndent: cellIndent.firstLine,
83687
+ hangingIndent: cellIndent.hanging,
83688
+ wordLayout: cellWordLayout
83689
+ });
83690
+ const rectX = fragment.x + cellX + padding.left + textIndentAdjust + Math.min(startX, endX);
83618
83691
  const rectWidth = Math.max(1, Math.abs(endX - startX));
83619
83692
  const lineOffset = lineHeightBeforeIndex(info.measure, index2) - lineHeightBeforeIndex(info.measure, info.startLine);
83620
83693
  const rectY = fragment.y + rowOffset + blockTopCursor + lineOffset;
@@ -83986,9 +84059,7 @@ function getMeasuredTextWidth(text, font, letterSpacing, ctx2) {
83986
84059
  try {
83987
84060
  ctx2.font = font;
83988
84061
  const metrics = ctx2.measureText(text);
83989
- const advanceWidth = metrics.width;
83990
- const paintedWidth = (metrics.actualBoundingBoxLeft || 0) + (metrics.actualBoundingBoxRight || 0);
83991
- const baseWidth = Math.max(advanceWidth, paintedWidth);
84062
+ const baseWidth = metrics.width;
83992
84063
  const extra = letterSpacing ? Math.max(0, text.length - 1) * letterSpacing : 0;
83993
84064
  const width = baseWidth + extra;
83994
84065
  cache$1.set(key2, { width });
@@ -84197,7 +84268,8 @@ async function measureParagraphBlock(block, maxWidth) {
84197
84268
  const isWordLayoutList = Boolean(wordLayout?.marker);
84198
84269
  const suppressFirstLine = block.attrs?.suppressFirstLineIndent === true;
84199
84270
  const rawFirstLineOffset = suppressFirstLine ? 0 : firstLine - hanging;
84200
- const firstLineOffset = isWordLayoutList ? 0 : rawFirstLineOffset;
84271
+ const clampedFirstLineOffset = Math.max(0, rawFirstLineOffset);
84272
+ const firstLineOffset = isWordLayoutList ? 0 : clampedFirstLineOffset;
84201
84273
  const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
84202
84274
  let leftJustifiedMarkerSpace = 0;
84203
84275
  if (wordLayout?.marker) {
@@ -84350,7 +84422,8 @@ async function measureParagraphBlock(block, maxWidth) {
84350
84422
  if (run2.kind === "break") {
84351
84423
  if (currentLine) {
84352
84424
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84353
- const completedLine = { ...currentLine, ...metrics };
84425
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84426
+ const completedLine = { ...lineBase, ...metrics };
84354
84427
  addBarTabsToLine(completedLine);
84355
84428
  lines.push(completedLine);
84356
84429
  currentLine = null;
@@ -84411,7 +84484,8 @@ async function measureParagraphBlock(block, maxWidth) {
84411
84484
  width: 0,
84412
84485
  maxFontSize: lastFontSize,
84413
84486
  maxWidth: nextLineMaxWidth,
84414
- segments: []
84487
+ segments: [],
84488
+ spaceCount: 0
84415
84489
  };
84416
84490
  tabStopCursor = 0;
84417
84491
  pendingTabAlignment = null;
@@ -84429,7 +84503,8 @@ async function measureParagraphBlock(block, maxWidth) {
84429
84503
  maxFontSize: 12,
84430
84504
  // Default font size for tabs
84431
84505
  maxWidth: getEffectiveWidth(initialAvailableWidth),
84432
- segments: []
84506
+ segments: [],
84507
+ spaceCount: 0
84433
84508
  };
84434
84509
  }
84435
84510
  const originX = currentLine.width;
@@ -84478,6 +84553,7 @@ async function measureParagraphBlock(block, maxWidth) {
84478
84553
  maxFontSize: imageHeight,
84479
84554
  // Use image height for line height calculation
84480
84555
  maxWidth: getEffectiveWidth(initialAvailableWidth),
84556
+ spaceCount: 0,
84481
84557
  segments: [
84482
84558
  {
84483
84559
  runIndex,
@@ -84493,8 +84569,9 @@ async function measureParagraphBlock(block, maxWidth) {
84493
84569
  const appliedTabAlign = lastAppliedTabAlign;
84494
84570
  if (currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
84495
84571
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84572
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84496
84573
  const completedLine = {
84497
- ...currentLine,
84574
+ ...lineBase,
84498
84575
  ...metrics
84499
84576
  };
84500
84577
  addBarTabsToLine(completedLine);
@@ -84510,6 +84587,7 @@ async function measureParagraphBlock(block, maxWidth) {
84510
84587
  width: imageWidth,
84511
84588
  maxFontSize: imageHeight,
84512
84589
  maxWidth: getEffectiveWidth(contentWidth),
84590
+ spaceCount: 0,
84513
84591
  segments: [
84514
84592
  {
84515
84593
  runIndex,
@@ -84565,6 +84643,7 @@ async function measureParagraphBlock(block, maxWidth) {
84565
84643
  width: annotationWidth,
84566
84644
  maxFontSize: annotationHeight,
84567
84645
  maxWidth: getEffectiveWidth(initialAvailableWidth),
84646
+ spaceCount: 0,
84568
84647
  segments: [
84569
84648
  {
84570
84649
  runIndex,
@@ -84579,8 +84658,9 @@ async function measureParagraphBlock(block, maxWidth) {
84579
84658
  }
84580
84659
  if (currentLine.width + annotationWidth > currentLine.maxWidth && currentLine.width > 0) {
84581
84660
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84661
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84582
84662
  const completedLine = {
84583
- ...currentLine,
84663
+ ...lineBase,
84584
84664
  ...metrics
84585
84665
  };
84586
84666
  addBarTabsToLine(completedLine);
@@ -84596,6 +84676,7 @@ async function measureParagraphBlock(block, maxWidth) {
84596
84676
  width: annotationWidth,
84597
84677
  maxFontSize: annotationHeight,
84598
84678
  maxWidth: getEffectiveWidth(contentWidth),
84679
+ spaceCount: 0,
84599
84680
  segments: [
84600
84681
  {
84601
84682
  runIndex,
@@ -84651,14 +84732,16 @@ async function measureParagraphBlock(block, maxWidth) {
84651
84732
  maxFontSize: run2.fontSize,
84652
84733
  maxFontInfo: getFontInfoFromRun(run2),
84653
84734
  maxWidth: getEffectiveWidth(initialAvailableWidth),
84654
- segments: [{ runIndex, fromChar: spacesStartChar, toChar: spacesEndChar, width: spacesWidth }]
84735
+ segments: [{ runIndex, fromChar: spacesStartChar, toChar: spacesEndChar, width: spacesWidth }],
84736
+ spaceCount: spacesLength
84655
84737
  };
84656
84738
  } else {
84657
84739
  const boundarySpacing = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
84658
84740
  if (currentLine.width + boundarySpacing + spacesWidth > currentLine.maxWidth - WIDTH_FUDGE_PX && currentLine.width > 0) {
84659
84741
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84742
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84660
84743
  const completedLine = {
84661
- ...currentLine,
84744
+ ...lineBase,
84662
84745
  ...metrics
84663
84746
  };
84664
84747
  addBarTabsToLine(completedLine);
@@ -84675,7 +84758,8 @@ async function measureParagraphBlock(block, maxWidth) {
84675
84758
  maxFontSize: run2.fontSize,
84676
84759
  maxFontInfo: getFontInfoFromRun(run2),
84677
84760
  maxWidth: getEffectiveWidth(contentWidth),
84678
- segments: [{ runIndex, fromChar: spacesStartChar, toChar: spacesEndChar, width: spacesWidth }]
84761
+ segments: [{ runIndex, fromChar: spacesStartChar, toChar: spacesEndChar, width: spacesWidth }],
84762
+ spaceCount: spacesLength
84679
84763
  };
84680
84764
  } else {
84681
84765
  currentLine.toRun = runIndex;
@@ -84684,6 +84768,7 @@ async function measureParagraphBlock(block, maxWidth) {
84684
84768
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run2);
84685
84769
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run2.fontSize);
84686
84770
  appendSegment(currentLine.segments, runIndex, spacesStartChar, spacesEndChar, spacesWidth);
84771
+ currentLine.spaceCount += spacesLength;
84687
84772
  }
84688
84773
  }
84689
84774
  charPosInRun = spacesEndChar;
@@ -84700,7 +84785,56 @@ async function measureParagraphBlock(block, maxWidth) {
84700
84785
  for (let wordIndex = 0; wordIndex < words.length; wordIndex++) {
84701
84786
  const word = words[wordIndex];
84702
84787
  if (word === "") {
84703
- charPosInRun += 1;
84788
+ const spaceStartChar = charPosInRun;
84789
+ const spaceEndChar = charPosInRun + 1;
84790
+ const singleSpaceWidth = measureRunWidth(" ", font, ctx2, run2);
84791
+ if (!currentLine) {
84792
+ currentLine = {
84793
+ fromRun: runIndex,
84794
+ fromChar: spaceStartChar,
84795
+ toRun: runIndex,
84796
+ toChar: spaceEndChar,
84797
+ width: singleSpaceWidth,
84798
+ maxFontSize: run2.fontSize,
84799
+ maxFontInfo: getFontInfoFromRun(run2),
84800
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
84801
+ segments: [{ runIndex, fromChar: spaceStartChar, toChar: spaceEndChar, width: singleSpaceWidth }],
84802
+ spaceCount: 1
84803
+ };
84804
+ } else {
84805
+ const boundarySpacing2 = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
84806
+ if (currentLine.width + boundarySpacing2 + singleSpaceWidth > currentLine.maxWidth - WIDTH_FUDGE_PX && currentLine.width > 0) {
84807
+ const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84808
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84809
+ const completedLine = { ...lineBase, ...metrics };
84810
+ addBarTabsToLine(completedLine);
84811
+ lines.push(completedLine);
84812
+ tabStopCursor = 0;
84813
+ pendingTabAlignment = null;
84814
+ lastAppliedTabAlign = null;
84815
+ currentLine = {
84816
+ fromRun: runIndex,
84817
+ fromChar: spaceStartChar,
84818
+ toRun: runIndex,
84819
+ toChar: spaceEndChar,
84820
+ width: singleSpaceWidth,
84821
+ maxFontSize: run2.fontSize,
84822
+ maxFontInfo: getFontInfoFromRun(run2),
84823
+ maxWidth: getEffectiveWidth(contentWidth),
84824
+ segments: [{ runIndex, fromChar: spaceStartChar, toChar: spaceEndChar, width: singleSpaceWidth }],
84825
+ spaceCount: 1
84826
+ };
84827
+ } else {
84828
+ currentLine.toRun = runIndex;
84829
+ currentLine.toChar = spaceEndChar;
84830
+ currentLine.width = roundValue(currentLine.width + boundarySpacing2 + singleSpaceWidth);
84831
+ currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run2);
84832
+ currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run2.fontSize);
84833
+ appendSegment(currentLine.segments, runIndex, spaceStartChar, spaceEndChar, singleSpaceWidth);
84834
+ currentLine.spaceCount += 1;
84835
+ }
84836
+ }
84837
+ charPosInRun = spaceEndChar;
84704
84838
  continue;
84705
84839
  }
84706
84840
  const isLastWordInSegment = wordIndex === words.length - 1;
@@ -84721,13 +84855,15 @@ async function measureParagraphBlock(block, maxWidth) {
84721
84855
  maxFontSize: run2.fontSize,
84722
84856
  maxFontInfo: getFontInfoFromRun(run2),
84723
84857
  maxWidth: getEffectiveWidth(initialAvailableWidth),
84724
- segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
84858
+ segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }],
84859
+ spaceCount: 0
84725
84860
  };
84726
84861
  const ls = run2.letterSpacing ?? 0;
84727
84862
  if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX) {
84728
84863
  currentLine.toChar = wordEndWithSpace;
84729
84864
  currentLine.width = roundValue(currentLine.width + spaceWidth + ls);
84730
84865
  charPosInRun = wordEndWithSpace;
84866
+ currentLine.spaceCount += 1;
84731
84867
  } else {
84732
84868
  charPosInRun = wordEndWithSpace;
84733
84869
  }
@@ -84735,10 +84871,36 @@ async function measureParagraphBlock(block, maxWidth) {
84735
84871
  }
84736
84872
  const isTocEntry = block.attrs?.isTocEntry;
84737
84873
  const boundarySpacing = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
84738
- if (currentLine.width + boundarySpacing + wordOnlyWidth > currentLine.maxWidth - WIDTH_FUDGE_PX && currentLine.width > 0 && !isTocEntry) {
84874
+ const justifyAlignment = block.attrs?.alignment === "justify";
84875
+ const totalWidthWithWord = currentLine.width + boundarySpacing + wordCommitWidth + // Safe cast: only TextRuns produce word segments from split(), other run types are handled earlier
84876
+ (isLastWord ? 0 : run2.letterSpacing ?? 0);
84877
+ const availableWidth = currentLine.maxWidth - WIDTH_FUDGE_PX;
84878
+ let shouldBreak = currentLine.width + boundarySpacing + wordOnlyWidth > availableWidth && currentLine.width > 0 && !isTocEntry;
84879
+ let compressedWidth = null;
84880
+ if (shouldBreak && justifyAlignment) {
84881
+ const isParagraphLastWord = isLastWord && runIndex === runsToProcess.length - 1;
84882
+ if (!isParagraphLastWord) {
84883
+ const existingSpaces = currentLine.spaceCount ?? 0;
84884
+ const candidateSpaces = existingSpaces + (isLastWord ? 0 : 1);
84885
+ if (candidateSpaces > 0) {
84886
+ const overflow = totalWidthWithWord - availableWidth;
84887
+ if (overflow > 0) {
84888
+ const baseSpaceWidth = spaceWidth || measureRunWidth(" ", font, ctx2, run2) || Math.max(1, boundarySpacing);
84889
+ const perSpaceCompression = overflow / candidateSpaces;
84890
+ const maxPerSpaceCompression = baseSpaceWidth * 0.25;
84891
+ if (perSpaceCompression <= maxPerSpaceCompression) {
84892
+ shouldBreak = false;
84893
+ compressedWidth = availableWidth;
84894
+ }
84895
+ }
84896
+ }
84897
+ }
84898
+ }
84899
+ if (shouldBreak) {
84739
84900
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84901
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84740
84902
  const completedLine = {
84741
- ...currentLine,
84903
+ ...lineBase,
84742
84904
  ...metrics
84743
84905
  };
84744
84906
  addBarTabsToLine(completedLine);
@@ -84754,12 +84916,14 @@ async function measureParagraphBlock(block, maxWidth) {
84754
84916
  maxFontSize: run2.fontSize,
84755
84917
  maxFontInfo: getFontInfoFromRun(run2),
84756
84918
  maxWidth: getEffectiveWidth(contentWidth),
84757
- segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
84919
+ segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }],
84920
+ spaceCount: 0
84758
84921
  };
84759
84922
  if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX) {
84760
84923
  currentLine.toChar = wordEndWithSpace;
84761
84924
  currentLine.width = roundValue(currentLine.width + spaceWidth + (run2.letterSpacing ?? 0));
84762
84925
  charPosInRun = wordEndWithSpace;
84926
+ currentLine.spaceCount += 1;
84763
84927
  } else {
84764
84928
  charPosInRun = wordEndWithSpace;
84765
84929
  }
@@ -84780,7 +84944,8 @@ async function measureParagraphBlock(block, maxWidth) {
84780
84944
  useExplicitXHere ? segmentStartX : void 0
84781
84945
  );
84782
84946
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84783
- const completedLine = { ...currentLine, ...metrics };
84947
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84948
+ const completedLine = { ...lineBase, ...metrics };
84784
84949
  addBarTabsToLine(completedLine);
84785
84950
  lines.push(completedLine);
84786
84951
  tabStopCursor = 0;
@@ -84793,12 +84958,14 @@ async function measureParagraphBlock(block, maxWidth) {
84793
84958
  currentLine.toChar = newToChar;
84794
84959
  const useExplicitX = wordIndex === 0 && segmentStartX !== void 0;
84795
84960
  const explicitX = useExplicitX ? segmentStartX : void 0;
84796
- currentLine.width = roundValue(
84797
- currentLine.width + boundarySpacing + wordCommitWidth + (isLastWord ? 0 : run2.letterSpacing ?? 0)
84798
- );
84961
+ const targetWidth = compressedWidth != null ? compressedWidth : currentLine.width + boundarySpacing + wordCommitWidth + (isLastWord ? 0 : run2.letterSpacing ?? 0);
84962
+ currentLine.width = roundValue(targetWidth);
84799
84963
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run2);
84800
84964
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run2.fontSize);
84801
84965
  appendSegment(currentLine.segments, runIndex, wordStartChar, newToChar, wordCommitWidth, explicitX);
84966
+ if (!isLastWord) {
84967
+ currentLine.spaceCount += 1;
84968
+ }
84802
84969
  }
84803
84970
  charPosInRun = isLastWord ? wordEndNoSpace : wordEndWithSpace;
84804
84971
  }
@@ -84821,7 +84988,8 @@ async function measureParagraphBlock(block, maxWidth) {
84821
84988
  maxFontSize: run2.fontSize,
84822
84989
  maxFontInfo: getFontInfoFromRun(run2),
84823
84990
  maxWidth: getEffectiveWidth(initialAvailableWidth),
84824
- segments: []
84991
+ segments: [],
84992
+ spaceCount: 0
84825
84993
  };
84826
84994
  }
84827
84995
  const originX = currentLine.width;
@@ -84867,8 +85035,9 @@ async function measureParagraphBlock(block, maxWidth) {
84867
85035
  }
84868
85036
  if (currentLine) {
84869
85037
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
85038
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84870
85039
  const finalLine = {
84871
- ...currentLine,
85040
+ ...lineBase,
84872
85041
  ...metrics
84873
85042
  };
84874
85043
  addBarTabsToLine(finalLine);
@@ -91158,18 +91327,78 @@ computeCaretLayoutRectGeometry_fn = function(pos, includeDomFallback = true) {
91158
91327
  if (range2.pmStart == null || range2.pmEnd == null) return null;
91159
91328
  const pmOffset = pmPosToCharOffset(block, line, pos);
91160
91329
  const markerWidth = fragment.markerWidth ?? measure.marker?.markerWidth ?? 0;
91161
- const paraIndentLeft = block.attrs?.indent?.left ?? 0;
91162
- const paraIndentRight = block.attrs?.indent?.right ?? 0;
91163
- const availableWidth = Math.max(0, fragment.width - (paraIndentLeft + paraIndentRight));
91330
+ const indent = extractParagraphIndent(block.attrs?.indent);
91331
+ const availableWidth = Math.max(0, fragment.width - (indent.left + indent.right));
91164
91332
  const charX = measureCharacterX(block, line, pmOffset, availableWidth);
91165
- const firstLineOffset = (block.attrs?.indent?.firstLine ?? 0) - (block.attrs?.indent?.hanging ?? 0);
91166
91333
  const isFirstLine = index2 === fragment.fromLine;
91167
- const isListFirstLine = isFirstLine && !fragment.continuesFromPrev && (fragment.markerWidth ?? 0) > 0;
91168
- let indentAdjust = 0;
91169
- if (!isListFirstLine) {
91170
- indentAdjust = paraIndentLeft + (isFirstLine ? firstLineOffset : 0);
91334
+ const isListItemFlag = isListItem(markerWidth, block);
91335
+ const isListFirstLine = isFirstLine && !fragment.continuesFromPrev && isListItemFlag;
91336
+ const wordLayout = getWordLayoutConfig(block);
91337
+ const isFirstLineIndentMode = wordLayout?.firstLineIndentMode === true;
91338
+ if (isListFirstLine && isFirstLineIndentMode) {
91339
+ const textStartPx = calculateTextStartIndent({
91340
+ isFirstLine,
91341
+ isListItem: isListItemFlag,
91342
+ markerWidth,
91343
+ paraIndentLeft: indent.left,
91344
+ firstLineIndent: indent.firstLine,
91345
+ hangingIndent: indent.hanging,
91346
+ wordLayout
91347
+ });
91348
+ const localX2 = fragment.x + textStartPx + charX;
91349
+ const lineOffset2 = __privateMethod$1(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, fragment.fromLine, index2);
91350
+ const localY2 = fragment.y + lineOffset2;
91351
+ const result2 = {
91352
+ pageIndex: hit.pageIndex,
91353
+ x: localX2,
91354
+ y: localY2,
91355
+ height: line.lineHeight
91356
+ };
91357
+ const pageEl2 = __privateGet$1(this, _painterHost)?.querySelector(
91358
+ `.superdoc-page[data-page-index="${hit.pageIndex}"]`
91359
+ );
91360
+ const pageRect2 = pageEl2?.getBoundingClientRect();
91361
+ const zoom2 = __privateGet$1(this, _layoutOptions).zoom ?? 1;
91362
+ let domCaretX2 = null;
91363
+ let domCaretY2 = null;
91364
+ const spanEls2 = pageEl2?.querySelectorAll("span[data-pm-start][data-pm-end]") ?? [];
91365
+ for (const spanEl of spanEls2) {
91366
+ const pmStart = Number(spanEl.dataset.pmStart);
91367
+ const pmEnd = Number(spanEl.dataset.pmEnd);
91368
+ if (pos >= pmStart && pos <= pmEnd && spanEl.firstChild?.nodeType === Node.TEXT_NODE) {
91369
+ const textNode = spanEl.firstChild;
91370
+ const charIndex = Math.min(pos - pmStart, textNode.length);
91371
+ const rangeObj = document.createRange();
91372
+ rangeObj.setStart(textNode, charIndex);
91373
+ rangeObj.setEnd(textNode, charIndex);
91374
+ const rangeRect = rangeObj.getBoundingClientRect();
91375
+ if (pageRect2) {
91376
+ domCaretX2 = (rangeRect.left - pageRect2.left) / zoom2;
91377
+ domCaretY2 = (rangeRect.top - pageRect2.top) / zoom2;
91378
+ }
91379
+ break;
91380
+ }
91381
+ }
91382
+ if (includeDomFallback && domCaretX2 != null && domCaretY2 != null) {
91383
+ return {
91384
+ pageIndex: hit.pageIndex,
91385
+ x: domCaretX2,
91386
+ y: domCaretY2,
91387
+ height: line.lineHeight
91388
+ };
91389
+ }
91390
+ return result2;
91171
91391
  }
91172
- const localX = fragment.x + markerWidth + indentAdjust + charX;
91392
+ const indentAdjust = calculateTextStartIndent({
91393
+ isFirstLine,
91394
+ isListItem: isListItemFlag,
91395
+ markerWidth,
91396
+ paraIndentLeft: indent.left,
91397
+ firstLineIndent: indent.firstLine,
91398
+ hangingIndent: indent.hanging,
91399
+ wordLayout
91400
+ });
91401
+ const localX = fragment.x + indentAdjust + charX;
91173
91402
  const lineOffset = __privateMethod$1(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, fragment.fromLine, index2);
91174
91403
  const localY = fragment.y + lineOffset;
91175
91404
  const result = {