@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
@@ -19631,9 +19631,9 @@ function encodeCSSFromPPr(paragraphProperties, hasPreviousParagraph, nextParagra
19631
19631
  const { spacing, indent, borders, justification } = paragraphProperties;
19632
19632
  const nextStyleId = nextParagraphProps?.styleId;
19633
19633
  if (spacing) {
19634
- const getEffectiveBefore = (nextSpacing, isListItem) => {
19634
+ const getEffectiveBefore = (nextSpacing, isListItem2) => {
19635
19635
  if (!nextSpacing) return 0;
19636
- if (nextSpacing.beforeAutospacing && isListItem) {
19636
+ if (nextSpacing.beforeAutospacing && isListItem2) {
19637
19637
  return 0;
19638
19638
  }
19639
19639
  return nextSpacing.before || 0;
@@ -20014,7 +20014,7 @@ function addTextDecorationEntries(targetSet, value) {
20014
20014
  }
20015
20015
  String(value).split(/\s+/).map((entry) => entry.trim()).filter(Boolean).forEach((entry) => targetSet.add(entry));
20016
20016
  }
20017
- const getSpacingStyle = (spacing, isListItem) => {
20017
+ const getSpacingStyle = (spacing, isListItem2) => {
20018
20018
  let { before, after, line, lineRule, beforeAutospacing, afterAutospacing } = spacing;
20019
20019
  line = twipsToLines(line);
20020
20020
  if (line != null && line < 1) {
@@ -20025,13 +20025,13 @@ const getSpacingStyle = (spacing, isListItem) => {
20025
20025
  }
20026
20026
  before = twipsToPixels$2(before);
20027
20027
  if (beforeAutospacing) {
20028
- if (isListItem) {
20028
+ if (isListItem2) {
20029
20029
  before = 0;
20030
20030
  }
20031
20031
  }
20032
20032
  after = twipsToPixels$2(after);
20033
20033
  if (afterAutospacing) {
20034
- if (isListItem) {
20034
+ if (isListItem2) {
20035
20035
  after = 0;
20036
20036
  }
20037
20037
  }
@@ -42397,7 +42397,7 @@ const _SuperConverter = class _SuperConverter2 {
42397
42397
  static getStoredSuperdocVersion(docx) {
42398
42398
  return _SuperConverter2.getStoredCustomProperty(docx, "SuperdocVersion");
42399
42399
  }
42400
- static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.87") {
42400
+ static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.89") {
42401
42401
  return _SuperConverter2.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
42402
42402
  }
42403
42403
  /**
@@ -59603,7 +59603,7 @@ const isHeadless = (editor) => {
59603
59603
  const shouldSkipNodeView = (editor) => {
59604
59604
  return isHeadless(editor);
59605
59605
  };
59606
- const summaryVersion = "1.0.0-beta.87";
59606
+ const summaryVersion = "1.0.0-beta.89";
59607
59607
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
59608
59608
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
59609
59609
  function mapAttributes(attrs) {
@@ -60392,7 +60392,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
60392
60392
  { default: remarkStringify },
60393
60393
  { default: remarkGfm }
60394
60394
  ] = await Promise.all([
60395
- Promise.resolve().then(() => require("./index-rv7o9043-DD5SvBoC.cjs")),
60395
+ Promise.resolve().then(() => require("./index-DcTrJ8db-kUMXGs8M.cjs")),
60396
60396
  Promise.resolve().then(() => require("./index-DRCvimau-H4Ck3S9a.cjs")),
60397
60397
  Promise.resolve().then(() => require("./index-C_x_N6Uh-Db3CUJMX.cjs")),
60398
60398
  Promise.resolve().then(() => require("./index-D_sWOSiG-BtDZzJ6I.cjs")),
@@ -60597,7 +60597,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
60597
60597
  * Process collaboration migrations
60598
60598
  */
60599
60599
  processCollaborationMigrations() {
60600
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.87");
60600
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.89");
60601
60601
  if (!this.options.ydoc) return;
60602
60602
  const metaMap = this.options.ydoc.getMap("meta");
60603
60603
  let docVersion = metaMap.get("version");
@@ -73509,7 +73509,14 @@ const renderTableCell = (deps) => {
73509
73509
  let renderedHeight = 0;
73510
73510
  for (let lineIdx = localStartLine; lineIdx < localEndLine && lineIdx < lines.length; lineIdx++) {
73511
73511
  const line = lines[lineIdx];
73512
- const lineEl = renderLine(block, line, { ...context, section: "body" });
73512
+ const isLastLine = lineIdx === lines.length - 1;
73513
+ const lineEl = renderLine(
73514
+ block,
73515
+ line,
73516
+ { ...context, section: "body" },
73517
+ lineIdx,
73518
+ isLastLine
73519
+ );
73513
73520
  lineEl.style.paddingLeft = "";
73514
73521
  lineEl.style.paddingRight = "";
73515
73522
  lineEl.style.textIndent = "";
@@ -76141,8 +76148,11 @@ const _DomPainter = class _DomPainter2 {
76141
76148
  const applyFragmentFrameWithSection = (el, frag) => {
76142
76149
  this.applyFragmentFrame(el, frag, context.section);
76143
76150
  };
76144
- const renderLineForTableCell = (block, line, ctx2) => {
76145
- return this.renderLine(block, line, ctx2, void 0, void 0, true);
76151
+ const renderLineForTableCell = (block, line, ctx2, lineIndex, isLastLine) => {
76152
+ const lastRun = block.runs.length > 0 ? block.runs[block.runs.length - 1] : null;
76153
+ const paragraphEndsWithLineBreak = lastRun?.kind === "lineBreak";
76154
+ const shouldSkipJustify = isLastLine && !paragraphEndsWithLineBreak;
76155
+ return this.renderLine(block, line, ctx2, void 0, lineIndex, shouldSkipJustify);
76146
76156
  };
76147
76157
  const renderDrawingContentForTableCell = (block) => {
76148
76158
  if (block.drawingKind === "image") {
@@ -76751,9 +76761,10 @@ const _DomPainter = class _DomPainter2 {
76751
76761
  el.setAttribute("styleid", styleId);
76752
76762
  }
76753
76763
  const alignment2 = block.attrs?.alignment;
76754
- if (alignment2 === "center" || alignment2 === "right") {
76755
- el.style.textAlign = alignment2;
76756
- } else if (alignment2 === "justify") {
76764
+ const effectiveAlignment = alignment2;
76765
+ if (effectiveAlignment === "center" || effectiveAlignment === "right") {
76766
+ el.style.textAlign = effectiveAlignment;
76767
+ } else if (effectiveAlignment === "justify") {
76757
76768
  el.style.textAlign = "left";
76758
76769
  } else {
76759
76770
  el.style.textAlign = "left";
@@ -76815,16 +76826,16 @@ const _DomPainter = class _DomPainter2 {
76815
76826
  }
76816
76827
  const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
76817
76828
  const availableWidth = availableWidthOverride ?? line.maxWidth ?? line.width;
76818
- const shouldJustify = !skipJustify && alignment2 === "justify" && !hasExplicitPositioning;
76829
+ const shouldJustify = !skipJustify && effectiveAlignment === "justify" && !hasExplicitPositioning;
76819
76830
  if (shouldJustify) {
76820
76831
  const spaceCount = textSlices.reduce(
76821
76832
  (sum, s2) => sum + Array.from(s2).filter((ch) => ch === " " || ch === " ").length,
76822
76833
  0
76823
76834
  );
76824
- const slack = Math.max(0, availableWidth - line.width);
76825
- if (spaceCount > 0 && slack > 0) {
76826
- const extraPerSpace = slack / spaceCount;
76827
- el.style.wordSpacing = `${extraPerSpace}px`;
76835
+ const slack = availableWidth - line.width;
76836
+ if (spaceCount > 0 && slack !== 0) {
76837
+ const spacingPerSpace = slack / spaceCount;
76838
+ el.style.wordSpacing = `${spacingPerSpace}px`;
76828
76839
  }
76829
76840
  }
76830
76841
  if (hasExplicitPositioning && line.segments) {
@@ -78285,6 +78296,50 @@ function findCharIndexAtX(textNode, container, targetX) {
78285
78296
  }
78286
78297
  return index2;
78287
78298
  }
78299
+ function getWordLayoutConfig(block) {
78300
+ if (!block || block.kind !== "paragraph") {
78301
+ return void 0;
78302
+ }
78303
+ return block.attrs?.wordLayout;
78304
+ }
78305
+ function isListItem(markerWidth, block) {
78306
+ const hasMarkerWidth = markerWidth > 0;
78307
+ if (hasMarkerWidth) {
78308
+ return true;
78309
+ }
78310
+ if (!block || block.kind !== "paragraph") {
78311
+ return false;
78312
+ }
78313
+ const wordLayout = getWordLayoutConfig(block);
78314
+ const hasListAttrs = block.attrs?.listItem != null || wordLayout?.marker != null;
78315
+ if (hasListAttrs) {
78316
+ return true;
78317
+ }
78318
+ const hangingIndent = block.attrs?.indent?.hanging ?? 0;
78319
+ const paraIndentLeft = block.attrs?.indent?.left ?? 0;
78320
+ const hasHangingIndentPattern = hangingIndent > 0 && paraIndentLeft > 0;
78321
+ return hasHangingIndentPattern;
78322
+ }
78323
+ function calculateTextStartIndent(params2) {
78324
+ const { isFirstLine, isListItem: isListItem2, markerWidth, paraIndentLeft, firstLineIndent, hangingIndent, wordLayout } = params2;
78325
+ const firstLineOffset = firstLineIndent - hangingIndent;
78326
+ const isFirstLineIndentMode = wordLayout?.firstLineIndentMode === true;
78327
+ let indentAdjust = paraIndentLeft;
78328
+ if (isListItem2 && isFirstLine && isFirstLineIndentMode) {
78329
+ const textStartFallback = paraIndentLeft + Math.max(firstLineIndent, 0) + markerWidth;
78330
+ indentAdjust = typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : textStartFallback;
78331
+ } else if (isFirstLine && !isListItem2) {
78332
+ indentAdjust += firstLineOffset;
78333
+ }
78334
+ return indentAdjust;
78335
+ }
78336
+ function extractParagraphIndent(indent) {
78337
+ const left2 = typeof indent?.left === "number" && Number.isFinite(indent.left) ? indent.left : 0;
78338
+ const right2 = typeof indent?.right === "number" && Number.isFinite(indent.right) ? indent.right : 0;
78339
+ const firstLine = typeof indent?.firstLine === "number" && Number.isFinite(indent.firstLine) ? indent.firstLine : 0;
78340
+ const hanging = typeof indent?.hanging === "number" && Number.isFinite(indent.hanging) ? indent.hanging : 0;
78341
+ return { left: left2, right: right2, firstLine, hanging };
78342
+ }
78288
78343
  const defaultHeaderFooterIdentifier = () => ({
78289
78344
  headerIds: { default: null, first: null, even: null, odd: null },
78290
78345
  footerIds: { default: null, first: null, even: null, odd: null },
@@ -83296,8 +83351,8 @@ function clickToPosition(layout, blocks, measures, containerPoint, domContainer,
83296
83351
  );
83297
83352
  }
83298
83353
  const markerWidth = fragment.markerWidth ?? measure.marker?.markerWidth ?? 0;
83299
- const isListItem = markerWidth > 0;
83300
- const alignmentOverride = isListItem ? "left" : void 0;
83354
+ const isListItem3 = markerWidth > 0;
83355
+ const alignmentOverride = isListItem3 ? "left" : void 0;
83301
83356
  const pos = mapPointToPm(block, line, pageRelativePoint.x - fragment.x, isRTL, availableWidth, alignmentOverride);
83302
83357
  if (pos == null) {
83303
83358
  logClickStage("warn", "no-position", {
@@ -83341,8 +83396,8 @@ function clickToPosition(layout, blocks, measures, containerPoint, domContainer,
83341
83396
  );
83342
83397
  }
83343
83398
  const cellMarkerWidth = cellMeasure.marker?.markerWidth ?? 0;
83344
- const isListItem = cellMarkerWidth > 0;
83345
- const alignmentOverride = isListItem ? "left" : void 0;
83399
+ const isListItem3 = cellMarkerWidth > 0;
83400
+ const alignmentOverride = isListItem3 ? "left" : void 0;
83346
83401
  const pos = mapPointToPm(cellBlock, line, localX, isRTL, availableWidth, alignmentOverride);
83347
83402
  if (pos != null) {
83348
83403
  logClickStage("log", "success", {
@@ -83500,17 +83555,22 @@ function selectionToRects(layout, blocks, measures, from2, to) {
83500
83555
  const charOffsetFrom = pmPosToCharOffset(block, line, sliceFrom);
83501
83556
  const charOffsetTo = pmPosToCharOffset(block, line, sliceTo);
83502
83557
  const markerWidth = fragment.markerWidth ?? measure.marker?.markerWidth ?? 0;
83503
- const isListItem = markerWidth > 0;
83504
- const alignmentOverride = isListItem ? "left" : void 0;
83558
+ const isListItemFlag = isListItem(markerWidth, block);
83559
+ const alignmentOverride = isListItemFlag ? "left" : void 0;
83505
83560
  const startX = mapPmToX(block, line, charOffsetFrom, fragment.width, alignmentOverride);
83506
83561
  const endX = mapPmToX(block, line, charOffsetTo, fragment.width, alignmentOverride);
83507
- const paraIndentLeft = block.attrs?.indent?.left ?? 0;
83508
- const firstLineOffset = (block.attrs?.indent?.firstLine ?? 0) - (block.attrs?.indent?.hanging ?? 0);
83562
+ const indent = extractParagraphIndent(block.attrs?.indent);
83563
+ const wordLayout = getWordLayoutConfig(block);
83509
83564
  const isFirstLine = index2 === fragment.fromLine;
83510
- let indentAdjust = paraIndentLeft;
83511
- if (isFirstLine && !isListItem) {
83512
- indentAdjust += firstLineOffset;
83513
- }
83565
+ const indentAdjust = calculateTextStartIndent({
83566
+ isFirstLine,
83567
+ isListItem: isListItemFlag,
83568
+ markerWidth,
83569
+ paraIndentLeft: indent.left,
83570
+ firstLineIndent: indent.firstLine,
83571
+ hangingIndent: indent.hanging,
83572
+ wordLayout
83573
+ });
83514
83574
  const rectX = fragment.x + indentAdjust + Math.min(startX, endX);
83515
83575
  const rectWidth = Math.max(1, Math.abs(endX - startX));
83516
83576
  const lineOffset = lineHeightBeforeIndex(measure, index2) - lineHeightBeforeIndex(measure, fragment.fromLine);
@@ -83613,9 +83673,12 @@ function selectionToRects(layout, blocks, measures, from2, to) {
83613
83673
  let blockTopCursor = padding.top + verticalOffset;
83614
83674
  renderedBlocks.forEach((info) => {
83615
83675
  const paragraphMarkerWidth = info.measure.marker?.markerWidth ?? 0;
83616
- const isListItem = paragraphMarkerWidth > 0;
83617
- const alignmentOverride = isListItem ? "left" : void 0;
83618
- const paraIndentLeft = info.block.kind === "paragraph" ? info.block.attrs?.indent?.left ?? 0 : 0;
83676
+ const cellIsListItem = isListItem(paragraphMarkerWidth, info.block);
83677
+ const alignmentOverride = cellIsListItem ? "left" : void 0;
83678
+ const cellIndent = extractParagraphIndent(
83679
+ info.block.kind === "paragraph" ? info.block.attrs?.indent : void 0
83680
+ );
83681
+ const cellWordLayout = getWordLayoutConfig(info.block);
83619
83682
  const intersectingLines = findLinesIntersectingRange(info.block, info.measure, from2, to);
83620
83683
  intersectingLines.forEach(({ line, index: index2 }) => {
83621
83684
  if (index2 < info.startLine || index2 >= info.endLine) {
@@ -83631,7 +83694,17 @@ function selectionToRects(layout, blocks, measures, from2, to) {
83631
83694
  const availableWidth = Math.max(1, cellMeasure.width - padding.left - padding.right);
83632
83695
  const startX = mapPmToX(info.block, line, charOffsetFrom, availableWidth, alignmentOverride);
83633
83696
  const endX = mapPmToX(info.block, line, charOffsetTo, availableWidth, alignmentOverride);
83634
- const rectX = fragment.x + cellX + padding.left + paraIndentLeft + Math.min(startX, endX);
83697
+ const isFirstLine = index2 === info.startLine;
83698
+ const textIndentAdjust = calculateTextStartIndent({
83699
+ isFirstLine,
83700
+ isListItem: cellIsListItem,
83701
+ markerWidth: paragraphMarkerWidth,
83702
+ paraIndentLeft: cellIndent.left,
83703
+ firstLineIndent: cellIndent.firstLine,
83704
+ hangingIndent: cellIndent.hanging,
83705
+ wordLayout: cellWordLayout
83706
+ });
83707
+ const rectX = fragment.x + cellX + padding.left + textIndentAdjust + Math.min(startX, endX);
83635
83708
  const rectWidth = Math.max(1, Math.abs(endX - startX));
83636
83709
  const lineOffset = lineHeightBeforeIndex(info.measure, index2) - lineHeightBeforeIndex(info.measure, info.startLine);
83637
83710
  const rectY = fragment.y + rowOffset + blockTopCursor + lineOffset;
@@ -84003,9 +84076,7 @@ function getMeasuredTextWidth(text, font, letterSpacing, ctx2) {
84003
84076
  try {
84004
84077
  ctx2.font = font;
84005
84078
  const metrics = ctx2.measureText(text);
84006
- const advanceWidth = metrics.width;
84007
- const paintedWidth = (metrics.actualBoundingBoxLeft || 0) + (metrics.actualBoundingBoxRight || 0);
84008
- const baseWidth = Math.max(advanceWidth, paintedWidth);
84079
+ const baseWidth = metrics.width;
84009
84080
  const extra = letterSpacing ? Math.max(0, text.length - 1) * letterSpacing : 0;
84010
84081
  const width = baseWidth + extra;
84011
84082
  cache$1.set(key2, { width });
@@ -84214,7 +84285,8 @@ async function measureParagraphBlock(block, maxWidth) {
84214
84285
  const isWordLayoutList = Boolean(wordLayout?.marker);
84215
84286
  const suppressFirstLine = block.attrs?.suppressFirstLineIndent === true;
84216
84287
  const rawFirstLineOffset = suppressFirstLine ? 0 : firstLine - hanging;
84217
- const firstLineOffset = isWordLayoutList ? 0 : rawFirstLineOffset;
84288
+ const clampedFirstLineOffset = Math.max(0, rawFirstLineOffset);
84289
+ const firstLineOffset = isWordLayoutList ? 0 : clampedFirstLineOffset;
84218
84290
  const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
84219
84291
  let leftJustifiedMarkerSpace = 0;
84220
84292
  if (wordLayout?.marker) {
@@ -84367,7 +84439,8 @@ async function measureParagraphBlock(block, maxWidth) {
84367
84439
  if (run2.kind === "break") {
84368
84440
  if (currentLine) {
84369
84441
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84370
- const completedLine = { ...currentLine, ...metrics };
84442
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84443
+ const completedLine = { ...lineBase, ...metrics };
84371
84444
  addBarTabsToLine(completedLine);
84372
84445
  lines.push(completedLine);
84373
84446
  currentLine = null;
@@ -84428,7 +84501,8 @@ async function measureParagraphBlock(block, maxWidth) {
84428
84501
  width: 0,
84429
84502
  maxFontSize: lastFontSize,
84430
84503
  maxWidth: nextLineMaxWidth,
84431
- segments: []
84504
+ segments: [],
84505
+ spaceCount: 0
84432
84506
  };
84433
84507
  tabStopCursor = 0;
84434
84508
  pendingTabAlignment = null;
@@ -84446,7 +84520,8 @@ async function measureParagraphBlock(block, maxWidth) {
84446
84520
  maxFontSize: 12,
84447
84521
  // Default font size for tabs
84448
84522
  maxWidth: getEffectiveWidth(initialAvailableWidth),
84449
- segments: []
84523
+ segments: [],
84524
+ spaceCount: 0
84450
84525
  };
84451
84526
  }
84452
84527
  const originX = currentLine.width;
@@ -84495,6 +84570,7 @@ async function measureParagraphBlock(block, maxWidth) {
84495
84570
  maxFontSize: imageHeight,
84496
84571
  // Use image height for line height calculation
84497
84572
  maxWidth: getEffectiveWidth(initialAvailableWidth),
84573
+ spaceCount: 0,
84498
84574
  segments: [
84499
84575
  {
84500
84576
  runIndex,
@@ -84510,8 +84586,9 @@ async function measureParagraphBlock(block, maxWidth) {
84510
84586
  const appliedTabAlign = lastAppliedTabAlign;
84511
84587
  if (currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
84512
84588
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84589
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84513
84590
  const completedLine = {
84514
- ...currentLine,
84591
+ ...lineBase,
84515
84592
  ...metrics
84516
84593
  };
84517
84594
  addBarTabsToLine(completedLine);
@@ -84527,6 +84604,7 @@ async function measureParagraphBlock(block, maxWidth) {
84527
84604
  width: imageWidth,
84528
84605
  maxFontSize: imageHeight,
84529
84606
  maxWidth: getEffectiveWidth(contentWidth),
84607
+ spaceCount: 0,
84530
84608
  segments: [
84531
84609
  {
84532
84610
  runIndex,
@@ -84582,6 +84660,7 @@ async function measureParagraphBlock(block, maxWidth) {
84582
84660
  width: annotationWidth,
84583
84661
  maxFontSize: annotationHeight,
84584
84662
  maxWidth: getEffectiveWidth(initialAvailableWidth),
84663
+ spaceCount: 0,
84585
84664
  segments: [
84586
84665
  {
84587
84666
  runIndex,
@@ -84596,8 +84675,9 @@ async function measureParagraphBlock(block, maxWidth) {
84596
84675
  }
84597
84676
  if (currentLine.width + annotationWidth > currentLine.maxWidth && currentLine.width > 0) {
84598
84677
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84678
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84599
84679
  const completedLine = {
84600
- ...currentLine,
84680
+ ...lineBase,
84601
84681
  ...metrics
84602
84682
  };
84603
84683
  addBarTabsToLine(completedLine);
@@ -84613,6 +84693,7 @@ async function measureParagraphBlock(block, maxWidth) {
84613
84693
  width: annotationWidth,
84614
84694
  maxFontSize: annotationHeight,
84615
84695
  maxWidth: getEffectiveWidth(contentWidth),
84696
+ spaceCount: 0,
84616
84697
  segments: [
84617
84698
  {
84618
84699
  runIndex,
@@ -84668,14 +84749,16 @@ async function measureParagraphBlock(block, maxWidth) {
84668
84749
  maxFontSize: run2.fontSize,
84669
84750
  maxFontInfo: getFontInfoFromRun(run2),
84670
84751
  maxWidth: getEffectiveWidth(initialAvailableWidth),
84671
- segments: [{ runIndex, fromChar: spacesStartChar, toChar: spacesEndChar, width: spacesWidth }]
84752
+ segments: [{ runIndex, fromChar: spacesStartChar, toChar: spacesEndChar, width: spacesWidth }],
84753
+ spaceCount: spacesLength
84672
84754
  };
84673
84755
  } else {
84674
84756
  const boundarySpacing = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
84675
84757
  if (currentLine.width + boundarySpacing + spacesWidth > currentLine.maxWidth - WIDTH_FUDGE_PX && currentLine.width > 0) {
84676
84758
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84759
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84677
84760
  const completedLine = {
84678
- ...currentLine,
84761
+ ...lineBase,
84679
84762
  ...metrics
84680
84763
  };
84681
84764
  addBarTabsToLine(completedLine);
@@ -84692,7 +84775,8 @@ async function measureParagraphBlock(block, maxWidth) {
84692
84775
  maxFontSize: run2.fontSize,
84693
84776
  maxFontInfo: getFontInfoFromRun(run2),
84694
84777
  maxWidth: getEffectiveWidth(contentWidth),
84695
- segments: [{ runIndex, fromChar: spacesStartChar, toChar: spacesEndChar, width: spacesWidth }]
84778
+ segments: [{ runIndex, fromChar: spacesStartChar, toChar: spacesEndChar, width: spacesWidth }],
84779
+ spaceCount: spacesLength
84696
84780
  };
84697
84781
  } else {
84698
84782
  currentLine.toRun = runIndex;
@@ -84701,6 +84785,7 @@ async function measureParagraphBlock(block, maxWidth) {
84701
84785
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run2);
84702
84786
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run2.fontSize);
84703
84787
  appendSegment(currentLine.segments, runIndex, spacesStartChar, spacesEndChar, spacesWidth);
84788
+ currentLine.spaceCount += spacesLength;
84704
84789
  }
84705
84790
  }
84706
84791
  charPosInRun = spacesEndChar;
@@ -84717,7 +84802,56 @@ async function measureParagraphBlock(block, maxWidth) {
84717
84802
  for (let wordIndex = 0; wordIndex < words.length; wordIndex++) {
84718
84803
  const word = words[wordIndex];
84719
84804
  if (word === "") {
84720
- charPosInRun += 1;
84805
+ const spaceStartChar = charPosInRun;
84806
+ const spaceEndChar = charPosInRun + 1;
84807
+ const singleSpaceWidth = measureRunWidth(" ", font, ctx2, run2);
84808
+ if (!currentLine) {
84809
+ currentLine = {
84810
+ fromRun: runIndex,
84811
+ fromChar: spaceStartChar,
84812
+ toRun: runIndex,
84813
+ toChar: spaceEndChar,
84814
+ width: singleSpaceWidth,
84815
+ maxFontSize: run2.fontSize,
84816
+ maxFontInfo: getFontInfoFromRun(run2),
84817
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
84818
+ segments: [{ runIndex, fromChar: spaceStartChar, toChar: spaceEndChar, width: singleSpaceWidth }],
84819
+ spaceCount: 1
84820
+ };
84821
+ } else {
84822
+ const boundarySpacing2 = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
84823
+ if (currentLine.width + boundarySpacing2 + singleSpaceWidth > currentLine.maxWidth - WIDTH_FUDGE_PX && currentLine.width > 0) {
84824
+ const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84825
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84826
+ const completedLine = { ...lineBase, ...metrics };
84827
+ addBarTabsToLine(completedLine);
84828
+ lines.push(completedLine);
84829
+ tabStopCursor = 0;
84830
+ pendingTabAlignment = null;
84831
+ lastAppliedTabAlign = null;
84832
+ currentLine = {
84833
+ fromRun: runIndex,
84834
+ fromChar: spaceStartChar,
84835
+ toRun: runIndex,
84836
+ toChar: spaceEndChar,
84837
+ width: singleSpaceWidth,
84838
+ maxFontSize: run2.fontSize,
84839
+ maxFontInfo: getFontInfoFromRun(run2),
84840
+ maxWidth: getEffectiveWidth(contentWidth),
84841
+ segments: [{ runIndex, fromChar: spaceStartChar, toChar: spaceEndChar, width: singleSpaceWidth }],
84842
+ spaceCount: 1
84843
+ };
84844
+ } else {
84845
+ currentLine.toRun = runIndex;
84846
+ currentLine.toChar = spaceEndChar;
84847
+ currentLine.width = roundValue(currentLine.width + boundarySpacing2 + singleSpaceWidth);
84848
+ currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run2);
84849
+ currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run2.fontSize);
84850
+ appendSegment(currentLine.segments, runIndex, spaceStartChar, spaceEndChar, singleSpaceWidth);
84851
+ currentLine.spaceCount += 1;
84852
+ }
84853
+ }
84854
+ charPosInRun = spaceEndChar;
84721
84855
  continue;
84722
84856
  }
84723
84857
  const isLastWordInSegment = wordIndex === words.length - 1;
@@ -84738,13 +84872,15 @@ async function measureParagraphBlock(block, maxWidth) {
84738
84872
  maxFontSize: run2.fontSize,
84739
84873
  maxFontInfo: getFontInfoFromRun(run2),
84740
84874
  maxWidth: getEffectiveWidth(initialAvailableWidth),
84741
- segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
84875
+ segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }],
84876
+ spaceCount: 0
84742
84877
  };
84743
84878
  const ls = run2.letterSpacing ?? 0;
84744
84879
  if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX) {
84745
84880
  currentLine.toChar = wordEndWithSpace;
84746
84881
  currentLine.width = roundValue(currentLine.width + spaceWidth + ls);
84747
84882
  charPosInRun = wordEndWithSpace;
84883
+ currentLine.spaceCount += 1;
84748
84884
  } else {
84749
84885
  charPosInRun = wordEndWithSpace;
84750
84886
  }
@@ -84752,10 +84888,36 @@ async function measureParagraphBlock(block, maxWidth) {
84752
84888
  }
84753
84889
  const isTocEntry = block.attrs?.isTocEntry;
84754
84890
  const boundarySpacing = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
84755
- if (currentLine.width + boundarySpacing + wordOnlyWidth > currentLine.maxWidth - WIDTH_FUDGE_PX && currentLine.width > 0 && !isTocEntry) {
84891
+ const justifyAlignment = block.attrs?.alignment === "justify";
84892
+ const totalWidthWithWord = currentLine.width + boundarySpacing + wordCommitWidth + // Safe cast: only TextRuns produce word segments from split(), other run types are handled earlier
84893
+ (isLastWord ? 0 : run2.letterSpacing ?? 0);
84894
+ const availableWidth = currentLine.maxWidth - WIDTH_FUDGE_PX;
84895
+ let shouldBreak = currentLine.width + boundarySpacing + wordOnlyWidth > availableWidth && currentLine.width > 0 && !isTocEntry;
84896
+ let compressedWidth = null;
84897
+ if (shouldBreak && justifyAlignment) {
84898
+ const isParagraphLastWord = isLastWord && runIndex === runsToProcess.length - 1;
84899
+ if (!isParagraphLastWord) {
84900
+ const existingSpaces = currentLine.spaceCount ?? 0;
84901
+ const candidateSpaces = existingSpaces + (isLastWord ? 0 : 1);
84902
+ if (candidateSpaces > 0) {
84903
+ const overflow = totalWidthWithWord - availableWidth;
84904
+ if (overflow > 0) {
84905
+ const baseSpaceWidth = spaceWidth || measureRunWidth(" ", font, ctx2, run2) || Math.max(1, boundarySpacing);
84906
+ const perSpaceCompression = overflow / candidateSpaces;
84907
+ const maxPerSpaceCompression = baseSpaceWidth * 0.25;
84908
+ if (perSpaceCompression <= maxPerSpaceCompression) {
84909
+ shouldBreak = false;
84910
+ compressedWidth = availableWidth;
84911
+ }
84912
+ }
84913
+ }
84914
+ }
84915
+ }
84916
+ if (shouldBreak) {
84756
84917
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84918
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84757
84919
  const completedLine = {
84758
- ...currentLine,
84920
+ ...lineBase,
84759
84921
  ...metrics
84760
84922
  };
84761
84923
  addBarTabsToLine(completedLine);
@@ -84771,12 +84933,14 @@ async function measureParagraphBlock(block, maxWidth) {
84771
84933
  maxFontSize: run2.fontSize,
84772
84934
  maxFontInfo: getFontInfoFromRun(run2),
84773
84935
  maxWidth: getEffectiveWidth(contentWidth),
84774
- segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
84936
+ segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }],
84937
+ spaceCount: 0
84775
84938
  };
84776
84939
  if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX) {
84777
84940
  currentLine.toChar = wordEndWithSpace;
84778
84941
  currentLine.width = roundValue(currentLine.width + spaceWidth + (run2.letterSpacing ?? 0));
84779
84942
  charPosInRun = wordEndWithSpace;
84943
+ currentLine.spaceCount += 1;
84780
84944
  } else {
84781
84945
  charPosInRun = wordEndWithSpace;
84782
84946
  }
@@ -84797,7 +84961,8 @@ async function measureParagraphBlock(block, maxWidth) {
84797
84961
  useExplicitXHere ? segmentStartX : void 0
84798
84962
  );
84799
84963
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
84800
- const completedLine = { ...currentLine, ...metrics };
84964
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84965
+ const completedLine = { ...lineBase, ...metrics };
84801
84966
  addBarTabsToLine(completedLine);
84802
84967
  lines.push(completedLine);
84803
84968
  tabStopCursor = 0;
@@ -84810,12 +84975,14 @@ async function measureParagraphBlock(block, maxWidth) {
84810
84975
  currentLine.toChar = newToChar;
84811
84976
  const useExplicitX = wordIndex === 0 && segmentStartX !== void 0;
84812
84977
  const explicitX = useExplicitX ? segmentStartX : void 0;
84813
- currentLine.width = roundValue(
84814
- currentLine.width + boundarySpacing + wordCommitWidth + (isLastWord ? 0 : run2.letterSpacing ?? 0)
84815
- );
84978
+ const targetWidth = compressedWidth != null ? compressedWidth : currentLine.width + boundarySpacing + wordCommitWidth + (isLastWord ? 0 : run2.letterSpacing ?? 0);
84979
+ currentLine.width = roundValue(targetWidth);
84816
84980
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run2);
84817
84981
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run2.fontSize);
84818
84982
  appendSegment(currentLine.segments, runIndex, wordStartChar, newToChar, wordCommitWidth, explicitX);
84983
+ if (!isLastWord) {
84984
+ currentLine.spaceCount += 1;
84985
+ }
84819
84986
  }
84820
84987
  charPosInRun = isLastWord ? wordEndNoSpace : wordEndWithSpace;
84821
84988
  }
@@ -84838,7 +85005,8 @@ async function measureParagraphBlock(block, maxWidth) {
84838
85005
  maxFontSize: run2.fontSize,
84839
85006
  maxFontInfo: getFontInfoFromRun(run2),
84840
85007
  maxWidth: getEffectiveWidth(initialAvailableWidth),
84841
- segments: []
85008
+ segments: [],
85009
+ spaceCount: 0
84842
85010
  };
84843
85011
  }
84844
85012
  const originX = currentLine.width;
@@ -84884,8 +85052,9 @@ async function measureParagraphBlock(block, maxWidth) {
84884
85052
  }
84885
85053
  if (currentLine) {
84886
85054
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
85055
+ const { spaceCount: _sc, ...lineBase } = currentLine;
84887
85056
  const finalLine = {
84888
- ...currentLine,
85057
+ ...lineBase,
84889
85058
  ...metrics
84890
85059
  };
84891
85060
  addBarTabsToLine(finalLine);
@@ -91175,18 +91344,78 @@ computeCaretLayoutRectGeometry_fn = function(pos, includeDomFallback = true) {
91175
91344
  if (range2.pmStart == null || range2.pmEnd == null) return null;
91176
91345
  const pmOffset = pmPosToCharOffset(block, line, pos);
91177
91346
  const markerWidth = fragment.markerWidth ?? measure.marker?.markerWidth ?? 0;
91178
- const paraIndentLeft = block.attrs?.indent?.left ?? 0;
91179
- const paraIndentRight = block.attrs?.indent?.right ?? 0;
91180
- const availableWidth = Math.max(0, fragment.width - (paraIndentLeft + paraIndentRight));
91347
+ const indent = extractParagraphIndent(block.attrs?.indent);
91348
+ const availableWidth = Math.max(0, fragment.width - (indent.left + indent.right));
91181
91349
  const charX = measureCharacterX(block, line, pmOffset, availableWidth);
91182
- const firstLineOffset = (block.attrs?.indent?.firstLine ?? 0) - (block.attrs?.indent?.hanging ?? 0);
91183
91350
  const isFirstLine = index2 === fragment.fromLine;
91184
- const isListFirstLine = isFirstLine && !fragment.continuesFromPrev && (fragment.markerWidth ?? 0) > 0;
91185
- let indentAdjust = 0;
91186
- if (!isListFirstLine) {
91187
- indentAdjust = paraIndentLeft + (isFirstLine ? firstLineOffset : 0);
91351
+ const isListItemFlag = isListItem(markerWidth, block);
91352
+ const isListFirstLine = isFirstLine && !fragment.continuesFromPrev && isListItemFlag;
91353
+ const wordLayout = getWordLayoutConfig(block);
91354
+ const isFirstLineIndentMode = wordLayout?.firstLineIndentMode === true;
91355
+ if (isListFirstLine && isFirstLineIndentMode) {
91356
+ const textStartPx = calculateTextStartIndent({
91357
+ isFirstLine,
91358
+ isListItem: isListItemFlag,
91359
+ markerWidth,
91360
+ paraIndentLeft: indent.left,
91361
+ firstLineIndent: indent.firstLine,
91362
+ hangingIndent: indent.hanging,
91363
+ wordLayout
91364
+ });
91365
+ const localX2 = fragment.x + textStartPx + charX;
91366
+ const lineOffset2 = __privateMethod$1(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, fragment.fromLine, index2);
91367
+ const localY2 = fragment.y + lineOffset2;
91368
+ const result2 = {
91369
+ pageIndex: hit.pageIndex,
91370
+ x: localX2,
91371
+ y: localY2,
91372
+ height: line.lineHeight
91373
+ };
91374
+ const pageEl2 = __privateGet$1(this, _painterHost)?.querySelector(
91375
+ `.superdoc-page[data-page-index="${hit.pageIndex}"]`
91376
+ );
91377
+ const pageRect2 = pageEl2?.getBoundingClientRect();
91378
+ const zoom2 = __privateGet$1(this, _layoutOptions).zoom ?? 1;
91379
+ let domCaretX2 = null;
91380
+ let domCaretY2 = null;
91381
+ const spanEls2 = pageEl2?.querySelectorAll("span[data-pm-start][data-pm-end]") ?? [];
91382
+ for (const spanEl of spanEls2) {
91383
+ const pmStart = Number(spanEl.dataset.pmStart);
91384
+ const pmEnd = Number(spanEl.dataset.pmEnd);
91385
+ if (pos >= pmStart && pos <= pmEnd && spanEl.firstChild?.nodeType === Node.TEXT_NODE) {
91386
+ const textNode = spanEl.firstChild;
91387
+ const charIndex = Math.min(pos - pmStart, textNode.length);
91388
+ const rangeObj = document.createRange();
91389
+ rangeObj.setStart(textNode, charIndex);
91390
+ rangeObj.setEnd(textNode, charIndex);
91391
+ const rangeRect = rangeObj.getBoundingClientRect();
91392
+ if (pageRect2) {
91393
+ domCaretX2 = (rangeRect.left - pageRect2.left) / zoom2;
91394
+ domCaretY2 = (rangeRect.top - pageRect2.top) / zoom2;
91395
+ }
91396
+ break;
91397
+ }
91398
+ }
91399
+ if (includeDomFallback && domCaretX2 != null && domCaretY2 != null) {
91400
+ return {
91401
+ pageIndex: hit.pageIndex,
91402
+ x: domCaretX2,
91403
+ y: domCaretY2,
91404
+ height: line.lineHeight
91405
+ };
91406
+ }
91407
+ return result2;
91188
91408
  }
91189
- const localX = fragment.x + markerWidth + indentAdjust + charX;
91409
+ const indentAdjust = calculateTextStartIndent({
91410
+ isFirstLine,
91411
+ isListItem: isListItemFlag,
91412
+ markerWidth,
91413
+ paraIndentLeft: indent.left,
91414
+ firstLineIndent: indent.firstLine,
91415
+ hangingIndent: indent.hanging,
91416
+ wordLayout
91417
+ });
91418
+ const localX = fragment.x + indentAdjust + charX;
91190
91419
  const lineOffset = __privateMethod$1(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, fragment.fromLine, index2);
91191
91420
  const localY = fragment.y + lineOffset;
91192
91421
  const result = {