@harbour-enterprises/superdoc 1.3.0-next.4 → 1.3.0-next.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  const jszip = require("./jszip-C8_CqJxM.cjs");
3
3
  const helpers$1 = require("./helpers-nOdwpmwb.cjs");
4
- const superEditor_converter = require("./SuperConverter-qB6m0K1X.cjs");
4
+ const superEditor_converter = require("./SuperConverter-BdOf8skU.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.6";
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.6");
17988
17988
  if (!this.options.ydoc) return;
17989
17989
  const metaMap = this.options.ydoc.getMap("meta");
17990
17990
  let docVersion = metaMap.get("version");
@@ -30859,8 +30859,7 @@ function getHeaderFooterTypeForSection(pageNumber, sectionIndex, identifier, opt
30859
30859
  const titlePgEnabled = sectionTitlePg === true;
30860
30860
  const isFirstPageOfSection = sectionPageNumber === 1;
30861
30861
  if (isFirstPageOfSection && titlePgEnabled) {
30862
- if (hasFirst) return "first";
30863
- if (!hasDefault && !hasEven && !hasOdd) return null;
30862
+ if (hasFirst || hasDefault || hasEven || hasOdd) return "first";
30864
30863
  return null;
30865
30864
  }
30866
30865
  if (identifier.alternateHeaders) {
@@ -32916,6 +32915,45 @@ function layoutDocument(blocks, measures, options = {}) {
32916
32915
  return height;
32917
32916
  };
32918
32917
  const headerContentHeights = options.headerContentHeights;
32918
+ const footerContentHeights = options.footerContentHeights;
32919
+ const headerContentHeightsByRId = options.headerContentHeightsByRId;
32920
+ const footerContentHeightsByRId = options.footerContentHeightsByRId;
32921
+ const getVariantTypeForPage = (sectionPageNumber, titlePgEnabled, alternateHeaders) => {
32922
+ if (sectionPageNumber === 1 && titlePgEnabled) {
32923
+ return "first";
32924
+ }
32925
+ return "default";
32926
+ };
32927
+ const getHeaderHeightForPage = (variantType, headerRef) => {
32928
+ if (headerRef && headerContentHeightsByRId?.has(headerRef)) {
32929
+ return validateContentHeight(headerContentHeightsByRId.get(headerRef));
32930
+ }
32931
+ if (headerContentHeights) {
32932
+ return validateContentHeight(headerContentHeights[variantType]);
32933
+ }
32934
+ return 0;
32935
+ };
32936
+ const getFooterHeightForPage = (variantType, footerRef) => {
32937
+ if (footerRef && footerContentHeightsByRId?.has(footerRef)) {
32938
+ return validateContentHeight(footerContentHeightsByRId.get(footerRef));
32939
+ }
32940
+ if (footerContentHeights) {
32941
+ return validateContentHeight(footerContentHeights[variantType]);
32942
+ }
32943
+ return 0;
32944
+ };
32945
+ const calculateEffectiveTopMargin = (headerContentHeight, currentHeaderDistance, baseTopMargin) => {
32946
+ if (headerContentHeight > 0) {
32947
+ return Math.max(baseTopMargin, currentHeaderDistance + headerContentHeight);
32948
+ }
32949
+ return baseTopMargin;
32950
+ };
32951
+ const calculateEffectiveBottomMargin = (footerContentHeight, currentFooterDistance, baseBottomMargin) => {
32952
+ if (footerContentHeight > 0) {
32953
+ return Math.max(baseBottomMargin, currentFooterDistance + footerContentHeight);
32954
+ }
32955
+ return baseBottomMargin;
32956
+ };
32919
32957
  const maxHeaderContentHeight = headerContentHeights ? Math.max(
32920
32958
  0,
32921
32959
  validateContentHeight(headerContentHeights.default),
@@ -32923,9 +32961,6 @@ function layoutDocument(blocks, measures, options = {}) {
32923
32961
  validateContentHeight(headerContentHeights.even),
32924
32962
  validateContentHeight(headerContentHeights.odd)
32925
32963
  ) : 0;
32926
- const headerDistance = margins.header ?? margins.top;
32927
- const effectiveTopMargin = maxHeaderContentHeight > 0 ? Math.max(margins.top, headerDistance + maxHeaderContentHeight) : margins.top;
32928
- const footerContentHeights = options.footerContentHeights;
32929
32964
  const maxFooterContentHeight = footerContentHeights ? Math.max(
32930
32965
  0,
32931
32966
  validateContentHeight(footerContentHeights.default),
@@ -32933,8 +32968,12 @@ function layoutDocument(blocks, measures, options = {}) {
32933
32968
  validateContentHeight(footerContentHeights.even),
32934
32969
  validateContentHeight(footerContentHeights.odd)
32935
32970
  ) : 0;
32971
+ const headerDistance = margins.header ?? margins.top;
32936
32972
  const footerDistance = margins.footer ?? margins.bottom;
32937
- const effectiveBottomMargin = maxFooterContentHeight > 0 ? Math.max(margins.bottom, footerDistance + maxFooterContentHeight) : margins.bottom;
32973
+ const defaultHeaderHeight = getHeaderHeightForPage("default", void 0);
32974
+ const defaultFooterHeight = getFooterHeightForPage("default", void 0);
32975
+ const effectiveTopMargin = calculateEffectiveTopMargin(defaultHeaderHeight, headerDistance, margins.top);
32976
+ const effectiveBottomMargin = calculateEffectiveBottomMargin(defaultFooterHeight, footerDistance, margins.bottom);
32938
32977
  let activeTopMargin = effectiveTopMargin;
32939
32978
  let activeBottomMargin = effectiveBottomMargin;
32940
32979
  let activeLeftMargin = margins.left;
@@ -32943,6 +32982,10 @@ function layoutDocument(blocks, measures, options = {}) {
32943
32982
  let pendingBottomMargin = null;
32944
32983
  let pendingLeftMargin = null;
32945
32984
  let pendingRightMargin = null;
32985
+ let activeSectionBaseTopMargin = margins.top;
32986
+ let activeSectionBaseBottomMargin = margins.bottom;
32987
+ let pendingSectionBaseTopMargin = null;
32988
+ let pendingSectionBaseBottomMargin = null;
32946
32989
  let activeHeaderDistance = margins.header ?? margins.top;
32947
32990
  let pendingHeaderDistance = null;
32948
32991
  let activeFooterDistance = margins.footer ?? margins.bottom;
@@ -33148,6 +33191,7 @@ function layoutDocument(blocks, measures, options = {}) {
33148
33191
  }
33149
33192
  let activeSectionIndex = initialSectionMetadata?.sectionIndex ?? 0;
33150
33193
  let pendingSectionIndex = null;
33194
+ const sectionFirstPageNumbers = /* @__PURE__ */ new Map();
33151
33195
  const paginator = createPaginator({
33152
33196
  margins: paginatorMargins,
33153
33197
  getActiveTopMargin: () => activeTopMargin,
@@ -33161,6 +33205,7 @@ function layoutDocument(blocks, measures, options = {}) {
33161
33205
  createPage,
33162
33206
  onNewPage: (state) => {
33163
33207
  if (!state) {
33208
+ const isEnteringNewSection = pendingSectionIndex !== null;
33164
33209
  const applied = applyPendingToActive({
33165
33210
  activeTopMargin,
33166
33211
  activeBottomMargin,
@@ -33228,7 +33273,69 @@ function layoutDocument(blocks, measures, options = {}) {
33228
33273
  activeVAlign = pendingVAlign;
33229
33274
  pendingVAlign = null;
33230
33275
  }
33276
+ if (pendingSectionBaseTopMargin !== null) {
33277
+ activeSectionBaseTopMargin = pendingSectionBaseTopMargin;
33278
+ pendingSectionBaseTopMargin = null;
33279
+ }
33280
+ if (pendingSectionBaseBottomMargin !== null) {
33281
+ activeSectionBaseBottomMargin = pendingSectionBaseBottomMargin;
33282
+ pendingSectionBaseBottomMargin = null;
33283
+ }
33231
33284
  pageCount += 1;
33285
+ const newPageNumber = pageCount;
33286
+ if (isEnteringNewSection || !sectionFirstPageNumbers.has(activeSectionIndex)) {
33287
+ sectionFirstPageNumbers.set(activeSectionIndex, newPageNumber);
33288
+ }
33289
+ const firstPageInSection = sectionFirstPageNumbers.get(activeSectionIndex) ?? newPageNumber;
33290
+ const sectionPageNumber = newPageNumber - firstPageInSection + 1;
33291
+ const sectionMetadata = sectionMetadataList[activeSectionIndex];
33292
+ const titlePgEnabled = sectionMetadata?.titlePg ?? false;
33293
+ const variantType = getVariantTypeForPage(sectionPageNumber, titlePgEnabled);
33294
+ let headerRef = activeSectionRefs?.headerRefs?.[variantType];
33295
+ let footerRef = activeSectionRefs?.footerRefs?.[variantType];
33296
+ let effectiveVariantType = variantType;
33297
+ if (!headerRef && variantType !== "default" && activeSectionIndex > 0) {
33298
+ const prevSectionMetadata = sectionMetadataList[activeSectionIndex - 1];
33299
+ if (prevSectionMetadata?.headerRefs?.[variantType]) {
33300
+ headerRef = prevSectionMetadata.headerRefs[variantType];
33301
+ layoutLog(
33302
+ `[Layout] Page ${newPageNumber}: Inheriting header '${variantType}' from section ${activeSectionIndex - 1}: ${headerRef}`
33303
+ );
33304
+ }
33305
+ }
33306
+ if (!footerRef && variantType !== "default" && activeSectionIndex > 0) {
33307
+ const prevSectionMetadata = sectionMetadataList[activeSectionIndex - 1];
33308
+ if (prevSectionMetadata?.footerRefs?.[variantType]) {
33309
+ footerRef = prevSectionMetadata.footerRefs[variantType];
33310
+ layoutLog(
33311
+ `[Layout] Page ${newPageNumber}: Inheriting footer '${variantType}' from section ${activeSectionIndex - 1}: ${footerRef}`
33312
+ );
33313
+ }
33314
+ }
33315
+ if (!headerRef && variantType !== "default" && activeSectionRefs?.headerRefs?.default) {
33316
+ headerRef = activeSectionRefs.headerRefs.default;
33317
+ effectiveVariantType = "default";
33318
+ }
33319
+ if (!footerRef && variantType !== "default" && activeSectionRefs?.footerRefs?.default) {
33320
+ footerRef = activeSectionRefs.footerRefs.default;
33321
+ }
33322
+ const headerHeight = getHeaderHeightForPage(effectiveVariantType, headerRef);
33323
+ const footerHeight = getFooterHeightForPage(
33324
+ variantType !== "default" && !activeSectionRefs?.footerRefs?.[variantType] ? "default" : variantType,
33325
+ footerRef
33326
+ );
33327
+ activeTopMargin = calculateEffectiveTopMargin(headerHeight, activeHeaderDistance, activeSectionBaseTopMargin);
33328
+ activeBottomMargin = calculateEffectiveBottomMargin(
33329
+ footerHeight,
33330
+ activeFooterDistance,
33331
+ activeSectionBaseBottomMargin
33332
+ );
33333
+ layoutLog(
33334
+ `[Layout] Page ${newPageNumber}: Using variant '${variantType}' - headerHeight: ${headerHeight}, footerHeight: ${footerHeight}`
33335
+ );
33336
+ layoutLog(
33337
+ `[Layout] Page ${newPageNumber}: Adjusted margins - top: ${activeTopMargin}, bottom: ${activeBottomMargin} (base: ${activeSectionBaseTopMargin}, ${activeSectionBaseBottomMargin})`
33338
+ );
33232
33339
  return;
33233
33340
  }
33234
33341
  if (state?.page) {
@@ -33434,6 +33541,20 @@ function layoutDocument(blocks, measures, options = {}) {
33434
33541
  pendingColumns = updatedState.pendingColumns;
33435
33542
  activeOrientation = updatedState.activeOrientation;
33436
33543
  pendingOrientation = updatedState.pendingOrientation;
33544
+ const isFirstSection = effectiveBlock.attrs?.isFirstSection && states.length === 0;
33545
+ const blockTopMargin = effectiveBlock.margins?.top;
33546
+ const blockBottomMargin = effectiveBlock.margins?.bottom;
33547
+ if (isFirstSection) {
33548
+ activeSectionBaseTopMargin = typeof blockTopMargin === "number" ? blockTopMargin : margins.top;
33549
+ activeSectionBaseBottomMargin = typeof blockBottomMargin === "number" ? blockBottomMargin : margins.bottom;
33550
+ } else if (blockTopMargin !== void 0 || blockBottomMargin !== void 0) {
33551
+ if (blockTopMargin !== void 0) {
33552
+ pendingSectionBaseTopMargin = typeof blockTopMargin === "number" ? blockTopMargin : margins.top;
33553
+ }
33554
+ if (blockBottomMargin !== void 0) {
33555
+ pendingSectionBaseBottomMargin = typeof blockBottomMargin === "number" ? blockBottomMargin : margins.bottom;
33556
+ }
33557
+ }
33437
33558
  if (effectiveBlock.vAlign) {
33438
33559
  const isFirstSection2 = effectiveBlock.attrs?.isFirstSection && states.length === 0;
33439
33560
  if (isFirstSection2) {
@@ -33452,7 +33573,6 @@ function layoutDocument(blocks, measures, options = {}) {
33452
33573
  }
33453
33574
  const sectionIndexRaw = effectiveBlock.attrs?.sectionIndex;
33454
33575
  const metadataIndex = typeof sectionIndexRaw === "number" ? sectionIndexRaw : Number(sectionIndexRaw ?? NaN);
33455
- const isFirstSection = effectiveBlock.attrs?.isFirstSection && states.length === 0;
33456
33576
  if (Number.isFinite(metadataIndex)) {
33457
33577
  if (isFirstSection) {
33458
33578
  activeSectionIndex = metadataIndex;
@@ -35640,6 +35760,7 @@ async function incrementalLayout(previousBlocks, _previousLayout, nextBlocks, op
35640
35760
  `[Perf] 4.1 Measure all blocks: ${(measureEnd - measureStart).toFixed(2)}ms (${cacheMisses} measured, ${cacheHits} cached)`
35641
35761
  );
35642
35762
  let headerContentHeights;
35763
+ let headerContentHeightsByRId;
35643
35764
  const hasHeaderBlocks = headerFooter?.headerBlocks && Object.keys(headerFooter.headerBlocks).length > 0;
35644
35765
  const hasHeaderBlocksByRId = headerFooter?.headerBlocksByRId && headerFooter.headerBlocksByRId.size > 0;
35645
35766
  if (headerFooter?.constraints && (hasHeaderBlocks || hasHeaderBlocksByRId)) {
@@ -35679,7 +35800,8 @@ async function incrementalLayout(previousBlocks, _previousLayout, nextBlocks, op
35679
35800
  }
35680
35801
  }
35681
35802
  if (hasHeaderBlocksByRId && headerFooter.headerBlocksByRId) {
35682
- for (const [_rId, blocks] of headerFooter.headerBlocksByRId) {
35803
+ headerContentHeightsByRId = /* @__PURE__ */ new Map();
35804
+ for (const [rId, blocks] of headerFooter.headerBlocksByRId) {
35683
35805
  if (!blocks || blocks.length === 0) continue;
35684
35806
  const measureConstraints = {
35685
35807
  maxWidth: headerFooter.constraints.width,
@@ -35691,8 +35813,7 @@ async function incrementalLayout(previousBlocks, _previousLayout, nextBlocks, op
35691
35813
  height: headerFooter.constraints.height
35692
35814
  });
35693
35815
  if (layout2.height > 0) {
35694
- const currentDefault = headerContentHeights.default ?? 0;
35695
- headerContentHeights.default = Math.max(currentDefault, layout2.height);
35816
+ headerContentHeightsByRId.set(rId, layout2.height);
35696
35817
  }
35697
35818
  }
35698
35819
  }
@@ -35700,6 +35821,7 @@ async function incrementalLayout(previousBlocks, _previousLayout, nextBlocks, op
35700
35821
  perfLog(`[Perf] 4.1.5 Pre-layout headers for height: ${(hfPreEnd - hfPreStart).toFixed(2)}ms`);
35701
35822
  }
35702
35823
  let footerContentHeights;
35824
+ let footerContentHeightsByRId;
35703
35825
  const hasFooterBlocks = headerFooter?.footerBlocks && Object.keys(headerFooter.footerBlocks).length > 0;
35704
35826
  const hasFooterBlocksByRId = headerFooter?.footerBlocksByRId && headerFooter.footerBlocksByRId.size > 0;
35705
35827
  if (headerFooter?.constraints && (hasFooterBlocks || hasFooterBlocksByRId)) {
@@ -35742,7 +35864,8 @@ async function incrementalLayout(previousBlocks, _previousLayout, nextBlocks, op
35742
35864
  }
35743
35865
  }
35744
35866
  if (hasFooterBlocksByRId && headerFooter.footerBlocksByRId) {
35745
- for (const [_rId, blocks] of headerFooter.footerBlocksByRId) {
35867
+ footerContentHeightsByRId = /* @__PURE__ */ new Map();
35868
+ for (const [rId, blocks] of headerFooter.footerBlocksByRId) {
35746
35869
  if (!blocks || blocks.length === 0) continue;
35747
35870
  const measureConstraints = {
35748
35871
  maxWidth: headerFooter.constraints.width,
@@ -35754,8 +35877,7 @@ async function incrementalLayout(previousBlocks, _previousLayout, nextBlocks, op
35754
35877
  height: headerFooter.constraints.height
35755
35878
  });
35756
35879
  if (layout2.height > 0) {
35757
- const currentDefault = footerContentHeights.default ?? 0;
35758
- footerContentHeights.default = Math.max(currentDefault, layout2.height);
35880
+ footerContentHeightsByRId.set(rId, layout2.height);
35759
35881
  }
35760
35882
  }
35761
35883
  }
@@ -35770,9 +35892,13 @@ async function incrementalLayout(previousBlocks, _previousLayout, nextBlocks, op
35770
35892
  let layout = layoutDocument(nextBlocks, measures, {
35771
35893
  ...options,
35772
35894
  headerContentHeights,
35773
- // Pass header heights to prevent overlap
35895
+ // Pass header heights to prevent overlap (per-variant)
35774
35896
  footerContentHeights,
35775
- // Pass footer heights to prevent overlap
35897
+ // Pass footer heights to prevent overlap (per-variant)
35898
+ headerContentHeightsByRId,
35899
+ // Pass header heights by rId for per-page margin calculation
35900
+ footerContentHeightsByRId,
35901
+ // Pass footer heights by rId for per-page margin calculation
35776
35902
  remeasureParagraph: (block, maxWidth, firstLineIndent) => remeasureParagraph(block, maxWidth, firstLineIndent)
35777
35903
  });
35778
35904
  const layoutEnd = performance.now();
@@ -35820,9 +35946,13 @@ async function incrementalLayout(previousBlocks, _previousLayout, nextBlocks, op
35820
35946
  layout = layoutDocument(currentBlocks, currentMeasures, {
35821
35947
  ...options,
35822
35948
  headerContentHeights,
35823
- // Pass header heights to prevent overlap
35949
+ // Pass header heights to prevent overlap (per-variant)
35824
35950
  footerContentHeights,
35825
- // Pass footer heights to prevent overlap
35951
+ // Pass footer heights to prevent overlap (per-variant)
35952
+ headerContentHeightsByRId,
35953
+ // Pass header heights by rId for per-page margin calculation
35954
+ footerContentHeightsByRId,
35955
+ // Pass footer heights by rId for per-page margin calculation
35826
35956
  remeasureParagraph: (block, maxWidth, firstLineIndent) => remeasureParagraph(block, maxWidth, firstLineIndent)
35827
35957
  });
35828
35958
  const relayoutEnd = performance.now();
@@ -41246,6 +41376,19 @@ function tokenNodeToRun(node, positions, defaultFont, defaultSize, inheritedMark
41246
41376
  const effectiveMarks = nodeMarks.length > 0 ? nodeMarks : marksAsAttrs;
41247
41377
  const marks = [...effectiveMarks, ...inheritedMarks ?? []];
41248
41378
  applyMarksToRun(run, marks, hyperlinkConfig, themeColors);
41379
+ if (marksAsAttrs.length > 0) {
41380
+ run._explicitFont = true;
41381
+ }
41382
+ console.debug("[token-debug] tokenNodeToRun", {
41383
+ token,
41384
+ fontFamily: run.fontFamily,
41385
+ fontSize: run.fontSize,
41386
+ defaultFont,
41387
+ defaultSize,
41388
+ nodeMarksCount: nodeMarks.length,
41389
+ marksAsAttrsCount: marksAsAttrs.length,
41390
+ inheritedMarksCount: inheritedMarks?.length ?? 0
41391
+ });
41249
41392
  return run;
41250
41393
  }
41251
41394
  const EIGHTHS_PER_POINT = 8;
@@ -44994,6 +45137,10 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
44994
45137
  if (TOKEN_INLINE_TYPES.has(node.type)) {
44995
45138
  const tokenKind = TOKEN_INLINE_TYPES.get(node.type);
44996
45139
  if (tokenKind) {
45140
+ const marksAsAttrs = Array.isArray(node.attrs?.marksAsAttrs) ? node.attrs.marksAsAttrs : [];
45141
+ const nodeMarks = node.marks ?? [];
45142
+ const effectiveMarks = nodeMarks.length > 0 ? nodeMarks : marksAsAttrs;
45143
+ const mergedMarks = [...effectiveMarks, ...inheritedMarks ?? []];
44997
45144
  const tokenRun = tokenNodeToRun(
44998
45145
  node,
44999
45146
  positions,
@@ -45010,6 +45157,23 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
45010
45157
  const inlineStyleId = getInlineStyleId(inheritedMarks);
45011
45158
  applyRunStyles2(tokenRun, inlineStyleId, activeRunStyleId);
45012
45159
  applyBaseRunDefaults(tokenRun, baseRunDefaults, defaultFont, defaultSize);
45160
+ if (mergedMarks.length > 0) {
45161
+ applyMarksToRun(
45162
+ tokenRun,
45163
+ mergedMarks,
45164
+ hyperlinkConfig,
45165
+ themeColors,
45166
+ converterContext?.backgroundColor
45167
+ );
45168
+ }
45169
+ console.debug("[token-debug] paragraph-token-run", {
45170
+ token: tokenRun.token,
45171
+ fontFamily: tokenRun.fontFamily,
45172
+ fontSize: tokenRun.fontSize,
45173
+ inlineStyleId,
45174
+ runStyleId: activeRunStyleId,
45175
+ mergedMarksCount: mergedMarks.length
45176
+ });
45013
45177
  currentRuns.push(tokenRun);
45014
45178
  }
45015
45179
  return;
@@ -47994,6 +48158,77 @@ function isLineBreakRun(run) {
47994
48158
  function isFieldAnnotationRun(run) {
47995
48159
  return run.kind === "fieldAnnotation";
47996
48160
  }
48161
+ function measureTabAlignmentGroup(startRunIndex, runs, ctx2, decimalSeparator = ".") {
48162
+ const result = {
48163
+ totalWidth: 0,
48164
+ runs: [],
48165
+ endRunIndex: runs.length
48166
+ };
48167
+ let foundDecimal = false;
48168
+ for (let i = startRunIndex; i < runs.length; i++) {
48169
+ const run = runs[i];
48170
+ if (isTabRun(run)) {
48171
+ result.endRunIndex = i;
48172
+ break;
48173
+ }
48174
+ if (isLineBreakRun(run) || run.kind === "break" && run.breakType === "line") {
48175
+ result.endRunIndex = i;
48176
+ break;
48177
+ }
48178
+ if (run.kind === "text" || run.kind === void 0) {
48179
+ const textRun = run;
48180
+ const text = textRun.text || "";
48181
+ if (text.length > 0) {
48182
+ const { font } = buildFontString(textRun);
48183
+ const width = measureRunWidth(text, font, ctx2, textRun, 0);
48184
+ let beforeDecimalWidth;
48185
+ if (!foundDecimal) {
48186
+ const decimalIdx = text.indexOf(decimalSeparator);
48187
+ if (decimalIdx >= 0) {
48188
+ foundDecimal = true;
48189
+ const beforeText = text.slice(0, decimalIdx);
48190
+ beforeDecimalWidth = beforeText.length > 0 ? measureRunWidth(beforeText, font, ctx2, textRun, 0) : 0;
48191
+ result.beforeDecimalWidth = result.totalWidth + beforeDecimalWidth;
48192
+ }
48193
+ }
48194
+ result.runs.push({
48195
+ runIndex: i,
48196
+ width,
48197
+ text,
48198
+ beforeDecimalWidth
48199
+ });
48200
+ result.totalWidth += width;
48201
+ } else {
48202
+ result.runs.push({ runIndex: i, width: 0, text: "" });
48203
+ }
48204
+ continue;
48205
+ }
48206
+ if (isImageRun(run)) {
48207
+ const leftSpace = run.distLeft ?? 0;
48208
+ const rightSpace = run.distRight ?? 0;
48209
+ const imageWidth = run.width + leftSpace + rightSpace;
48210
+ result.runs.push({ runIndex: i, width: imageWidth });
48211
+ result.totalWidth += imageWidth;
48212
+ continue;
48213
+ }
48214
+ if (isFieldAnnotationRun(run)) {
48215
+ const fontSize2 = run.fontSize ?? DEFAULT_FIELD_ANNOTATION_FONT_SIZE;
48216
+ const { font } = buildFontString({
48217
+ fontFamily: run.fontFamily ?? "Arial",
48218
+ fontSize: fontSize2,
48219
+ bold: run.bold,
48220
+ italic: run.italic
48221
+ });
48222
+ const textWidth = run.displayLabel ? measureRunWidth(run.displayLabel, font, ctx2, run, 0) : 0;
48223
+ const pillWidth = textWidth + FIELD_ANNOTATION_PILL_PADDING;
48224
+ result.runs.push({ runIndex: i, width: pillWidth });
48225
+ result.totalWidth += pillWidth;
48226
+ continue;
48227
+ }
48228
+ result.runs.push({ runIndex: i, width: 0 });
48229
+ }
48230
+ return result;
48231
+ }
47997
48232
  async function measureBlock(block, constraints) {
47998
48233
  const normalized = normalizeConstraints(constraints);
47999
48234
  if (block.kind === "drawing") {
@@ -48117,6 +48352,7 @@ async function measureParagraphBlock(block, maxWidth) {
48117
48352
  let pendingTabAlignment = null;
48118
48353
  let lastAppliedTabAlign = null;
48119
48354
  const warnedTabVals = /* @__PURE__ */ new Set();
48355
+ let activeTabGroup = null;
48120
48356
  const validateTabStopVal = (stop) => {
48121
48357
  if (!ALLOWED_TAB_VALS.has(stop.val) && !warnedTabVals.has(stop.val)) {
48122
48358
  warnedTabVals.add(stop.val);
@@ -48296,6 +48532,7 @@ async function measureParagraphBlock(block, maxWidth) {
48296
48532
  continue;
48297
48533
  }
48298
48534
  if (isTabRun(run)) {
48535
+ activeTabGroup = null;
48299
48536
  if (!currentLine) {
48300
48537
  currentLine = {
48301
48538
  fromRun: runIndex,
@@ -48320,12 +48557,6 @@ async function measureParagraphBlock(block, maxWidth) {
48320
48557
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, 12);
48321
48558
  currentLine.toRun = runIndex;
48322
48559
  currentLine.toChar = 1;
48323
- if (stop) {
48324
- validateTabStopVal(stop);
48325
- pendingTabAlignment = { target: clampedTarget, val: stop.val };
48326
- } else {
48327
- pendingTabAlignment = null;
48328
- }
48329
48560
  if (stop && stop.leader && stop.leader !== "none") {
48330
48561
  const leaderStyle = stop.leader;
48331
48562
  const from3 = Math.min(originX, clampedTarget);
@@ -48333,6 +48564,36 @@ async function measureParagraphBlock(block, maxWidth) {
48333
48564
  if (!currentLine.leaders) currentLine.leaders = [];
48334
48565
  currentLine.leaders.push({ from: from3, to, style: leaderStyle });
48335
48566
  }
48567
+ if (stop) {
48568
+ validateTabStopVal(stop);
48569
+ if (stop.val === "end" || stop.val === "center" || stop.val === "decimal") {
48570
+ const groupMeasure = measureTabAlignmentGroup(runIndex + 1, runsToProcess, ctx2, decimalSeparator);
48571
+ if (groupMeasure.totalWidth > 0) {
48572
+ let groupStartX;
48573
+ if (stop.val === "end") {
48574
+ groupStartX = Math.max(0, clampedTarget - groupMeasure.totalWidth);
48575
+ } else if (stop.val === "center") {
48576
+ groupStartX = Math.max(0, clampedTarget - groupMeasure.totalWidth / 2);
48577
+ } else {
48578
+ const beforeDecimal = groupMeasure.beforeDecimalWidth ?? groupMeasure.totalWidth;
48579
+ groupStartX = Math.max(0, clampedTarget - beforeDecimal);
48580
+ }
48581
+ activeTabGroup = {
48582
+ measure: groupMeasure,
48583
+ startX: groupStartX,
48584
+ currentX: groupStartX,
48585
+ target: clampedTarget,
48586
+ val: stop.val
48587
+ };
48588
+ currentLine.width = roundValue(groupStartX);
48589
+ }
48590
+ pendingTabAlignment = null;
48591
+ } else {
48592
+ pendingTabAlignment = { target: clampedTarget, val: stop.val };
48593
+ }
48594
+ } else {
48595
+ pendingTabAlignment = null;
48596
+ }
48336
48597
  continue;
48337
48598
  }
48338
48599
  if (isImageRun(run)) {
@@ -48343,7 +48604,10 @@ async function measureParagraphBlock(block, maxWidth) {
48343
48604
  const bottomSpace = run.distBottom ?? 0;
48344
48605
  const imageHeight = run.height + topSpace + bottomSpace;
48345
48606
  let imageStartX;
48346
- if (pendingTabAlignment && currentLine) {
48607
+ if (activeTabGroup && currentLine) {
48608
+ imageStartX = activeTabGroup.currentX;
48609
+ activeTabGroup.currentX = roundValue(activeTabGroup.currentX + imageWidth);
48610
+ } else if (pendingTabAlignment && currentLine) {
48347
48611
  imageStartX = alignPendingTabForWidth(imageWidth);
48348
48612
  }
48349
48613
  if (!currentLine) {
@@ -48368,10 +48632,14 @@ async function measureParagraphBlock(block, maxWidth) {
48368
48632
  }
48369
48633
  ]
48370
48634
  };
48635
+ if (activeTabGroup && runIndex + 1 >= activeTabGroup.measure.endRunIndex) {
48636
+ activeTabGroup = null;
48637
+ }
48371
48638
  continue;
48372
48639
  }
48373
48640
  const appliedTabAlign = lastAppliedTabAlign;
48374
- if (currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
48641
+ const skipFitCheck = activeTabGroup !== null;
48642
+ if (!skipFitCheck && currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
48375
48643
  trimTrailingWrapSpaces(currentLine);
48376
48644
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
48377
48645
  const lineBase = currentLine;
@@ -48384,6 +48652,7 @@ async function measureParagraphBlock(block, maxWidth) {
48384
48652
  tabStopCursor = 0;
48385
48653
  pendingTabAlignment = null;
48386
48654
  lastAppliedTabAlign = null;
48655
+ activeTabGroup = null;
48387
48656
  currentLine = {
48388
48657
  fromRun: runIndex,
48389
48658
  fromChar: 0,
@@ -48416,6 +48685,9 @@ async function measureParagraphBlock(block, maxWidth) {
48416
48685
  ...imageStartX !== void 0 ? { x: imageStartX } : {}
48417
48686
  });
48418
48687
  }
48688
+ if (activeTabGroup && runIndex + 1 >= activeTabGroup.measure.endRunIndex) {
48689
+ activeTabGroup = null;
48690
+ }
48419
48691
  const tabAlign = appliedTabAlign;
48420
48692
  if (tabAlign && currentLine && tabAlign.val === "end") {
48421
48693
  currentLine.width = roundValue(tabAlign.target);
@@ -48591,7 +48863,11 @@ async function measureParagraphBlock(block, maxWidth) {
48591
48863
  }
48592
48864
  }
48593
48865
  let segmentStartX;
48594
- if (currentLine && pendingTabAlignment) {
48866
+ let inActiveTabGroup = false;
48867
+ if (activeTabGroup && currentLine) {
48868
+ segmentStartX = activeTabGroup.currentX;
48869
+ inActiveTabGroup = true;
48870
+ } else if (currentLine && pendingTabAlignment) {
48595
48871
  segmentStartX = alignSegmentAtTab(segment, font, run, charPosInRun);
48596
48872
  if (segmentStartX == null) {
48597
48873
  segmentStartX = currentLine.width;
@@ -48628,6 +48904,7 @@ async function measureParagraphBlock(block, maxWidth) {
48628
48904
  tabStopCursor = 0;
48629
48905
  pendingTabAlignment = null;
48630
48906
  lastAppliedTabAlign = null;
48907
+ activeTabGroup = null;
48631
48908
  currentLine = {
48632
48909
  fromRun: runIndex,
48633
48910
  fromChar: spaceStartChar,
@@ -48646,7 +48923,19 @@ async function measureParagraphBlock(block, maxWidth) {
48646
48923
  currentLine.width = roundValue(currentLine.width + boundarySpacing2 + singleSpaceWidth);
48647
48924
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run);
48648
48925
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run.fontSize);
48649
- appendSegment(currentLine.segments, runIndex, spaceStartChar, spaceEndChar, singleSpaceWidth);
48926
+ let spaceExplicitX;
48927
+ if (inActiveTabGroup && activeTabGroup) {
48928
+ spaceExplicitX = activeTabGroup.currentX;
48929
+ activeTabGroup.currentX = roundValue(activeTabGroup.currentX + singleSpaceWidth);
48930
+ }
48931
+ appendSegment(
48932
+ currentLine.segments,
48933
+ runIndex,
48934
+ spaceStartChar,
48935
+ spaceEndChar,
48936
+ singleSpaceWidth,
48937
+ spaceExplicitX
48938
+ );
48650
48939
  currentLine.spaceCount += 1;
48651
48940
  }
48652
48941
  }
@@ -48794,7 +49083,7 @@ async function measureParagraphBlock(block, maxWidth) {
48794
49083
  const totalWidthWithWord = currentLine.width + boundarySpacing + wordCommitWidth + // Safe cast: only TextRuns produce word segments from split(), other run types are handled earlier
48795
49084
  (shouldIncludeDelimiterSpace ? run.letterSpacing ?? 0 : 0);
48796
49085
  const availableWidth = currentLine.maxWidth - WIDTH_FUDGE_PX2;
48797
- let shouldBreak = currentLine.width + boundarySpacing + wordOnlyWidth > availableWidth && currentLine.width > 0 && !isTocEntry;
49086
+ let shouldBreak = !inActiveTabGroup && currentLine.width + boundarySpacing + wordOnlyWidth > availableWidth && currentLine.width > 0 && !isTocEntry;
48798
49087
  let compressedWidth = null;
48799
49088
  if (shouldBreak && justifyAlignment) {
48800
49089
  const isLastNonEmptyWordInSegment = wordIndex === lastNonEmptyWordIndex;
@@ -48859,15 +49148,14 @@ async function measureParagraphBlock(block, maxWidth) {
48859
49148
  currentLine.width = roundValue(currentLine.width + boundarySpacing + wordOnlyWidth);
48860
49149
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run);
48861
49150
  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
- );
49151
+ let explicitXHere;
49152
+ if (inActiveTabGroup && activeTabGroup) {
49153
+ explicitXHere = activeTabGroup.currentX;
49154
+ activeTabGroup.currentX = roundValue(activeTabGroup.currentX + wordOnlyWidth);
49155
+ } else if (wordIndex === 0 && segmentStartX !== void 0) {
49156
+ explicitXHere = segmentStartX;
49157
+ }
49158
+ appendSegment(currentLine.segments, runIndex, wordStartChar, wordEndNoSpace, wordOnlyWidth, explicitXHere);
48871
49159
  trimTrailingWrapSpaces(currentLine);
48872
49160
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
48873
49161
  const lineBase = currentLine;
@@ -48882,8 +49170,13 @@ async function measureParagraphBlock(block, maxWidth) {
48882
49170
  }
48883
49171
  const newToChar = shouldIncludeDelimiterSpace ? wordEndWithSpace : wordEndNoSpace;
48884
49172
  currentLine.toChar = newToChar;
48885
- const useExplicitX = wordIndex === 0 && segmentStartX !== void 0;
48886
- const explicitX = useExplicitX ? segmentStartX : void 0;
49173
+ let explicitX;
49174
+ if (inActiveTabGroup && activeTabGroup) {
49175
+ explicitX = activeTabGroup.currentX;
49176
+ activeTabGroup.currentX = roundValue(activeTabGroup.currentX + wordCommitWidth);
49177
+ } else if (wordIndex === 0 && segmentStartX !== void 0) {
49178
+ explicitX = segmentStartX;
49179
+ }
48887
49180
  const targetWidth = compressedWidth != null ? compressedWidth : currentLine.width + boundarySpacing + wordCommitWidth + (shouldIncludeDelimiterSpace ? run.letterSpacing ?? 0 : 0);
48888
49181
  if (compressedWidth != null) {
48889
49182
  currentLine.naturalWidth = roundValue(totalWidthWithWord);
@@ -48905,6 +49198,12 @@ async function measureParagraphBlock(block, maxWidth) {
48905
49198
  }
48906
49199
  }
48907
49200
  lastAppliedTabAlign = null;
49201
+ if (activeTabGroup && runIndex + 1 >= activeTabGroup.measure.endRunIndex) {
49202
+ if (currentLine && activeTabGroup.val === "end") {
49203
+ currentLine.width = roundValue(activeTabGroup.target);
49204
+ }
49205
+ activeTabGroup = null;
49206
+ }
48908
49207
  if (!isLastSegment) {
48909
49208
  pendingTabAlignment = null;
48910
49209
  if (!currentLine) {
@@ -53234,7 +53533,26 @@ class PresentationEditor extends EventEmitter {
53234
53533
  const firstPageInSection = sectionFirstPageNumbers.get(sectionIndex);
53235
53534
  const sectionPageNumber = typeof firstPageInSection === "number" ? pageNumber - firstPageInSection + 1 : pageNumber;
53236
53535
  const headerFooterType = multiSectionId ? getHeaderFooterTypeForSection(pageNumber, sectionIndex, multiSectionId, { kind, sectionPageNumber }) : getHeaderFooterType(pageNumber, legacyIdentifier, { kind });
53237
- const sectionRId = page?.sectionRefs && kind === "header" ? page.sectionRefs.headerRefs?.[headerFooterType] ?? void 0 : page?.sectionRefs && kind === "footer" ? page.sectionRefs.footerRefs?.[headerFooterType] ?? void 0 : void 0;
53536
+ let sectionRId;
53537
+ if (page?.sectionRefs && kind === "header") {
53538
+ sectionRId = page.sectionRefs.headerRefs?.[headerFooterType];
53539
+ if (!sectionRId && headerFooterType && headerFooterType !== "default" && sectionIndex > 0 && multiSectionId) {
53540
+ const prevSectionIds = multiSectionId.sectionHeaderIds.get(sectionIndex - 1);
53541
+ sectionRId = prevSectionIds?.[headerFooterType] ?? void 0;
53542
+ }
53543
+ if (!sectionRId && headerFooterType !== "default") {
53544
+ sectionRId = page.sectionRefs.headerRefs?.default;
53545
+ }
53546
+ } else if (page?.sectionRefs && kind === "footer") {
53547
+ sectionRId = page.sectionRefs.footerRefs?.[headerFooterType];
53548
+ if (!sectionRId && headerFooterType && headerFooterType !== "default" && sectionIndex > 0 && multiSectionId) {
53549
+ const prevSectionIds = multiSectionId.sectionFooterIds.get(sectionIndex - 1);
53550
+ sectionRId = prevSectionIds?.[headerFooterType] ?? void 0;
53551
+ }
53552
+ if (!sectionRId && headerFooterType !== "default") {
53553
+ sectionRId = page.sectionRefs.footerRefs?.default;
53554
+ }
53555
+ }
53238
53556
  if (!headerFooterType) {
53239
53557
  return null;
53240
53558
  }