@harbour-enterprises/superdoc 1.0.0-next.3 → 1.0.0-next.5

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 (54) hide show
  1. package/dist/chunks/{PdfViewer-PUn0q_lG.es.js → PdfViewer-BQ7d08ku.es.js} +1 -1
  2. package/dist/chunks/{PdfViewer-cVGt7Ne7.cjs → PdfViewer-D8FKTxiO.cjs} +1 -1
  3. package/dist/chunks/{index-Djmhr-R6.cjs → index-BOkSE8Li.cjs} +6 -5
  4. package/dist/chunks/{index-DLO-SgUP-BNtYQDPq.cjs → index-BUoOdDUj-CF4U3xYL.cjs} +1 -1
  5. package/dist/chunks/{index-DLO-SgUP-c73otQJ5.es.js → index-BUoOdDUj-CLmpIPsb.es.js} +1 -1
  6. package/dist/chunks/{index-mHanL4xN.es.js → index-D3wrs960.es.js} +6 -5
  7. package/dist/chunks/{super-editor.es-Cve8WKfM.cjs → super-editor.es-Bj_Ga0sp.cjs} +417 -117
  8. package/dist/chunks/{super-editor.es-S9Kp_7dy.es.js → super-editor.es-vynpc_1U.es.js} +417 -117
  9. package/dist/style.css +6 -6
  10. package/dist/super-editor/ai-writer.es.js +2 -2
  11. package/dist/super-editor/chunks/{converter-ByybZRFp.js → converter-D6Kvbivo.js} +1 -1
  12. package/dist/super-editor/chunks/{docx-zipper-CFQANTLI.js → docx-zipper-DAS45uKP.js} +1 -1
  13. package/dist/super-editor/chunks/{editor-Cu4hD14N.js → editor-BMEPaiVS.js} +418 -118
  14. package/dist/super-editor/chunks/{index-DLO-SgUP.js → index-BUoOdDUj.js} +1 -1
  15. package/dist/super-editor/chunks/{toolbar-5MMla0sj.js → toolbar-CUWKY5Cx.js} +2 -2
  16. package/dist/super-editor/converter.es.js +1 -1
  17. package/dist/super-editor/docx-zipper.es.js +2 -2
  18. package/dist/super-editor/editor.es.js +3 -3
  19. package/dist/super-editor/file-zipper.es.js +1 -1
  20. package/dist/super-editor/super-editor.es.js +6 -6
  21. package/dist/super-editor/toolbar.es.js +2 -2
  22. package/dist/super-editor.cjs +1 -1
  23. package/dist/super-editor.es.js +1 -1
  24. package/dist/superdoc.cjs +2 -2
  25. package/dist/superdoc.es.js +2 -2
  26. package/dist/superdoc.umd.js +422 -121
  27. package/dist/superdoc.umd.js.map +1 -1
  28. package/package.json +1 -1
  29. package/dist/images/altText_add.svg +0 -3
  30. package/dist/images/altText_disclaimer.svg +0 -3
  31. package/dist/images/altText_done.svg +0 -3
  32. package/dist/images/altText_spinner.svg +0 -30
  33. package/dist/images/altText_warning.svg +0 -3
  34. package/dist/images/annotation-check.svg +0 -11
  35. package/dist/images/annotation-comment.svg +0 -16
  36. package/dist/images/annotation-help.svg +0 -26
  37. package/dist/images/annotation-insert.svg +0 -10
  38. package/dist/images/annotation-key.svg +0 -11
  39. package/dist/images/annotation-newparagraph.svg +0 -11
  40. package/dist/images/annotation-noicon.svg +0 -7
  41. package/dist/images/annotation-note.svg +0 -42
  42. package/dist/images/annotation-paperclip.svg +0 -6
  43. package/dist/images/annotation-paragraph.svg +0 -16
  44. package/dist/images/annotation-pushpin.svg +0 -7
  45. package/dist/images/cursor-editorFreeHighlight.svg +0 -6
  46. package/dist/images/cursor-editorFreeText.svg +0 -3
  47. package/dist/images/cursor-editorInk.svg +0 -4
  48. package/dist/images/cursor-editorTextHighlight.svg +0 -8
  49. package/dist/images/editor-toolbar-delete.svg +0 -5
  50. package/dist/images/loading-icon.gif +0 -0
  51. package/dist/images/messageBar_closingButton.svg +0 -3
  52. package/dist/images/messageBar_warning.svg +0 -3
  53. package/dist/images/toolbarButton-editorHighlight.svg +0 -6
  54. package/dist/images/toolbarButton-menuArrow.svg +0 -3
@@ -42428,7 +42428,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
42428
42428
  static getStoredSuperdocVersion(docx) {
42429
42429
  return _SuperConverter2.getStoredCustomProperty(docx, "SuperdocVersion");
42430
42430
  }
42431
- static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-next.3") {
42431
+ static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-next.5") {
42432
42432
  return _SuperConverter2.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
42433
42433
  }
42434
42434
  /**
@@ -67513,7 +67513,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
67513
67513
  const shouldSkipNodeView = (editor) => {
67514
67514
  return isHeadless(editor);
67515
67515
  };
67516
- const summaryVersion = "1.0.0-next.3";
67516
+ const summaryVersion = "1.0.0-next.5";
67517
67517
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
67518
67518
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
67519
67519
  function mapAttributes(attrs) {
@@ -68302,7 +68302,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68302
68302
  { default: remarkStringify2 },
68303
68303
  { default: remarkGfm2 }
68304
68304
  ] = await Promise.all([
68305
- Promise.resolve().then(() => indexDLOSgUP),
68305
+ Promise.resolve().then(() => indexBUoOdDUj),
68306
68306
  Promise.resolve().then(() => indexDRCvimau),
68307
68307
  Promise.resolve().then(() => indexC_x_N6Uh),
68308
68308
  Promise.resolve().then(() => indexD_sWOSiG),
@@ -68507,7 +68507,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68507
68507
  * Process collaboration migrations
68508
68508
  */
68509
68509
  processCollaborationMigrations() {
68510
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-next.3");
68510
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-next.5");
68511
68511
  if (!this.options.ydoc) return;
68512
68512
  const metaMap = this.options.ydoc.getMap("meta");
68513
68513
  let docVersion = metaMap.get("version");
@@ -74112,6 +74112,34 @@ Please report this to https://github.com/markedjs/marked.`, e) {
74112
74112
  tabStopPosUsed: nextStop.pos
74113
74113
  };
74114
74114
  }
74115
+ const SPACE_CHARS$1 = /* @__PURE__ */ new Set([" ", " "]);
74116
+ function shouldApplyJustify(params2) {
74117
+ const { alignment: alignment2, hasExplicitPositioning, isLastLineOfParagraph, paragraphEndsWithLineBreak, skipJustifyOverride } = params2;
74118
+ if (alignment2 !== "justify" && alignment2 !== "both") {
74119
+ return false;
74120
+ }
74121
+ if (skipJustifyOverride === true) {
74122
+ return false;
74123
+ }
74124
+ if (hasExplicitPositioning) {
74125
+ return false;
74126
+ }
74127
+ if (isLastLineOfParagraph && !paragraphEndsWithLineBreak) {
74128
+ return false;
74129
+ }
74130
+ return true;
74131
+ }
74132
+ function calculateJustifySpacing(params2) {
74133
+ const { lineWidth, availableWidth, spaceCount, shouldJustify } = params2;
74134
+ if (!shouldJustify) {
74135
+ return 0;
74136
+ }
74137
+ if (spaceCount <= 0) {
74138
+ return 0;
74139
+ }
74140
+ const slack = availableWidth - lineWidth;
74141
+ return slack / spaceCount;
74142
+ }
74115
74143
  function resolveSpacingIndent$1(style2, numbering) {
74116
74144
  const spacing = {
74117
74145
  before: style2.spacing?.before ?? 0,
@@ -74378,13 +74406,14 @@ Please report this to https://github.com/markedjs/marked.`, e) {
74378
74406
  };
74379
74407
  }
74380
74408
  }
