@harbour-enterprises/superdoc 1.3.0-next.4 → 1.3.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.
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const vue = require("./vue-De9wkgLl.cjs");
4
- const superdoc = require("./index-Dtd_PFUu.cjs");
5
- const index = require("./index-Buh63pW6.cjs");
4
+ const superdoc = require("./index-79lZpkMi.cjs");
5
+ const index = require("./index-BHIGTNEQ.cjs");
6
6
  function self(vars) {
7
7
  const {
8
8
  opacityDisabled,
@@ -1,6 +1,6 @@
1
1
  import { d as defineComponent, h, T as Transition, p as process$1, w as watchEffect, c as computed, r as ref, f as onMounted, X as onUnmounted, E as createElementBlock, G as openBlock, K as createBaseVNode, M as createCommentVNode, I as createVNode, v as unref } from "./vue-BnBKJwCW.es.js";
2
- import { N as NBaseLoading, u as useSuperdocStore, s as storeToRefs, a as useSelection } from "./index-CiR7cacp.es.js";
3
- import { C as derived, r as c, q as cB, aF as fadeInTransition, y as cM, I as warnOnce, J as useConfig, N as useTheme, aG as pxfy, P as createKey, Q as useThemeClass, aH as useCompitable, ai as _export_sfc } from "./index-BgcNLeK9.es.js";
2
+ import { N as NBaseLoading, u as useSuperdocStore, s as storeToRefs, a as useSelection } from "./index-B697vddF.es.js";
3
+ import { C as derived, r as c, q as cB, aF as fadeInTransition, y as cM, I as warnOnce, J as useConfig, N as useTheme, aG as pxfy, P as createKey, Q as useThemeClass, aH as useCompitable, ai as _export_sfc } from "./index-BSxlafD_.es.js";
4
4
  function self(vars) {
5
5
  const {
6
6
  opacityDisabled,
@@ -30938,7 +30938,7 @@ class SuperConverter {
30938
30938
  static getStoredSuperdocVersion(docx) {
30939
30939
  return SuperConverter.getStoredCustomProperty(docx, "SuperdocVersion");
30940
30940
  }
30941
- static setStoredSuperdocVersion(docx = this.convertedXml, version = "1.3.0-next.4") {
30941
+ static setStoredSuperdocVersion(docx = this.convertedXml, version = "1.3.0-next.5") {
30942
30942
  return SuperConverter.setStoredCustomProperty(docx, "SuperdocVersion", version, false);
30943
30943
  }
30944
30944
  /**
@@ -30939,7 +30939,7 @@ class SuperConverter {
30939
30939
  static getStoredSuperdocVersion(docx) {
30940
30940
  return SuperConverter.getStoredCustomProperty(docx, "SuperdocVersion");
30941
30941
  }
30942
- static setStoredSuperdocVersion(docx = this.convertedXml, version = "1.3.0-next.4") {
30942
+ static setStoredSuperdocVersion(docx = this.convertedXml, version = "1.3.0-next.5") {
30943
30943
  return SuperConverter.setStoredCustomProperty(docx, "SuperdocVersion", version, false);
30944
30944
  }
30945
30945
  /**
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
- const index = require("./index-Buh63pW6.cjs");
3
- require("./SuperConverter-qB6m0K1X.cjs");
2
+ const index = require("./index-BHIGTNEQ.cjs");
3
+ require("./SuperConverter-tcg6NQjY.cjs");
4
4
  const blankDocx = require("./blank-docx-DfW3Eeh2.cjs");
5
5
  const eventemitter3 = require("./eventemitter3-BQuRcMPI.cjs");
6
6
  const provider = require("@hocuspocus/provider");
@@ -7461,7 +7461,7 @@ const _sfc_main = {
7461
7461
  __name: "SuperDoc",
7462
7462
  emits: ["selection-update"],
7463
7463
  setup(__props, { emit: __emit }) {
7464
- const PdfViewer = vue.defineAsyncComponent(() => Promise.resolve().then(() => require("./PdfViewer-DkzZlntQ.cjs")));
7464
+ const PdfViewer = vue.defineAsyncComponent(() => Promise.resolve().then(() => require("./PdfViewer-CvoctNPw.cjs")));
7465
7465
  const superdocStore = useSuperdocStore();
7466
7466
  const commentsStore = useCommentsStore();
7467
7467
  const {
@@ -8367,7 +8367,7 @@ class SuperDoc extends eventemitter3.EventEmitter {
8367
8367
  this.config.colors = shuffleArray(this.config.colors);
8368
8368
  this.userColorMap = /* @__PURE__ */ new Map();
8369
8369
  this.colorIndex = 0;
8370
- this.version = "1.3.0-next.4";
8370
+ this.version = "1.3.0-next.5";
8371
8371
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
8372
8372
  this.superdocId = config.superdocId || uuid.v4();
8373
8373
  this.colors = this.config.colors;
@@ -1,5 +1,5 @@
1
- import { B as BIT8, M as MAX_SAFE_INTEGER, c as create, a as BITS7, u as utf8TextDecoder, b as create$1, s as setIfUndefined, d as create$2, f as from, e as floor$1, g as equalityDeep, w as writeVarUint, h as writeVarString, t as toUint8Array, i as createEncoder, j as createInjectionKey, k as toString, l as throwError, m as useSsrAdapter, n as configProviderInjectionKey, o as cssrAnchorMetaName, p as globalStyle, q as cB, r as c, v as isMounted, x as commonVariables$2, y as cM, z as cNotM, A as cE, C as derived, D as changeColor, E as insideModal, F as insidePopover, G as resolveWrappedSlot, H as on, I as warnOnce, J as useConfig, K as useMergedState, L as useMemo, N as useTheme, O as useRtl, P as createKey, Q as useThemeClass, R as createId, S as call, T as render, U as messageProviderInjectionKey, V as messageApiInjectionKey, W as fromBase64, X as onChange, Y as varStorage, Z as toBase64, _ as createUint8ArrayFromArrayBuffer, $ as offChange, a0 as writeVarUint8Array, a1 as map, a2 as length, a3 as isNode, a4 as min, a5 as pow, a6 as comments_module_events, a7 as getFileObject, a8 as getTrackChanges, a9 as CommentsPluginKey, aa as TrackChangesBasePluginKey, ab as Editor, ac as getRichTextExtensions, ad as ellipsisVerticalSvg, ae as xmarkIconSvg, af as checkIconSvg, ag as caretDownIconSvg, ah as commentIconSvg, ai as _export_sfc, aj as NDropdown, ak as SuperInput, al as vClickOutside, am as PresentationEditor, an as SuperEditor, ao as AIWriter, ap as NConfigProvider, aq as SuperToolbar } from "./index-BgcNLeK9.es.js";
2
- import "./SuperConverter-D62X6P1R.es.js";
1
+ import { B as BIT8, M as MAX_SAFE_INTEGER, c as create, a as BITS7, u as utf8TextDecoder, b as create$1, s as setIfUndefined, d as create$2, f as from, e as floor$1, g as equalityDeep, w as writeVarUint, h as writeVarString, t as toUint8Array, i as createEncoder, j as createInjectionKey, k as toString, l as throwError, m as useSsrAdapter, n as configProviderInjectionKey, o as cssrAnchorMetaName, p as globalStyle, q as cB, r as c, v as isMounted, x as commonVariables$2, y as cM, z as cNotM, A as cE, C as derived, D as changeColor, E as insideModal, F as insidePopover, G as resolveWrappedSlot, H as on, I as warnOnce, J as useConfig, K as useMergedState, L as useMemo, N as useTheme, O as useRtl, P as createKey, Q as useThemeClass, R as createId, S as call, T as render, U as messageProviderInjectionKey, V as messageApiInjectionKey, W as fromBase64, X as onChange, Y as varStorage, Z as toBase64, _ as createUint8ArrayFromArrayBuffer, $ as offChange, a0 as writeVarUint8Array, a1 as map, a2 as length, a3 as isNode, a4 as min, a5 as pow, a6 as comments_module_events, a7 as getFileObject, a8 as getTrackChanges, a9 as CommentsPluginKey, aa as TrackChangesBasePluginKey, ab as Editor, ac as getRichTextExtensions, ad as ellipsisVerticalSvg, ae as xmarkIconSvg, af as checkIconSvg, ag as caretDownIconSvg, ah as commentIconSvg, ai as _export_sfc, aj as NDropdown, ak as SuperInput, al as vClickOutside, am as PresentationEditor, an as SuperEditor, ao as AIWriter, ap as NConfigProvider, aq as SuperToolbar } from "./index-BSxlafD_.es.js";
2
+ import "./SuperConverter-DMbipzpl.es.js";
3
3
  import { B as BlankDOCX } from "./blank-docx-ABm6XYAA.es.js";
4
4
  import { E as EventEmitter } from "./eventemitter3-CwrdEv8r.es.js";
5
5
  import { HocuspocusProvider, HocuspocusProviderWebsocket } from "@hocuspocus/provider";
@@ -7444,7 +7444,7 @@ const _sfc_main = {
7444
7444
  __name: "SuperDoc",
7445
7445
  emits: ["selection-update"],
7446
7446
  setup(__props, { emit: __emit }) {
7447
- const PdfViewer = defineAsyncComponent(() => import("./PdfViewer-BT0Whwl-.es.js"));
7447
+ const PdfViewer = defineAsyncComponent(() => import("./PdfViewer-Dbc_J_1L.es.js"));
7448
7448
  const superdocStore = useSuperdocStore();
7449
7449
  const commentsStore = useCommentsStore();
7450
7450
  const {
@@ -8350,7 +8350,7 @@ class SuperDoc extends EventEmitter {
8350
8350
  this.config.colors = shuffleArray(this.config.colors);
8351
8351
  this.userColorMap = /* @__PURE__ */ new Map();
8352
8352
  this.colorIndex = 0;
8353
- this.version = "1.3.0-next.4";
8353
+ this.version = "1.3.0-next.5";
8354
8354
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
8355
8355
  this.superdocId = config.superdocId || v4();
8356
8356
  this.colors = this.config.colors;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  const jszip = require("./jszip-C8_CqJxM.cjs");
3
3
  const helpers$1 = require("./helpers-nOdwpmwb.cjs");
4
- const superEditor_converter = require("./SuperConverter-qB6m0K1X.cjs");
4
+ const superEditor_converter = require("./SuperConverter-tcg6NQjY.cjs");
5
5
  const vue = require("./vue-De9wkgLl.cjs");
6
6
  require("./jszip.min-BPh2MMAa.cjs");
7
7
  const eventemitter3 = require("./eventemitter3-BQuRcMPI.cjs");
@@ -15351,7 +15351,7 @@ const canUseDOM = () => {
15351
15351
  return false;
15352
15352
  }
15353
15353
  };
15354
- const summaryVersion = "1.3.0-next.4";
15354
+ const summaryVersion = "1.3.0-next.5";
15355
15355
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
15356
15356
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
15357
15357
  function mapAttributes(attrs) {
@@ -17984,7 +17984,7 @@ class Editor extends EventEmitter {
17984
17984
  * Process collaboration migrations
17985
17985
  */
17986
17986
  processCollaborationMigrations() {
17987
- console.debug("[checkVersionMigrations] Current editor version", "1.3.0-next.4");
17987
+ console.debug("[checkVersionMigrations] Current editor version", "1.3.0-next.5");
17988
17988
  if (!this.options.ydoc) return;
17989
17989
  const metaMap = this.options.ydoc.getMap("meta");
17990
17990
  let docVersion = metaMap.get("version");
@@ -41246,6 +41246,19 @@ function tokenNodeToRun(node, positions, defaultFont, defaultSize, inheritedMark
41246
41246
  const effectiveMarks = nodeMarks.length > 0 ? nodeMarks : marksAsAttrs;
41247
41247
  const marks = [...effectiveMarks, ...inheritedMarks ?? []];
41248
41248
  applyMarksToRun(run, marks, hyperlinkConfig, themeColors);
41249
+ if (marksAsAttrs.length > 0) {
41250
+ run._explicitFont = true;
41251
+ }
41252
+ console.debug("[token-debug] tokenNodeToRun", {
41253
+ token,
41254
+ fontFamily: run.fontFamily,
41255
+ fontSize: run.fontSize,
41256
+ defaultFont,
41257
+ defaultSize,
41258
+ nodeMarksCount: nodeMarks.length,
41259
+ marksAsAttrsCount: marksAsAttrs.length,
41260
+ inheritedMarksCount: inheritedMarks?.length ?? 0
41261
+ });
41249
41262
  return run;
41250
41263
  }
41251
41264
  const EIGHTHS_PER_POINT = 8;
@@ -44994,6 +45007,10 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
44994
45007
  if (TOKEN_INLINE_TYPES.has(node.type)) {
44995
45008
  const tokenKind = TOKEN_INLINE_TYPES.get(node.type);
44996
45009
  if (tokenKind) {
45010
+ const marksAsAttrs = Array.isArray(node.attrs?.marksAsAttrs) ? node.attrs.marksAsAttrs : [];
45011
+ const nodeMarks = node.marks ?? [];
45012
+ const effectiveMarks = nodeMarks.length > 0 ? nodeMarks : marksAsAttrs;
45013
+ const mergedMarks = [...effectiveMarks, ...inheritedMarks ?? []];
44997
45014
  const tokenRun = tokenNodeToRun(
44998
45015
  node,
44999
45016
  positions,
@@ -45010,6 +45027,23 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
45010
45027
  const inlineStyleId = getInlineStyleId(inheritedMarks);
45011
45028
  applyRunStyles2(tokenRun, inlineStyleId, activeRunStyleId);
45012
45029
  applyBaseRunDefaults(tokenRun, baseRunDefaults, defaultFont, defaultSize);
45030
+ if (mergedMarks.length > 0) {
45031
+ applyMarksToRun(
45032
+ tokenRun,
45033
+ mergedMarks,
45034
+ hyperlinkConfig,
45035
+ themeColors,
45036
+ converterContext?.backgroundColor
45037
+ );
45038
+ }
45039
+ console.debug("[token-debug] paragraph-token-run", {
45040
+ token: tokenRun.token,
45041
+ fontFamily: tokenRun.fontFamily,
45042
+ fontSize: tokenRun.fontSize,
45043
+ inlineStyleId,
45044
+ runStyleId: activeRunStyleId,
45045
+ mergedMarksCount: mergedMarks.length
45046
+ });
45013
45047
  currentRuns.push(tokenRun);
45014
45048
  }
45015
45049
  return;
@@ -47994,6 +48028,77 @@ function isLineBreakRun(run) {
47994
48028
  function isFieldAnnotationRun(run) {
47995
48029
  return run.kind === "fieldAnnotation";
47996
48030
  }
48031
+ function measureTabAlignmentGroup(startRunIndex, runs, ctx2, decimalSeparator = ".") {
48032
+ const result = {
48033
+ totalWidth: 0,
48034
+ runs: [],
48035
+ endRunIndex: runs.length
48036
+ };
48037
+ let foundDecimal = false;
48038
+ for (let i = startRunIndex; i < runs.length; i++) {
48039
+ const run = runs[i];
48040
+ if (isTabRun(run)) {
48041
+ result.endRunIndex = i;
48042
+ break;
48043
+ }
48044
+ if (isLineBreakRun(run) || run.kind === "break" && run.breakType === "line") {
48045
+ result.endRunIndex = i;
48046
+ break;
48047
+ }
48048
+ if (run.kind === "text" || run.kind === void 0) {
48049
+ const textRun = run;
48050
+ const text = textRun.text || "";
48051
+ if (text.length > 0) {
48052
+ const { font } = buildFontString(textRun);
48053
+ const width = measureRunWidth(text, font, ctx2, textRun, 0);
48054
+ let beforeDecimalWidth;
48055
+ if (!foundDecimal) {
48056
+ const decimalIdx = text.indexOf(decimalSeparator);
48057
+ if (decimalIdx >= 0) {
48058
+ foundDecimal = true;
48059
+ const beforeText = text.slice(0, decimalIdx);
48060
+ beforeDecimalWidth = beforeText.length > 0 ? measureRunWidth(beforeText, font, ctx2, textRun, 0) : 0;
48061
+ result.beforeDecimalWidth = result.totalWidth + beforeDecimalWidth;
48062
+ }
48063
+ }
48064
+ result.runs.push({
48065
+ runIndex: i,
48066
+ width,
48067
+ text,
48068
+ beforeDecimalWidth
48069
+ });
48070
+ result.totalWidth += width;
48071
+ } else {
48072
+ result.runs.push({ runIndex: i, width: 0, text: "" });
48073
+ }
48074
+ continue;
48075
+ }
48076
+ if (isImageRun(run)) {
48077
+ const leftSpace = run.distLeft ?? 0;
48078
+ const rightSpace = run.distRight ?? 0;
48079
+ const imageWidth = run.width + leftSpace + rightSpace;
48080
+ result.runs.push({ runIndex: i, width: imageWidth });
48081
+ result.totalWidth += imageWidth;
48082
+ continue;
48083
+ }
48084
+ if (isFieldAnnotationRun(run)) {
48085
+ const fontSize2 = run.fontSize ?? DEFAULT_FIELD_ANNOTATION_FONT_SIZE;
48086
+ const { font } = buildFontString({
48087
+ fontFamily: run.fontFamily ?? "Arial",
48088
+ fontSize: fontSize2,
48089
+ bold: run.bold,
48090
+ italic: run.italic
48091
+ });
48092
+ const textWidth = run.displayLabel ? measureRunWidth(run.displayLabel, font, ctx2, run, 0) : 0;
48093
+ const pillWidth = textWidth + FIELD_ANNOTATION_PILL_PADDING;
48094
+ result.runs.push({ runIndex: i, width: pillWidth });
48095
+ result.totalWidth += pillWidth;
48096
+ continue;
48097
+ }
48098
+ result.runs.push({ runIndex: i, width: 0 });
48099
+ }
48100
+ return result;
48101
+ }
47997
48102
  async function measureBlock(block, constraints) {
47998
48103
  const normalized = normalizeConstraints(constraints);
47999
48104
  if (block.kind === "drawing") {
@@ -48117,6 +48222,7 @@ async function measureParagraphBlock(block, maxWidth) {
48117
48222
  let pendingTabAlignment = null;
48118
48223
  let lastAppliedTabAlign = null;
48119
48224
  const warnedTabVals = /* @__PURE__ */ new Set();
48225
+ let activeTabGroup = null;
48120
48226
  const validateTabStopVal = (stop) => {
48121
48227
  if (!ALLOWED_TAB_VALS.has(stop.val) && !warnedTabVals.has(stop.val)) {
48122
48228
  warnedTabVals.add(stop.val);
@@ -48296,6 +48402,7 @@ async function measureParagraphBlock(block, maxWidth) {
48296
48402
  continue;
48297
48403
  }
48298
48404
  if (isTabRun(run)) {
48405
+ activeTabGroup = null;
48299
48406
  if (!currentLine) {
48300
48407
  currentLine = {
48301
48408
  fromRun: runIndex,
@@ -48320,12 +48427,6 @@ async function measureParagraphBlock(block, maxWidth) {
48320
48427
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, 12);
48321
48428
  currentLine.toRun = runIndex;
48322
48429
  currentLine.toChar = 1;
48323
- if (stop) {
48324
- validateTabStopVal(stop);
48325
- pendingTabAlignment = { target: clampedTarget, val: stop.val };
48326
- } else {
48327
- pendingTabAlignment = null;
48328
- }
48329
48430
  if (stop && stop.leader && stop.leader !== "none") {
48330
48431
  const leaderStyle = stop.leader;
48331
48432
  const from3 = Math.min(originX, clampedTarget);
@@ -48333,6 +48434,36 @@ async function measureParagraphBlock(block, maxWidth) {
48333
48434
  if (!currentLine.leaders) currentLine.leaders = [];
48334
48435
  currentLine.leaders.push({ from: from3, to, style: leaderStyle });
48335
48436
  }
48437
+ if (stop) {
48438
+ validateTabStopVal(stop);
48439
+ if (stop.val === "end" || stop.val === "center" || stop.val === "decimal") {
48440
+ const groupMeasure = measureTabAlignmentGroup(runIndex + 1, runsToProcess, ctx2, decimalSeparator);
48441
+ if (groupMeasure.totalWidth > 0) {
48442
+ let groupStartX;
48443
+ if (stop.val === "end") {
48444
+ groupStartX = Math.max(0, clampedTarget - groupMeasure.totalWidth);
48445
+ } else if (stop.val === "center") {
48446
+ groupStartX = Math.max(0, clampedTarget - groupMeasure.totalWidth / 2);
48447
+ } else {
48448
+ const beforeDecimal = groupMeasure.beforeDecimalWidth ?? groupMeasure.totalWidth;
48449
+ groupStartX = Math.max(0, clampedTarget - beforeDecimal);
48450
+ }
48451
+ activeTabGroup = {
48452
+ measure: groupMeasure,
48453
+ startX: groupStartX,
48454
+ currentX: groupStartX,
48455
+ target: clampedTarget,
48456
+ val: stop.val
48457
+ };
48458
+ currentLine.width = roundValue(groupStartX);
48459
+ }
48460
+ pendingTabAlignment = null;
48461
+ } else {
48462
+ pendingTabAlignment = { target: clampedTarget, val: stop.val };
48463
+ }
48464
+ } else {
48465
+ pendingTabAlignment = null;
48466
+ }
48336
48467
  continue;
48337
48468
  }
48338
48469
  if (isImageRun(run)) {
@@ -48343,7 +48474,10 @@ async function measureParagraphBlock(block, maxWidth) {
48343
48474
  const bottomSpace = run.distBottom ?? 0;
48344
48475
  const imageHeight = run.height + topSpace + bottomSpace;
48345
48476
  let imageStartX;
48346
- if (pendingTabAlignment && currentLine) {
48477
+ if (activeTabGroup && currentLine) {
48478
+ imageStartX = activeTabGroup.currentX;
48479
+ activeTabGroup.currentX = roundValue(activeTabGroup.currentX + imageWidth);
48480
+ } else if (pendingTabAlignment && currentLine) {
48347
48481
  imageStartX = alignPendingTabForWidth(imageWidth);
48348
48482
  }
48349
48483
  if (!currentLine) {
@@ -48368,10 +48502,14 @@ async function measureParagraphBlock(block, maxWidth) {
48368
48502
  }
48369
48503
  ]
48370
48504
  };
48505
+ if (activeTabGroup && runIndex + 1 >= activeTabGroup.measure.endRunIndex) {
48506
+ activeTabGroup = null;
48507
+ }
48371
48508
  continue;
48372
48509
  }
48373
48510
  const appliedTabAlign = lastAppliedTabAlign;
48374
- if (currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
48511
+ const skipFitCheck = activeTabGroup !== null;
48512
+ if (!skipFitCheck && currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
48375
48513
  trimTrailingWrapSpaces(currentLine);
48376
48514
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
48377
48515
  const lineBase = currentLine;
@@ -48384,6 +48522,7 @@ async function measureParagraphBlock(block, maxWidth) {
48384
48522
  tabStopCursor = 0;
48385
48523
  pendingTabAlignment = null;
48386
48524
  lastAppliedTabAlign = null;
48525
+ activeTabGroup = null;
48387
48526
  currentLine = {
48388
48527
  fromRun: runIndex,
48389
48528
  fromChar: 0,
@@ -48416,6 +48555,9 @@ async function measureParagraphBlock(block, maxWidth) {
48416
48555
  ...imageStartX !== void 0 ? { x: imageStartX } : {}
48417
48556
  });
48418
48557
  }
48558
+ if (activeTabGroup && runIndex + 1 >= activeTabGroup.measure.endRunIndex) {
48559
+ activeTabGroup = null;
48560
+ }
48419
48561
  const tabAlign = appliedTabAlign;
48420
48562
  if (tabAlign && currentLine && tabAlign.val === "end") {
48421
48563
  currentLine.width = roundValue(tabAlign.target);
@@ -48591,7 +48733,11 @@ async function measureParagraphBlock(block, maxWidth) {
48591
48733
  }
48592
48734
  }
48593
48735
  let segmentStartX;
48594
- if (currentLine && pendingTabAlignment) {
48736
+ let inActiveTabGroup = false;
48737
+ if (activeTabGroup && currentLine) {
48738
+ segmentStartX = activeTabGroup.currentX;
48739
+ inActiveTabGroup = true;
48740
+ } else if (currentLine && pendingTabAlignment) {
48595
48741
  segmentStartX = alignSegmentAtTab(segment, font, run, charPosInRun);
48596
48742
  if (segmentStartX == null) {
48597
48743
  segmentStartX = currentLine.width;
@@ -48628,6 +48774,7 @@ async function measureParagraphBlock(block, maxWidth) {
48628
48774
  tabStopCursor = 0;
48629
48775
  pendingTabAlignment = null;
48630
48776
  lastAppliedTabAlign = null;
48777
+ activeTabGroup = null;
48631
48778
  currentLine = {
48632
48779
  fromRun: runIndex,
48633
48780
  fromChar: spaceStartChar,
@@ -48646,7 +48793,19 @@ async function measureParagraphBlock(block, maxWidth) {
48646
48793
  currentLine.width = roundValue(currentLine.width + boundarySpacing2 + singleSpaceWidth);
48647
48794
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run);
48648
48795
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run.fontSize);
48649
- appendSegment(currentLine.segments, runIndex, spaceStartChar, spaceEndChar, singleSpaceWidth);
48796
+ let spaceExplicitX;
48797
+ if (inActiveTabGroup && activeTabGroup) {
48798
+ spaceExplicitX = activeTabGroup.currentX;
48799
+ activeTabGroup.currentX = roundValue(activeTabGroup.currentX + singleSpaceWidth);
48800
+ }
48801
+ appendSegment(
48802
+ currentLine.segments,
48803
+ runIndex,
48804
+ spaceStartChar,
48805
+ spaceEndChar,
48806
+ singleSpaceWidth,
48807
+ spaceExplicitX
48808
+ );
48650
48809
  currentLine.spaceCount += 1;
48651
48810
  }
48652
48811
  }
@@ -48794,7 +48953,7 @@ async function measureParagraphBlock(block, maxWidth) {
48794
48953
  const totalWidthWithWord = currentLine.width + boundarySpacing + wordCommitWidth + // Safe cast: only TextRuns produce word segments from split(), other run types are handled earlier
48795
48954
  (shouldIncludeDelimiterSpace ? run.letterSpacing ?? 0 : 0);
48796
48955
  const availableWidth = currentLine.maxWidth - WIDTH_FUDGE_PX2;
48797
- let shouldBreak = currentLine.width + boundarySpacing + wordOnlyWidth > availableWidth && currentLine.width > 0 && !isTocEntry;
48956
+ let shouldBreak = !inActiveTabGroup && currentLine.width + boundarySpacing + wordOnlyWidth > availableWidth && currentLine.width > 0 && !isTocEntry;
48798
48957
  let compressedWidth = null;
48799
48958
  if (shouldBreak && justifyAlignment) {
48800
48959
  const isLastNonEmptyWordInSegment = wordIndex === lastNonEmptyWordIndex;
@@ -48859,15 +49018,14 @@ async function measureParagraphBlock(block, maxWidth) {
48859
49018
  currentLine.width = roundValue(currentLine.width + boundarySpacing + wordOnlyWidth);
48860
49019
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run);
48861
49020
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run.fontSize);
48862
- const useExplicitXHere = wordIndex === 0 && segmentStartX !== void 0;
48863
- appendSegment(
48864
- currentLine.segments,
48865
- runIndex,
48866
- wordStartChar,
48867
- wordEndNoSpace,
48868
- wordOnlyWidth,
48869
- useExplicitXHere ? segmentStartX : void 0
48870
- );
49021
+ let explicitXHere;
49022
+ if (inActiveTabGroup && activeTabGroup) {
49023
+ explicitXHere = activeTabGroup.currentX;
49024
+ activeTabGroup.currentX = roundValue(activeTabGroup.currentX + wordOnlyWidth);
49025
+ } else if (wordIndex === 0 && segmentStartX !== void 0) {
49026
+ explicitXHere = segmentStartX;
49027
+ }
49028
+ appendSegment(currentLine.segments, runIndex, wordStartChar, wordEndNoSpace, wordOnlyWidth, explicitXHere);
48871
49029
  trimTrailingWrapSpaces(currentLine);
48872
49030
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
48873
49031
  const lineBase = currentLine;
@@ -48882,8 +49040,13 @@ async function measureParagraphBlock(block, maxWidth) {
48882
49040
  }
48883
49041
  const newToChar = shouldIncludeDelimiterSpace ? wordEndWithSpace : wordEndNoSpace;
48884
49042
  currentLine.toChar = newToChar;
48885
- const useExplicitX = wordIndex === 0 && segmentStartX !== void 0;
48886
- const explicitX = useExplicitX ? segmentStartX : void 0;
49043
+ let explicitX;
49044
+ if (inActiveTabGroup && activeTabGroup) {
49045
+ explicitX = activeTabGroup.currentX;
49046
+ activeTabGroup.currentX = roundValue(activeTabGroup.currentX + wordCommitWidth);
49047
+ } else if (wordIndex === 0 && segmentStartX !== void 0) {
49048
+ explicitX = segmentStartX;
49049
+ }
48887
49050
  const targetWidth = compressedWidth != null ? compressedWidth : currentLine.width + boundarySpacing + wordCommitWidth + (shouldIncludeDelimiterSpace ? run.letterSpacing ?? 0 : 0);
48888
49051
  if (compressedWidth != null) {
48889
49052
  currentLine.naturalWidth = roundValue(totalWidthWithWord);
@@ -48905,6 +49068,12 @@ async function measureParagraphBlock(block, maxWidth) {
48905
49068
  }
48906
49069
  }
48907
49070
  lastAppliedTabAlign = null;
49071
+ if (activeTabGroup && runIndex + 1 >= activeTabGroup.measure.endRunIndex) {
49072
+ if (currentLine && activeTabGroup.val === "end") {
49073
+ currentLine.width = roundValue(activeTabGroup.target);
49074
+ }
49075
+ activeTabGroup = null;
49076
+ }
48908
49077
  if (!isLastSegment) {
48909
49078
  pendingTabAlignment = null;
48910
49079
  if (!currentLine) {