74409
+ const normalizedAlign = normalizeAlignment(resolvedExtended.justification);
74381
74410
  const hydrated = {
74382
74411
  resolved,
74383
74412
  spacing: resolvedSpacing,
74384
74413
  indent: resolvedIndent,
74385
74414
  borders: cloneIfObject(resolvedExtended.borders),
74386
74415
  shading: cloneIfObject(resolvedExtended.shading),
74387
- alignment: resolvedExtended.justification,
74416
+ alignment: normalizedAlign,
74388
74417
  tabStops: cloneIfObject(resolvedExtended.tabStops),
74389
74418
  keepLines: resolvedExtended.keepLines,
74390
74419
  keepNext: resolvedExtended.keepNext,
@@ -75085,7 +75114,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
75085
75114
  } else if (styleAlignment) {
75086
75115
  paragraphAttrs.alignment = styleAlignment;
75087
75116
  } else if (computed2.paragraph.alignment) {
75088
- paragraphAttrs.alignment = computed2.paragraph.alignment;
75117
+ paragraphAttrs.alignment = normalizeAlignment(computed2.paragraph.alignment);
75089
75118
  }
75090
75119
  const spacingPx = spacingPtToPx(spacing, normalizedSpacing);
75091
75120
  if (spacingPx) paragraphAttrs.spacing = spacingPx;
@@ -78042,7 +78071,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
78042
78071
  let measurementCanvas = null;
78043
78072
  let measurementCtx = null;
78044
78073
  const TAB_CHAR_LENGTH = 1;
78045
- const SPACE_CHARS = /* @__PURE__ */ new Set([" ", " "]);
78074
+ const SPACE_CHARS = SPACE_CHARS$1;
78046
78075
  const isTabRun$1 = (run2) => run2?.kind === "tab";
78047
78076
  function getMeasurementContext() {
78048
78077
  if (measurementCtx) return measurementCtx;
@@ -78068,29 +78097,50 @@ Please report this to https://github.com/markedjs/marked.`, e) {
78068
78097
  }
78069
78098
  return spaces;
78070
78099
  };
78071
- const getJustifyAdjustment = (block, line, availableWidthOverride, alignmentOverride) => {
78100
+ const getJustifyAdjustment = (block, line, availableWidthOverride, alignmentOverride, isLastLineOfParagraph, paragraphEndsWithLineBreak, skipJustifyOverride) => {
78072
78101
  if (block.kind !== "paragraph") {
78073
78102
  return { extraPerSpace: 0, totalSpaces: 0 };
78074
78103
  }
78075
- const alignment2 = alignmentOverride ?? block.attrs?.alignment;
78076
- const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
78077
- const availableWidth = availableWidthOverride ?? line.maxWidth ?? line.width;
78078
- const slack = Math.max(0, availableWidth - line.width);
78079
- if (alignment2 !== "justify" || hasExplicitPositioning || slack <= 0) {
78104
+ if (block.runs.length === 0) {
78080
78105
  return { extraPerSpace: 0, totalSpaces: 0 };
78081
78106
  }
78082
- const runs2 = sliceRunsForLine$1(block, line);
78083
- const totalSpaces = runs2.reduce((sum, run2) => {
78084
- if (isTabRun$1(run2) || "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation") {
78085
- return sum;
78086
- }
78087
- return sum + countSpaces(run2.text ?? "");
78088
- }, 0);
78089
- if (totalSpaces <= 0) {
78107
+ const alignment2 = alignmentOverride ?? block.attrs?.alignment;
78108
+ const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0) ?? false;
78109
+ const lastRunIndex = block.runs.length - 1;
78110
+ const lastRun = block.runs[lastRunIndex];
78111
+ const derivedIsLastLine = line.toRun >= lastRunIndex;
78112
+ const derivedEndsWithLineBreak = lastRun ? lastRun.kind === "lineBreak" : false;
78113
+ const shouldJustify = shouldApplyJustify({
78114
+ alignment: alignment2,
78115
+ hasExplicitPositioning,
78116
+ isLastLineOfParagraph: derivedIsLastLine,
78117
+ paragraphEndsWithLineBreak: derivedEndsWithLineBreak,
78118
+ skipJustifyOverride
78119
+ });
78120
+ if (!shouldJustify) {
78090
78121
  return { extraPerSpace: 0, totalSpaces: 0 };
78091
78122
  }
78123
+ let totalSpaces = line.spaceCount ?? 0;
78124
+ if (totalSpaces === 0) {
78125
+ const runs2 = sliceRunsForLine$1(block, line);
78126
+ totalSpaces = runs2.reduce((sum, run2) => {
78127
+ if (isTabRun$1(run2) || "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation") {
78128
+ return sum;
78129
+ }
78130
+ return sum + countSpaces(run2.text ?? "");
78131
+ }, 0);
78132
+ }
78133
+ const availableWidth = availableWidthOverride ?? line.maxWidth ?? line.width;
78134
+ const lineWidth = line.naturalWidth ?? line.width;
78135
+ const extraPerSpace = calculateJustifySpacing({
78136
+ lineWidth,
78137
+ availableWidth,
78138
+ spaceCount: totalSpaces,
78139
+ shouldJustify: true
78140
+ // Already checked above
78141
+ });
78092
78142
  return {
78093
- extraPerSpace: slack / totalSpaces,
78143
+ extraPerSpace,
78094
78144
  totalSpaces
78095
78145
  };
78096
78146
  };
@@ -78157,7 +78207,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
78157
78207
  line.width;
78158
78208
  const justify = getJustifyAdjustment(block, line, availableWidth, alignmentOverride);
78159
78209
  const alignment2 = alignmentOverride ?? (block.kind === "paragraph" ? block.attrs?.alignment : void 0);
78160
- const renderedLineWidth = alignment2 === "justify" ? line.width + Math.max(0, availableWidth - line.width) : line.width;
78210
+ const renderedLineWidth = alignment2 === "justify" && justify.extraPerSpace !== 0 ? availableWidth : line.width;
78161
78211
  const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
78162
78212
  const alignmentOffset = !hasExplicitPositioning && alignment2 === "center" ? Math.max(0, (availableWidth - renderedLineWidth) / 2) : !hasExplicitPositioning && alignment2 === "right" ? Math.max(0, availableWidth - renderedLineWidth) : 0;
78163
78213
  if (hasExplicitPositioning && line.segments && ctx2) {
@@ -78200,13 +78250,13 @@ Please report this to https://github.com/markedjs/marked.`, e) {
78200
78250
  const textUpToTarget = text2.slice(0, offsetInRun);
78201
78251
  const measured2 = ctx2.measureText(textUpToTarget);
78202
78252
  const spacingWidth = computeLetterSpacingWidth(run2, offsetInRun, runLength);
78203
- const spacesInPortion = justify.extraPerSpace > 0 ? countSpaces(textUpToTarget) : 0;
78253
+ const spacesInPortion = justify.extraPerSpace !== 0 ? countSpaces(textUpToTarget) : 0;
78204
78254
  return alignmentOffset + currentX + measured2.width + spacingWidth + justify.extraPerSpace * (spaceTally + spacesInPortion);
78205
78255
  }
78206
78256
  ctx2.font = getRunFontString(run2);
78207
78257
  const measured = ctx2.measureText(text2);
78208
78258
  const runLetterSpacing = computeLetterSpacingWidth(run2, runLength, runLength);
78209
- const spacesInRun = justify.extraPerSpace > 0 ? countSpaces(text2) : 0;
78259
+ const spacesInRun = justify.extraPerSpace !== 0 ? countSpaces(text2) : 0;
78210
78260
  currentX += measured.width + runLetterSpacing + justify.extraPerSpace * spacesInRun;
78211
78261
  spaceTally += spacesInRun;
78212
78262
  currentCharOffset += runLength;
@@ -83358,9 +83408,66 @@ ${l}
83358
83408
  const firstLineOffset = suppressFirstLineIndent ? 0 : (paraIndent?.firstLine ?? 0) - (paraIndent?.hanging ?? 0);
83359
83409
  const lastRun = block.runs.length > 0 ? block.runs[block.runs.length - 1] : null;
83360
83410
  const paragraphEndsWithLineBreak = lastRun?.kind === "lineBreak";
83411
+ let listFirstLineMarkerTabWidth;
83412
+ if (!fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker) {
83413
+ const markerBoxWidth = fragment.markerWidth;
83414
+ const markerTextWidth = fragment.markerTextWidth != null && isFinite(fragment.markerTextWidth) && fragment.markerTextWidth >= 0 ? fragment.markerTextWidth : markerBoxWidth;
83415
+ const suffix2 = wordLayout.marker.suffix ?? "tab";
83416
+ if (suffix2 === "tab") {
83417
+ const markerJustification = wordLayout.marker.justification ?? "left";
83418
+ const isFirstLineIndentMode = wordLayout.firstLineIndentMode === true;
83419
+ let markerStartPos;
83420
+ if (isFirstLineIndentMode && wordLayout.marker.markerX !== void 0 && Number.isFinite(wordLayout.marker.markerX)) {
83421
+ markerStartPos = wordLayout.marker.markerX;
83422
+ } else {
83423
+ const hanging = paraIndent?.hanging ?? 0;
83424
+ const firstLine = paraIndent?.firstLine ?? 0;
83425
+ markerStartPos = paraIndentLeft - hanging + firstLine;
83426
+ }
83427
+ const validMarkerStartPos = Number.isFinite(markerStartPos) ? markerStartPos : 0;
83428
+ let tabWidth;
83429
+ if (markerJustification === "left") {
83430
+ const currentPos = validMarkerStartPos + markerTextWidth;
83431
+ if (isFirstLineIndentMode) {
83432
+ const textStartTarget = wordLayout.marker.textStartX !== void 0 && Number.isFinite(wordLayout.marker.textStartX) ? wordLayout.marker.textStartX : wordLayout.textStartPx;
83433
+ if (textStartTarget !== void 0 && Number.isFinite(textStartTarget) && textStartTarget > currentPos) {
83434
+ tabWidth = textStartTarget - currentPos;
83435
+ } else {
83436
+ tabWidth = LIST_MARKER_GAP$1;
83437
+ }
83438
+ } else {
83439
+ const firstLine = paraIndent?.firstLine ?? 0;
83440
+ const textStart = paraIndentLeft + firstLine;
83441
+ tabWidth = textStart - currentPos;
83442
+ if (tabWidth <= 0) {
83443
+ tabWidth = DEFAULT_TAB_INTERVAL_PX$1 - currentPos % DEFAULT_TAB_INTERVAL_PX$1;
83444
+ } else if (tabWidth < LIST_MARKER_GAP$1) {
83445
+ tabWidth = LIST_MARKER_GAP$1;
83446
+ }
83447
+ }
83448
+ } else {
83449
+ const gutterWidth = fragment.markerGutter ?? wordLayout.marker.gutterWidthPx;
83450
+ tabWidth = gutterWidth !== void 0 && Number.isFinite(gutterWidth) && gutterWidth > 0 ? gutterWidth : LIST_MARKER_GAP$1;
83451
+ }
83452
+ if (tabWidth < LIST_MARKER_GAP$1) {
83453
+ tabWidth = LIST_MARKER_GAP$1;
83454
+ }
83455
+ listFirstLineMarkerTabWidth = validMarkerStartPos + markerTextWidth + tabWidth;
83456
+ } else if (suffix2 === "space") {
83457
+ const hanging = paraIndent?.hanging ?? 0;
83458
+ const firstLine = paraIndent?.firstLine ?? 0;
83459
+ const markerStartPos = paraIndentLeft - hanging + firstLine;
83460
+ const validMarkerStartPos = Number.isFinite(markerStartPos) ? markerStartPos : 0;
83461
+ listFirstLineMarkerTabWidth = validMarkerStartPos + markerTextWidth + 4;
83462
+ }
83463
+ }
83361
83464
  lines.forEach((line, index2) => {
83362
- const fallbackAvailableWidth = Math.max(0, fragment.width - (paraIndentLeft + paraIndentRight));
83363
- const availableWidthOverride = line.maxWidth ?? fallbackAvailableWidth;
83465
+ const positiveIndentReduction = Math.max(0, paraIndentLeft) + Math.max(0, paraIndentRight);
83466
+ const fallbackAvailableWidth = Math.max(0, fragment.width - positiveIndentReduction);
83467
+ let availableWidthOverride = line.maxWidth != null ? Math.min(line.maxWidth, fallbackAvailableWidth) : fallbackAvailableWidth;
83468
+ if (index2 === 0 && listFirstLineMarkerTabWidth != null) {
83469
+ availableWidthOverride = fragment.width - listFirstLineMarkerTabWidth - Math.max(0, paraIndentRight);
83470
+ }
83364
83471
  const isLastLineOfFragment = index2 === lines.length - 1;
83365
83472
  const isLastLineOfParagraph = isLastLineOfFragment && !fragment.continuesOnNext;
83366
83473
  const shouldSkipJustifyForLastLine = isLastLineOfParagraph && !paragraphEndsWithLineBreak;
@@ -83386,7 +83493,10 @@ ${l}
83386
83493
  }
83387
83494
  } else if (paraIndentLeft && paraIndentLeft > 0) {
83388
83495
  lineEl.style.paddingLeft = `${paraIndentLeft}px`;
83389
- } else if (!isFirstLine && paraIndent?.hanging && paraIndent.hanging > 0) {
83496
+ } else if (!isFirstLine && paraIndent?.hanging && paraIndent.hanging > 0 && // Only apply hanging padding when left indent is NOT negative.
83497
+ // When left indent is negative, the fragment position already accounts for it.
83498
+ // Adding padding here would shift body lines right, causing right-side overflow.
83499
+ !(paraIndentLeft != null && paraIndentLeft < 0)) {
83390
83500
  lineEl.style.paddingLeft = `${paraIndent.hanging}px`;
83391
83501
  }
83392
83502
  }
@@ -83415,6 +83525,7 @@ ${l}
83415
83525
  lineEl.style.paddingLeft = `${validMarkerStartPos}px`;
83416
83526
  const markerContainer = this.doc.createElement("span");
83417
83527
  markerContainer.style.display = "inline-block";
83528
+ markerContainer.style.wordSpacing = "0px";
83418
83529
  const markerEl = this.doc.createElement("span");
83419
83530
  markerEl.classList.add("superdoc-paragraph-marker");
83420
83531
  markerEl.textContent = wordLayout.marker.markerText ?? "";
@@ -83500,10 +83611,15 @@ ${l}
83500
83611
  }
83501
83612
  }
83502
83613
  tabEl.style.display = "inline-block";
83614
+ tabEl.style.wordSpacing = "0px";
83503
83615
  tabEl.style.width = `${tabWidth}px`;
83504
83616
  lineEl.prepend(tabEl);
83505
83617
  } else if (suffix2 === "space") {
83506
- lineEl.prepend(this.doc.createTextNode(" "));
83618
+ const spaceEl = this.doc.createElement("span");
83619
+ spaceEl.classList.add("superdoc-marker-suffix-space");
83620
+ spaceEl.style.wordSpacing = "0px";
83621
+ spaceEl.textContent = " ";
83622
+ lineEl.prepend(spaceEl);
83507
83623
  }
83508
83624
  lineEl.prepend(markerContainer);
83509
83625
  }
@@ -84795,11 +84911,8 @@ ${l}
84795
84911
  el.setAttribute("styleid", styleId);
84796
84912
  }
84797
84913
  const alignment2 = block.attrs?.alignment;
84798
- const effectiveAlignment = alignment2;
84799
- if (effectiveAlignment === "center" || effectiveAlignment === "right") {
84800
- el.style.textAlign = effectiveAlignment;
84801
- } else if (effectiveAlignment === "justify") {
84802
- el.style.textAlign = "left";
84914
+ if (alignment2 === "center" || alignment2 === "right") {
84915
+ el.style.textAlign = alignment2;
84803
84916
  } else {
84804
84917
  el.style.textAlign = "left";
84805
84918
  }
@@ -84810,9 +84923,8 @@ ${l}
84810
84923
  if (lineRange.pmEnd != null) {
84811
84924
  el.dataset.pmEnd = String(lineRange.pmEnd);
84812
84925
  }
84813
- const runsForLine = sliceRunsForLine(block, line);
84926
+ let runsForLine = sliceRunsForLine(block, line);
84814
84927
  const trackedConfig = this.resolveTrackedChangesConfig(block);
84815
- runsForLine.length > 0 ? runsForLine.filter((r2) => (r2.kind === "text" || r2.kind === void 0) && "text" in r2 && r2.text != null).map((r2) => r2.text) : gatherTextSlicesForLine(block, line);
84816
84928
  if (runsForLine.length === 0) {
84817
84929
  const span = this.doc.createElement("span");
84818
84930
  span.innerHTML = "&nbsp;";
@@ -84859,7 +84971,156 @@ ${l}
84859
84971
  });
84860
84972
  }
84861
84973
  const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
84862
- availableWidthOverride ?? line.maxWidth ?? line.width;
84974
+ const availableWidth = availableWidthOverride ?? line.maxWidth ?? line.width;
84975
+ const justifyShouldApply = shouldApplyJustify({
84976
+ alignment: block.attrs?.alignment,
84977
+ hasExplicitPositioning: hasExplicitPositioning ?? false,
84978
+ // Caller already folds last-line + trailing lineBreak behavior into skipJustify.
84979
+ isLastLineOfParagraph: false,
84980
+ paragraphEndsWithLineBreak: false,
84981
+ skipJustifyOverride: skipJustify
84982
+ });
84983
+ const countSpaces2 = (text2) => {
84984
+ let count = 0;
84985
+ for (let i2 = 0; i2 < text2.length; i2 += 1) {
84986
+ if (SPACE_CHARS$1.has(text2[i2])) count += 1;
84987
+ }
84988
+ return count;
84989
+ };
84990
+ if (justifyShouldApply) {
84991
+ const stableDataAttrs = (attrs) => {
84992
+ if (!attrs) return void 0;
84993
+ const keys2 = Object.keys(attrs).sort();
84994
+ const out = {};
84995
+ keys2.forEach((key2) => {
84996
+ out[key2] = attrs[key2];
84997
+ });
84998
+ return out;
84999
+ };
85000
+ const mergeSignature = (run2) => JSON.stringify({
85001
+ kind: run2.kind ?? "text",
85002
+ fontFamily: run2.fontFamily,
85003
+ fontSize: run2.fontSize,
85004
+ bold: run2.bold ?? false,
85005
+ italic: run2.italic ?? false,
85006
+ letterSpacing: run2.letterSpacing ?? null,
85007
+ color: run2.color ?? null,
85008
+ underline: run2.underline ?? null,
85009
+ strike: run2.strike ?? false,
85010
+ highlight: run2.highlight ?? null,
85011
+ textTransform: run2.textTransform ?? null,
85012
+ token: run2.token ?? null,
85013
+ pageRefMetadata: run2.pageRefMetadata ?? null,
85014
+ trackedChange: run2.trackedChange ?? null,
85015
+ sdt: run2.sdt ?? null,
85016
+ link: run2.link ?? null,
85017
+ comments: run2.comments ?? null,
85018
+ dataAttrs: stableDataAttrs(run2.dataAttrs) ?? null
85019
+ });
85020
+ const isWhitespaceOnly = (text2) => {
85021
+ if (text2.length === 0) return false;
85022
+ for (let i2 = 0; i2 < text2.length; i2 += 1) {
85023
+ if (!SPACE_CHARS$1.has(text2[i2])) return false;
85024
+ }
85025
+ return true;
85026
+ };
85027
+ const cloneTextRun = (run2) => ({
85028
+ ...run2,
85029
+ comments: run2.comments ? [...run2.comments] : void 0,
85030
+ dataAttrs: run2.dataAttrs ? { ...run2.dataAttrs } : void 0,
85031
+ underline: run2.underline ? { ...run2.underline } : void 0,
85032
+ pageRefMetadata: run2.pageRefMetadata ? { ...run2.pageRefMetadata } : void 0
85033
+ });
85034
+ const normalized = runsForLine.map((run2) => {
85035
+ if (run2.kind !== "text" && run2.kind !== void 0 || !("text" in run2)) return run2;
85036
+ return cloneTextRun(run2);
85037
+ });
85038
+ const merged = [];
85039
+ for (let i2 = 0; i2 < normalized.length; i2 += 1) {
85040
+ const run2 = normalized[i2];
85041
+ if (run2.kind !== "text" && run2.kind !== void 0 || !("text" in run2)) {
85042
+ merged.push(run2);
85043
+ continue;
85044
+ }
85045
+ const textRun = run2;
85046
+ if (!isWhitespaceOnly(textRun.text ?? "")) {
85047
+ merged.push(textRun);
85048
+ continue;
85049
+ }
85050
+ const prev = merged[merged.length - 1];
85051
+ if (prev && (prev.kind === "text" || prev.kind === void 0) && "text" in prev) {
85052
+ const prevTextRun = prev;
85053
+ if (mergeSignature(prevTextRun) === mergeSignature(textRun)) {
85054
+ const extra = textRun.text ?? "";
85055
+ prevTextRun.text = (prevTextRun.text ?? "") + extra;
85056
+ if (prevTextRun.pmStart != null) {
85057
+ prevTextRun.pmEnd = prevTextRun.pmStart + prevTextRun.text.length;
85058
+ } else if (prevTextRun.pmEnd != null) {
85059
+ prevTextRun.pmEnd = prevTextRun.pmEnd + extra.length;
85060
+ }
85061
+ continue;
85062
+ }
85063
+ }
85064
+ const next2 = normalized[i2 + 1];
85065
+ if (next2 && (next2.kind === "text" || next2.kind === void 0) && "text" in next2) {
85066
+ const nextTextRun = next2;
85067
+ if (mergeSignature(nextTextRun) === mergeSignature(textRun)) {
85068
+ const extra = textRun.text ?? "";
85069
+ nextTextRun.text = extra + (nextTextRun.text ?? "");
85070
+ if (textRun.pmStart != null) {
85071
+ nextTextRun.pmStart = textRun.pmStart;
85072
+ } else if (nextTextRun.pmStart != null) {
85073
+ nextTextRun.pmStart = nextTextRun.pmStart - extra.length;
85074
+ }
85075
+ if (nextTextRun.pmStart != null && nextTextRun.pmEnd == null) {
85076
+ nextTextRun.pmEnd = nextTextRun.pmStart + nextTextRun.text.length;
85077
+ }
85078
+ continue;
85079
+ }
85080
+ }
85081
+ merged.push(textRun);
85082
+ }
85083
+ runsForLine = merged;
85084
+ const hasNonSpaceText = runsForLine.some(
85085
+ (run2) => (run2.kind === "text" || run2.kind === void 0) && "text" in run2 && (run2.text ?? "").trim().length > 0
85086
+ );
85087
+ if (hasNonSpaceText) {
85088
+ for (let i2 = runsForLine.length - 1; i2 >= 0; i2 -= 1) {
85089
+ const run2 = runsForLine[i2];
85090
+ if (run2.kind !== "text" && run2.kind !== void 0 || !("text" in run2)) continue;
85091
+ const text2 = run2.text ?? "";
85092
+ let trimCount = 0;
85093
+ for (let j2 = text2.length - 1; j2 >= 0 && text2[j2] === " "; j2 -= 1) {
85094
+ trimCount += 1;
85095
+ }
85096
+ if (trimCount === 0) break;
85097
+ const nextText = text2.slice(0, Math.max(0, text2.length - trimCount));
85098
+ if (nextText.length === 0) {
85099
+ runsForLine.splice(i2, 1);
85100
+ continue;
85101
+ }
85102
+ run2.text = nextText;
85103
+ if (run2.pmEnd != null) {
85104
+ run2.pmEnd = run2.pmEnd - trimCount;
85105
+ }
85106
+ break;
85107
+ }
85108
+ }
85109
+ }
85110
+ const spaceCount = line.spaceCount ?? runsForLine.reduce((sum, run2) => {
85111
+ if (run2.kind !== "text" && run2.kind !== void 0 || !("text" in run2) || run2.text == null) return sum;
85112
+ return sum + countSpaces2(run2.text);
85113
+ }, 0);
85114
+ const lineWidth = line.naturalWidth ?? line.width;
85115
+ const spacingPerSpace = calculateJustifySpacing({
85116
+ lineWidth,
85117
+ availableWidth,
85118
+ spaceCount,
85119
+ shouldJustify: justifyShouldApply
85120
+ });
85121
+ if (spacingPerSpace !== 0) {
85122
+ el.style.wordSpacing = `${spacingPerSpace}px`;
85123
+ }
84863
85124
  if (hasExplicitPositioning && line.segments) {
84864
85125
  const paraIndent = block.attrs?.indent;
84865
85126
  const indentLeft = paraIndent?.left ?? 0;
@@ -85731,7 +85992,7 @@ ${l}
85731
85992
  element2.setAttribute("styleid", attrs.styleId);
85732
85993
  }
85733
85994
  if (attrs.alignment) {
85734
- element2.style.textAlign = attrs.alignment;
85995
+ element2.style.textAlign = attrs.alignment === "justify" || attrs.alignment === "both" ? "left" : attrs.alignment;
85735
85996
  }
85736
85997
  if (attrs.dropCap) {
85737
85998
  element2.classList.add("sd-editor-dropcap");
@@ -85796,23 +86057,6 @@ ${l}
85796
86057
  if (!shading?.fill) return;
85797
86058
  element2.style.backgroundColor = shading.fill;
85798
86059
  };
85799
- const gatherTextSlicesForLine = (block, line) => {
85800
- const slices = [];
85801
- const startRun = line.fromRun ?? 0;
85802
- const endRun = line.toRun ?? startRun;
85803
- for (let runIndex = startRun; runIndex <= endRun; runIndex += 1) {
85804
- const run2 = block.runs[runIndex];
85805
- if (!run2 || run2.kind !== "text" && run2.kind !== void 0 || !("text" in run2) || !run2.text) continue;
85806
- const isFirst = runIndex === startRun;
85807
- const isLast = runIndex === endRun;
85808
- const start2 = isFirst ? line.fromChar ?? 0 : 0;
85809
- const end2 = isLast ? line.toChar ?? run2.text.length : run2.text.length;
85810
- if (start2 >= end2) continue;
85811
- const slice2 = run2.text.slice(start2, end2);
85812
- if (slice2) slices.push(slice2);
85813
- }
85814
- return slices;
85815
- };
85816
86060
  const sliceRunsForLine = (block, line) => {
85817
86061
  const result = [];
85818
86062
  for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
@@ -86434,7 +86678,8 @@ ${l}
86434
86678
  let indentAdjust = paraIndentLeft;
86435
86679
  if (isListItem2 && isFirstLine && isFirstLineIndentMode) {
86436
86680
  const textStartFallback = paraIndentLeft + Math.max(firstLineIndent, 0) + markerWidth;
86437
- indentAdjust = typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : textStartFallback;
86681
+ const markerTextStartX = wordLayout?.marker?.textStartX;
86682
+ indentAdjust = typeof markerTextStartX === "number" && Number.isFinite(markerTextStartX) ? markerTextStartX : typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : textStartFallback;
86438
86683
  } else if (isFirstLine && !isListItem2) {
86439
86684
  indentAdjust += firstLineOffset;
86440
86685
  }
@@ -87124,6 +87369,20 @@ ${l}
87124
87369
  }
87125
87370
  return value;
87126
87371
  };
87372
+ function calculateFirstLineIndent(block, measure) {
87373
+ const wordLayout = block.attrs?.wordLayout;
87374
+ if (!wordLayout?.firstLineIndentMode) {
87375
+ return 0;
87376
+ }
87377
+ if (!wordLayout.marker || !measure.marker) {
87378
+ return 0;
87379
+ }
87380
+ const markerWidthRaw = measure.marker.markerWidth ?? wordLayout.marker.markerBoxWidthPx ?? 0;
87381
+ const markerWidth = Number.isFinite(markerWidthRaw) && markerWidthRaw >= 0 ? markerWidthRaw : 0;
87382
+ const gutterWidthRaw = measure.marker.gutterWidth ?? 0;
87383
+ const gutterWidth = Number.isFinite(gutterWidthRaw) && gutterWidthRaw >= 0 ? gutterWidthRaw : 0;
87384
+ return markerWidth + gutterWidth;
87385
+ }
87127
87386
  function layoutParagraphBlock(ctx2, anchors) {
87128
87387
  const { block, measure, columnWidth, ensurePage, advanceColumn, columnX, floatManager } = ctx2;
87129
87388
  const remeasureParagraph2 = ctx2.remeasureParagraph;
@@ -87253,17 +87512,8 @@ ${l}
87253
87512
  const remeasureWidth = Math.max(1, columnWidth - indentLeft - indentRight);
87254
87513
  let didRemeasureForColumnWidth = false;
87255
87514
  if (typeof remeasureParagraph2 === "function" && typeof measurementWidth === "number" && measurementWidth > remeasureWidth) {
87256
- let firstLineIndent = 0;
87257
- const wordLayout = block.attrs?.wordLayout;
87258
- if (wordLayout?.marker && measure.marker) {
87259
- const markerJustification = wordLayout.marker.justification ?? "left";
87260
- if (markerJustification === "left") {
87261
- const markerWidth = measure.marker.markerWidth ?? 0;
87262
- const gutterWidth = measure.marker.gutterWidth ?? wordLayout.marker.gutterWidthPx ?? 0;
87263
- firstLineIndent = markerWidth + gutterWidth;
87264
- }
87265
- }
87266
- const newMeasure = remeasureParagraph2(block, remeasureWidth, firstLineIndent);
87515
+ const firstLineIndent = calculateFirstLineIndent(block, measure);
87516
+ const newMeasure = remeasureParagraph2(block, columnWidth, firstLineIndent);
87267
87517
  lines = normalizeLines(newMeasure);
87268
87518
  didRemeasureForColumnWidth = true;
87269
87519
  }
@@ -87344,16 +87594,7 @@ ${l}
87344
87594
  }
87345
87595
  const narrowestRemeasureWidth = Math.max(1, narrowestWidth - indentLeft - indentRight);
87346
87596
  if (narrowestRemeasureWidth < remeasureWidth) {
87347
- let firstLineIndent = 0;
87348
- const wordLayout = block.attrs?.wordLayout;
87349
- if (wordLayout?.marker && measure.marker) {
87350
- const markerJustification = wordLayout.marker.justification ?? "left";
87351
- if (markerJustification === "left") {
87352
- const markerWidth = measure.marker.markerWidth ?? 0;
87353
- const gutterWidth = measure.marker.gutterWidth ?? wordLayout.marker.gutterWidthPx ?? 0;
87354
- firstLineIndent = markerWidth + gutterWidth;
87355
- }
87356
- }
87597
+ const firstLineIndent = calculateFirstLineIndent(block, measure);
87357
87598
  const newMeasure = remeasureParagraph2(block, narrowestRemeasureWidth, firstLineIndent);
87358
87599
  lines = normalizeLines(newMeasure);
87359
87600
  didRemeasureForFloats = true;
@@ -90500,7 +90741,8 @@ ${l}
90500
90741
  const indentHanging = Math.max(0, indent2?.hanging ?? 0);
90501
90742
  const rawFirstLineOffset = Math.max(0, firstLineIndent || indentFirstLine - indentHanging);
90502
90743
  const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
90503
- const textStartPx = wordLayout?.textStartPx;
90744
+ const markerTextStartX = wordLayout?.marker?.textStartX;
90745
+ const textStartPx = typeof markerTextStartX === "number" && Number.isFinite(markerTextStartX) ? markerTextStartX : typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : void 0;
90504
90746
  const treatAsHanging = textStartPx && indentLeft === 0 && indentHanging === 0;
90505
90747
  const firstLineWidth = typeof textStartPx === "number" && textStartPx > indentLeft && !treatAsHanging ? Math.max(1, maxWidth - textStartPx - indentRight) : Math.max(1, contentWidth - rawFirstLineOffset);
90506
90748
  const tabStops = buildTabStopsPx$1(indent2, attrs?.tabs, attrs?.tabIntervalTwips);
@@ -90512,6 +90754,7 @@ ${l}
90512
90754
  const startRun = currentRun;
90513
90755
  const startChar = currentChar;
90514
90756
  let width = 0;
90757
+ let widthAtLastBreak = -1;
90515
90758
  let lastBreakRun = -1;
90516
90759
  let lastBreakChar = -1;
90517
90760
  let endRun = currentRun;
@@ -90529,6 +90772,7 @@ ${l}
90529
90772
  endChar = 1;
90530
90773
  lastBreakRun = r2;
90531
90774
  lastBreakChar = 1;
90775
+ widthAtLastBreak = width;
90532
90776
  continue;
90533
90777
  }
90534
90778
  const text2 = runText(run2);
@@ -90539,6 +90783,7 @@ ${l}
90539
90783
  if (lastBreakRun >= 0) {
90540
90784
  endRun = lastBreakRun;
90541
90785
  endChar = lastBreakChar;
90786
+ width = widthAtLastBreak >= 0 ? widthAtLastBreak : width;
90542
90787
  } else {
90543
90788
  endRun = r2;
90544
90789
  endChar = c2;
@@ -90553,6 +90798,7 @@ ${l}
90553
90798
  if (ch === " " || ch === " " || ch === "-") {
90554
90799
  lastBreakRun = r2;
90555
90800
  lastBreakChar = c2 + 1;
90801
+ widthAtLastBreak = width;
90556
90802
  }
90557
90803
  }
90558
90804
  if (didBreakInThisLine) break;
@@ -92263,7 +92509,9 @@ ${l}
92263
92509
  }
92264
92510
  const markerWidth = fragment.markerWidth ?? measure.marker?.markerWidth ?? 0;
92265
92511
  const isListItem3 = markerWidth > 0;
92266
- const alignmentOverride = isListItem3 ? "left" : void 0;
92512
+ const paraAlignment = block.attrs?.alignment;
92513
+ const isJustified = paraAlignment === "justify" || paraAlignment === "both";
92514
+ const alignmentOverride = isListItem3 && !isJustified ? "left" : void 0;
92267
92515
  const pos = mapPointToPm(block, line, pageRelativePoint.x - fragment.x, isRTL, availableWidth, alignmentOverride);
92268
92516
  if (pos == null) {
92269
92517
  logClickStage("warn", "no-position", {
@@ -92330,7 +92578,9 @@ ${l}
92330
92578
  }
92331
92579
  const cellMarkerWidth = cellMeasure.marker?.markerWidth ?? 0;
92332
92580
  const isListItem3 = cellMarkerWidth > 0;
92333
- const alignmentOverride = isListItem3 ? "left" : void 0;
92581
+ const cellAlignment = cellBlock.attrs?.alignment;
92582
+ const isJustified = cellAlignment === "justify" || cellAlignment === "both";
92583
+ const alignmentOverride = isListItem3 && !isJustified ? "left" : void 0;
92334
92584
  const pos = mapPointToPm(cellBlock, line, localX, isRTL, availableWidth, alignmentOverride);
92335
92585
  if (pos != null) {
92336
92586
  logClickStage("log", "success", {
@@ -92499,7 +92749,9 @@ ${l}
92499
92749
  const charOffsetTo = pmPosToCharOffset(block, line, sliceTo);
92500
92750
  const markerWidth = fragment.markerWidth ?? measure.marker?.markerWidth ?? 0;
92501
92751
  const isListItemFlag = isListItem(markerWidth, block);
92502
- const alignmentOverride = isListItemFlag ? "left" : void 0;
92752
+ const blockAlignment = block.attrs?.alignment;
92753
+ const isJustified = blockAlignment === "justify" || blockAlignment === "both";
92754
+ const alignmentOverride = isListItemFlag && !isJustified ? "left" : void 0;
92503
92755
  const startX = mapPmToX(block, line, charOffsetFrom, fragment.width, alignmentOverride);
92504
92756
  const endX = mapPmToX(block, line, charOffsetTo, fragment.width, alignmentOverride);
92505
92757
  const indent2 = extractParagraphIndent(block.attrs?.indent);
@@ -93241,7 +93493,9 @@ ${l}
93241
93493
  const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
93242
93494
  const bodyContentWidth = contentWidth;
93243
93495
  let initialAvailableWidth;
93244
- const textStartPx = wordLayout?.textStartPx;
93496
+ const rawTextStartPx = wordLayout?.textStartPx;
93497
+ const markerTextStartX = wordLayout?.marker?.textStartX;
93498
+ const textStartPx = typeof markerTextStartX === "number" && Number.isFinite(markerTextStartX) ? markerTextStartX : typeof rawTextStartPx === "number" && Number.isFinite(rawTextStartPx) ? rawTextStartPx : void 0;
93245
93499
  if (typeof textStartPx === "number" && textStartPx > indentLeft) {
93246
93500
  initialAvailableWidth = Math.max(1, maxWidth - textStartPx - indentRight);
93247
93501
  } else {
@@ -93376,12 +93630,40 @@ ${l}
93376
93630
  runsToProcess.push(run2);
93377
93631
  }
93378
93632
  }
93633
+ const trimTrailingWrapSpaces = (lineToTrim) => {
93634
+ const lastRun = runsToProcess[lineToTrim.toRun];
93635
+ if (!lastRun || !("text" in lastRun) || typeof lastRun.text !== "string") return;
93636
+ const sliceStart = lineToTrim.toRun === lineToTrim.fromRun ? lineToTrim.fromChar : 0;
93637
+ const sliceEnd = lineToTrim.toChar;
93638
+ if (sliceEnd <= sliceStart) return;
93639
+ const sliceText = lastRun.text.slice(sliceStart, sliceEnd);
93640
+ let trimCount = 0;
93641
+ for (let i2 = sliceText.length - 1; i2 >= 0 && sliceText[i2] === " "; i2 -= 1) {
93642
+ trimCount += 1;
93643
+ }
93644
+ if (trimCount === 0) return;
93645
+ if (lineToTrim.fromRun === lineToTrim.toRun && sliceText.trim().length === 0) {
93646
+ return;
93647
+ }
93648
+ const keptText = sliceText.slice(0, Math.max(0, sliceText.length - trimCount));
93649
+ const { font } = buildFontString(
93650
+ lastRun
93651
+ );
93652
+ const fullWidth = measureRunWidth(sliceText, font, ctx2, lastRun);
93653
+ const keptWidth = keptText.length > 0 ? measureRunWidth(keptText, font, ctx2, lastRun) : 0;
93654
+ const delta = Math.max(0, fullWidth - keptWidth);
93655
+ lineToTrim.width = roundValue(Math.max(0, lineToTrim.width - delta));
93656
+ lineToTrim.spaceCount = Math.max(0, lineToTrim.spaceCount - trimCount);
93657
+ if (lineToTrim.naturalWidth != null && typeof lineToTrim.naturalWidth === "number") {
93658
+ lineToTrim.naturalWidth = roundValue(Math.max(0, lineToTrim.naturalWidth - delta));
93659
+ }
93660
+ };
93379
93661
  for (let runIndex = 0; runIndex < runsToProcess.length; runIndex++) {
93380
93662
  const run2 = runsToProcess[runIndex];
93381
93663
  if (run2.kind === "break") {
93382
93664
  if (currentLine) {
93383
93665
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
93384
- const { spaceCount: _sc, ...lineBase } = currentLine;
93666
+ const lineBase = currentLine;
93385
93667
  const completedLine = { ...lineBase, ...metrics };
93386
93668
  addBarTabsToLine(completedLine);
93387
93669
  lines.push(completedLine);
@@ -93426,7 +93708,7 @@ ${l}
93426
93708
  toRun: runIndex,
93427
93709
  toChar: 0,
93428
93710
  width: 0,
93429
- maxWidth: getEffectiveWidth(initialAvailableWidth),
93711
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
93430
93712
  segments: [],
93431
93713
  ...metrics
93432
93714
  };
@@ -93461,7 +93743,7 @@ ${l}
93461
93743
  width: 0,
93462
93744
  maxFontSize: 12,
93463
93745
  // Default font size for tabs
93464
- maxWidth: getEffectiveWidth(initialAvailableWidth),
93746
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
93465
93747
  segments: [],
93466
93748
  spaceCount: 0
93467
93749
  };
@@ -93511,7 +93793,7 @@ ${l}
93511
93793
  width: imageWidth,
93512
93794
  maxFontSize: imageHeight,
93513
93795
  // Use image height for line height calculation
93514
- maxWidth: getEffectiveWidth(initialAvailableWidth),
93796
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
93515
93797
  spaceCount: 0,
93516
93798
  segments: [
93517
93799
  {
@@ -93527,8 +93809,9 @@ ${l}
93527
93809
  }
93528
93810
  const appliedTabAlign = lastAppliedTabAlign;
93529
93811
  if (currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
93812
+ trimTrailingWrapSpaces(currentLine);
93530
93813
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
93531
- const { spaceCount: _sc, ...lineBase } = currentLine;
93814
+ const lineBase = currentLine;
93532
93815
  const completedLine = {
93533
93816
  ...lineBase,
93534
93817
  ...metrics
@@ -93601,7 +93884,7 @@ ${l}
93601
93884
  // Field annotations are atomic units
93602
93885
  width: annotationWidth,
93603
93886
  maxFontSize: annotationHeight,
93604
- maxWidth: getEffectiveWidth(initialAvailableWidth),
93887
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
93605
93888
  spaceCount: 0,
93606
93889
  segments: [
93607
93890
  {
@@ -93616,8 +93899,9 @@ ${l}
93616
93899
  continue;
93617
93900
  }
93618
93901
  if (currentLine.width + annotationWidth > currentLine.maxWidth && currentLine.width > 0) {
93902
+ trimTrailingWrapSpaces(currentLine);
93619
93903
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
93620
- const { spaceCount: _sc, ...lineBase } = currentLine;
93904
+ const lineBase = currentLine;
93621
93905
  const completedLine = {
93622
93906
  ...lineBase,
93623
93907
  ...metrics
@@ -93690,15 +93974,16 @@ ${l}
93690
93974
  width: spacesWidth,
93691
93975
  maxFontSize: run2.fontSize,
93692
93976
  maxFontInfo: getFontInfoFromRun(run2),
93693
- maxWidth: getEffectiveWidth(initialAvailableWidth),
93977
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
93694
93978
  segments: [{ runIndex, fromChar: spacesStartChar, toChar: spacesEndChar, width: spacesWidth }],
93695
93979
  spaceCount: spacesLength
93696
93980
  };
93697
93981
  } else {
93698
93982
  const boundarySpacing = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
93699
93983
  if (currentLine.width + boundarySpacing + spacesWidth > currentLine.maxWidth - WIDTH_FUDGE_PX2 && currentLine.width > 0) {
93984
+ trimTrailingWrapSpaces(currentLine);
93700
93985
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
93701
- const { spaceCount: _sc, ...lineBase } = currentLine;
93986
+ const lineBase = currentLine;
93702
93987
  const completedLine = {
93703
93988
  ...lineBase,
93704
93989
  ...metrics
@@ -93734,6 +94019,13 @@ ${l}
93734
94019
  continue;
93735
94020
  }
93736
94021
  const words = segment.split(" ");
94022
+ let lastNonEmptyWordIndex = -1;
94023
+ for (let i2 = words.length - 1; i2 >= 0; i2 -= 1) {
94024
+ if (words[i2] !== "") {
94025
+ lastNonEmptyWordIndex = i2;
94026
+ break;
94027
+ }
94028
+ }
93737
94029
  let segmentStartX;
93738
94030
  if (currentLine && pendingTabAlignment) {
93739
94031
  segmentStartX = alignSegmentAtTab(segment, font, run2);
@@ -93756,15 +94048,16 @@ ${l}
93756
94048
  width: singleSpaceWidth,
93757
94049
  maxFontSize: run2.fontSize,
93758
94050
  maxFontInfo: getFontInfoFromRun(run2),
93759
- maxWidth: getEffectiveWidth(initialAvailableWidth),
94051
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
93760
94052
  segments: [{ runIndex, fromChar: spaceStartChar, toChar: spaceEndChar, width: singleSpaceWidth }],
93761
94053
  spaceCount: 1
93762
94054
  };
93763
94055
  } else {
93764
94056
  const boundarySpacing2 = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
93765
94057
  if (currentLine.width + boundarySpacing2 + singleSpaceWidth > currentLine.maxWidth - WIDTH_FUDGE_PX2 && currentLine.width > 0) {
94058
+ trimTrailingWrapSpaces(currentLine);
93766
94059
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
93767
- const { spaceCount: _sc, ...lineBase } = currentLine;
94060
+ const lineBase = currentLine;
93768
94061
  const completedLine = { ...lineBase, ...metrics };
93769
94062
  addBarTabsToLine(completedLine);
93770
94063
  lines.push(completedLine);
@@ -93796,19 +94089,19 @@ ${l}
93796
94089
  charPosInRun = spaceEndChar;
93797
94090
  continue;
93798
94091
  }
93799
- const isLastWordInSegment = wordIndex === words.length - 1;
93800
- const isLastWord = isLastWordInSegment && isLastSegment;
93801
94092
  const wordOnlyWidth = measureRunWidth(word, font, ctx2, run2);
93802
- const spaceWidth = isLastWord ? 0 : measureRunWidth(" ", font, ctx2, run2);
93803
- const wordCommitWidth = isLastWord ? wordOnlyWidth : wordOnlyWidth + spaceWidth;
94093
+ const shouldIncludeDelimiterSpace = wordIndex < lastNonEmptyWordIndex;
94094
+ const spaceWidth = shouldIncludeDelimiterSpace ? measureRunWidth(" ", font, ctx2, run2) : 0;
94095
+ const wordCommitWidth = wordOnlyWidth + spaceWidth;
93804
94096
  const wordStartChar = charPosInRun;
93805
94097
  const wordEndNoSpace = charPosInRun + word.length;
93806
- const wordEndWithSpace = charPosInRun + (isLastWord ? word.length : word.length + 1);
94098
+ const wordEndWithSpace = wordEndNoSpace + (shouldIncludeDelimiterSpace ? 1 : 0);
93807
94099
  const effectiveMaxWidth = currentLine ? currentLine.maxWidth : getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : contentWidth);
93808
94100
  if (wordOnlyWidth > effectiveMaxWidth && word.length > 1) {
93809
94101
  if (currentLine && currentLine.width > 0 && currentLine.segments && currentLine.segments.length > 0) {
94102
+ trimTrailingWrapSpaces(currentLine);
93810
94103
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
93811
- const { spaceCount: _sc, ...lineBase } = currentLine;
94104
+ const lineBase = currentLine;
93812
94105
  const completedLine = { ...lineBase, ...metrics };
93813
94106
  addBarTabsToLine(completedLine);
93814
94107
  lines.push(completedLine);
@@ -93842,7 +94135,7 @@ ${l}
93842
94135
  });
93843
94136
  if (isLastChunk) {
93844
94137
  const ls = run2.letterSpacing ?? 0;
93845
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
94138
+ if (shouldIncludeDelimiterSpace && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
93846
94139
  currentLine.toChar = wordEndWithSpace;
93847
94140
  currentLine.width = roundValue(currentLine.width + spaceWidth + ls);
93848
94141
  charPosInRun = wordEndWithSpace;
@@ -93851,8 +94144,9 @@ ${l}
93851
94144
  charPosInRun = wordEndWithSpace;
93852
94145
  }
93853
94146
  } else {
94147
+ trimTrailingWrapSpaces(currentLine);
93854
94148
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
93855
- const { spaceCount: _sc, ...lineBase } = currentLine;
94149
+ const lineBase = currentLine;
93856
94150
  const completedLine = { ...lineBase, ...metrics };
93857
94151
  addBarTabsToLine(completedLine);
93858
94152
  lines.push(completedLine);
@@ -93874,7 +94168,7 @@ ${l}
93874
94168
  spaceCount: 0
93875
94169
  };
93876
94170
  const ls = run2.letterSpacing ?? 0;
93877
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
94171
+ if (shouldIncludeDelimiterSpace && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
93878
94172
  currentLine.toChar = wordEndWithSpace;
93879
94173
  currentLine.width = roundValue(currentLine.width + spaceWidth + ls);
93880
94174
  charPosInRun = wordEndWithSpace;
@@ -93911,12 +94205,12 @@ ${l}
93911
94205
  width: wordOnlyWidth,
93912
94206
  maxFontSize: run2.fontSize,
93913
94207
  maxFontInfo: getFontInfoFromRun(run2),
93914
- maxWidth: getEffectiveWidth(initialAvailableWidth),
94208
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
93915
94209
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }],
93916
94210
  spaceCount: 0
93917
94211
  };
93918
94212
  const ls = run2.letterSpacing ?? 0;
93919
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
94213
+ if (shouldIncludeDelimiterSpace && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
93920
94214
  currentLine.toChar = wordEndWithSpace;
93921
94215
  currentLine.width = roundValue(currentLine.width + spaceWidth + ls);
93922
94216
  charPosInRun = wordEndWithSpace;
@@ -93930,15 +94224,16 @@ ${l}
93930
94224
  const boundarySpacing = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
93931
94225
  const justifyAlignment = block.attrs?.alignment === "justify";
93932
94226
  const totalWidthWithWord = currentLine.width + boundarySpacing + wordCommitWidth + // Safe cast: only TextRuns produce word segments from split(), other run types are handled earlier
93933
- (isLastWord ? 0 : run2.letterSpacing ?? 0);
94227
+ (shouldIncludeDelimiterSpace ? run2.letterSpacing ?? 0 : 0);
93934
94228
  const availableWidth = currentLine.maxWidth - WIDTH_FUDGE_PX2;
93935
94229
  let shouldBreak = currentLine.width + boundarySpacing + wordOnlyWidth > availableWidth && currentLine.width > 0 && !isTocEntry;
93936
94230
  let compressedWidth = null;
93937
94231
  if (shouldBreak && justifyAlignment) {
93938
- const isParagraphLastWord = isLastWord && runIndex === runsToProcess.length - 1;
94232
+ const isLastNonEmptyWordInSegment = wordIndex === lastNonEmptyWordIndex;
94233
+ const isParagraphLastWord = isLastSegment && isLastNonEmptyWordInSegment && runIndex === runsToProcess.length - 1;
93939
94234
  if (!isParagraphLastWord) {
93940
94235
  const existingSpaces = currentLine.spaceCount ?? 0;
93941
- const candidateSpaces = existingSpaces + (isLastWord ? 0 : 1);
94236
+ const candidateSpaces = existingSpaces + (shouldIncludeDelimiterSpace ? 1 : 0);
93942
94237
  if (candidateSpaces > 0) {
93943
94238
  const overflow = totalWidthWithWord - availableWidth;
93944
94239
  if (overflow > 0) {
@@ -93954,8 +94249,9 @@ ${l}
93954
94249
  }
93955
94250
  }
93956
94251
  if (shouldBreak) {
94252
+ trimTrailingWrapSpaces(currentLine);
93957
94253
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
93958
- const { spaceCount: _sc, ...lineBase } = currentLine;
94254
+ const lineBase = currentLine;
93959
94255
  const completedLine = {
93960
94256
  ...lineBase,
93961
94257
  ...metrics
@@ -93976,7 +94272,7 @@ ${l}
93976
94272
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }],
93977
94273
  spaceCount: 0
93978
94274
  };
93979
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
94275
+ if (shouldIncludeDelimiterSpace && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
93980
94276
  currentLine.toChar = wordEndWithSpace;
93981
94277
  currentLine.width = roundValue(currentLine.width + spaceWidth + (run2.letterSpacing ?? 0));
93982
94278
  charPosInRun = wordEndWithSpace;
@@ -93986,7 +94282,7 @@ ${l}
93986
94282
  }
93987
94283
  } else {
93988
94284
  currentLine.toRun = runIndex;
93989
- if (!isLastWord && currentLine.width + boundarySpacing + wordOnlyWidth + spaceWidth > currentLine.maxWidth - WIDTH_FUDGE_PX2) {
94285
+ if (shouldIncludeDelimiterSpace && currentLine.width + boundarySpacing + wordOnlyWidth + spaceWidth > currentLine.maxWidth - WIDTH_FUDGE_PX2) {
93990
94286
  currentLine.toChar = wordEndNoSpace;
93991
94287
  currentLine.width = roundValue(currentLine.width + boundarySpacing + wordOnlyWidth);
93992
94288
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run2);
@@ -94000,8 +94296,9 @@ ${l}
94000
94296
  wordOnlyWidth,
94001
94297
  useExplicitXHere ? segmentStartX : void 0
94002
94298
  );
94299
+ trimTrailingWrapSpaces(currentLine);
94003
94300
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
94004
- const { spaceCount: _sc, ...lineBase } = currentLine;
94301
+ const lineBase = currentLine;
94005
94302
  const completedLine = { ...lineBase, ...metrics };
94006
94303
  addBarTabsToLine(completedLine);
94007
94304
  lines.push(completedLine);
@@ -94011,20 +94308,23 @@ ${l}
94011
94308
  charPosInRun = wordEndNoSpace + 1;
94012
94309
  continue;
94013
94310
  }
94014
- const newToChar = isLastWord ? wordEndNoSpace : wordEndWithSpace;
94311
+ const newToChar = shouldIncludeDelimiterSpace ? wordEndWithSpace : wordEndNoSpace;
94015
94312
  currentLine.toChar = newToChar;
94016
94313
  const useExplicitX = wordIndex === 0 && segmentStartX !== void 0;
94017
94314
  const explicitX = useExplicitX ? segmentStartX : void 0;
94018
- const targetWidth = compressedWidth != null ? compressedWidth : currentLine.width + boundarySpacing + wordCommitWidth + (isLastWord ? 0 : run2.letterSpacing ?? 0);
94315
+ const targetWidth = compressedWidth != null ? compressedWidth : currentLine.width + boundarySpacing + wordCommitWidth + (shouldIncludeDelimiterSpace ? run2.letterSpacing ?? 0 : 0);
94316
+ if (compressedWidth != null) {
94317
+ currentLine.naturalWidth = roundValue(totalWidthWithWord);
94318
+ }
94019
94319
  currentLine.width = roundValue(targetWidth);
94020
94320
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run2);
94021
94321
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run2.fontSize);
94022
94322
  appendSegment(currentLine.segments, runIndex, wordStartChar, newToChar, wordCommitWidth, explicitX);
94023
- if (!isLastWord) {
94323
+ if (shouldIncludeDelimiterSpace) {
94024
94324
  currentLine.spaceCount += 1;
94025
94325
  }
94026
94326
  }
94027
- charPosInRun = isLastWord ? wordEndNoSpace : wordEndWithSpace;
94327
+ charPosInRun = shouldIncludeDelimiterSpace ? wordEndWithSpace : wordEndNoSpace;
94028
94328
  }
94029
94329
  if (lastAppliedTabAlign && currentLine) {
94030
94330
  const appliedTab = lastAppliedTabAlign;
@@ -94044,7 +94344,7 @@ ${l}
94044
94344
  width: 0,
94045
94345
  maxFontSize: run2.fontSize,
94046
94346
  maxFontInfo: getFontInfoFromRun(run2),
94047
- maxWidth: getEffectiveWidth(initialAvailableWidth),
94347
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
94048
94348
  segments: [],
94049
94349
  spaceCount: 0
94050
94350
  };
@@ -94092,7 +94392,7 @@ ${l}
94092
94392
  }
94093
94393
  if (currentLine) {
94094
94394
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
94095
- const { spaceCount: _sc, ...lineBase } = currentLine;
94395
+ const lineBase = currentLine;
94096
94396
  const finalLine = {
94097
94397
  ...lineBase,
94098
94398
  ...metrics
@@ -151830,7 +152130,8 @@ ${style2}
151830
152130
  measurementTimeoutId.value = null;
151831
152131
  }
151832
152132
  const totalComments = getFloatingComments.value.length;
151833
- if (totalComments === 0) {
152133
+ const measuredComments = renderedSizes.value.length;
152134
+ if (totalComments === 0 || measuredComments === 0) {
151834
152135
  return;
151835
152136
  }
151836
152137
  nextTick(processLocations);
@@ -151911,7 +152212,7 @@ ${style2}
151911
152212
  };
151912
152213
  }
151913
152214
  };
151914
- const FloatingComments = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-6905dd07"]]);
152215
+ const FloatingComments = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-1402ce8c"]]);
151915
152216
  const _sfc_main$9 = {
151916
152217
  __name: "TextField",
151917
152218
  props: {
@@ -153443,7 +153744,7 @@ ${style2}
153443
153744
  this.config.colors = shuffleArray(this.config.colors);
153444
153745
  this.userColorMap = /* @__PURE__ */ new Map();
153445
153746
  this.colorIndex = 0;
153446
- this.version = "1.0.0-next.3";
153747
+ this.version = "1.0.0-next.5";
153447
153748
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
153448
153749
  this.superdocId = config2.superdocId || v4();
153449
153750
  this.colors = this.config.colors;
@@ -155916,7 +156217,7 @@ ${style2}
155916
156217
  value && typeof value === "object" && "byteLength" in value && "byteOffset" in value
155917
156218
  );
155918
156219
  }
155919
- const indexDLOSgUP = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
156220
+ const indexBUoOdDUj = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
155920
156221
  __proto__: null,
155921
156222
  unified
155922
156223
  }, Symbol.toStringTag, { value: "Module" }));