@harbour-enterprises/superdoc 1.6.2-next.1 → 1.7.0-next.10

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,6 +1,6 @@
1
1
  import { B as Buffer$2 } from "./jszip-B1fkPkPJ.es.js";
2
2
  import { t as twipsToInches, i as inchesToTwips, p as ptToTwips, l as linesToTwips, a as twipsToLines, b as pixelsToTwips, h as halfPointToPoints, c as twipsToPixels$2, d as convertSizeToCSS, e as inchesToPixels } from "./helpers-C8e9wR5l.es.js";
3
- import { g as generateDocxRandomId, T as TextSelection$1, o as objectIncludes, w as wrapTextsInRuns, D as DOMParser$1, c as createDocFromMarkdown, a as createDocFromHTML, b as chainableEditorState, d as convertMarkdownToHTML, f as findParentNode, e as findParentNodeClosestToPos, h as generateRandom32BitHex, i as generateRandomSigned32BitIntStrId, P as PluginKey, j as Plugin, M as Mapping, N as NodeSelection, k as Selection, l as Slice, m as DOMSerializer, F as Fragment, n as Mark$1, p as dropPoint, A as AllSelection, q as Schema$1, s as canSplit, t as resolveRunProperties, u as encodeMarksFromRPr, v as liftTarget, x as canJoin, y as joinPoint, z as replaceStep$1, R as ReplaceAroundStep$1, B as htmlHandler, C as ReplaceStep, E as getResolvedParagraphProperties, G as changeListLevel, H as isList$1, I as updateNumberingProperties, L as ListHelpers, J as inputRulesPlugin, K as TrackDeleteMarkName$1, O as TrackInsertMarkName$1, Q as TrackFormatMarkName$1, U as AddMarkStep, V as RemoveMarkStep, W as CommandService, S as SuperConverter, X as EditorState, Y as unflattenListsInHtml, Z as SelectionRange, _ as Transform, $ as createOoxmlResolver, a0 as translator, a1 as translator$1, a2 as resolveDocxFontFamily, a3 as combineIndentProperties, a4 as _getReferencedTableStyles, a5 as decodeRPrFromMarks, a6 as calculateResolvedParagraphProperties, a7 as encodeCSSFromPPr, a8 as encodeCSSFromRPr, a9 as generateOrderedListIndex, aa as docxNumberingHelpers, ab as InputRule, ac as insertNewRelationship, ad as kebabCase$1, ae as getUnderlineCssString } from "./SuperConverter-C0XQKCFE.es.js";
3
+ import { g as generateDocxRandomId, T as TextSelection$1, o as objectIncludes, w as wrapTextsInRuns, D as DOMParser$1, c as createDocFromMarkdown, a as createDocFromHTML, b as chainableEditorState, d as convertMarkdownToHTML, f as findParentNode, e as findParentNodeClosestToPos, h as generateRandom32BitHex, i as generateRandomSigned32BitIntStrId, P as PluginKey, j as Plugin, M as Mapping, N as NodeSelection, k as Selection, l as Slice, m as DOMSerializer, F as Fragment, n as Mark$1, p as dropPoint, A as AllSelection, q as Schema$1, s as canSplit, t as resolveRunProperties, u as encodeMarksFromRPr, v as liftTarget, x as canJoin, y as joinPoint, z as replaceStep$1, R as ReplaceAroundStep$1, B as htmlHandler, C as ReplaceStep, E as getResolvedParagraphProperties, G as changeListLevel, H as isList$1, I as updateNumberingProperties, L as ListHelpers, J as inputRulesPlugin, K as TrackDeleteMarkName$1, O as TrackInsertMarkName$1, Q as TrackFormatMarkName$1, U as AddMarkStep, V as RemoveMarkStep, W as CommandService, S as SuperConverter, X as EditorState, Y as unflattenListsInHtml, Z as SelectionRange, _ as Transform, $ as createOoxmlResolver, a0 as translator, a1 as translator$1, a2 as resolveDocxFontFamily, a3 as combineIndentProperties, a4 as _getReferencedTableStyles, a5 as decodeRPrFromMarks, a6 as calculateResolvedParagraphProperties, a7 as encodeCSSFromPPr, a8 as encodeCSSFromRPr, a9 as generateOrderedListIndex, aa as docxNumberingHelpers, ab as InputRule, ac as insertNewRelationship, ad as kebabCase$1, ae as getUnderlineCssString } from "./SuperConverter-CsrXPsVn.es.js";
4
4
  import { p as process$1, r as ref, C as global$1, c as computed, E as createElementBlock, F as Fragment$1, S as renderList, O as withModifiers, G as openBlock, P as normalizeClass, M as createCommentVNode, H as toDisplayString, K as createBaseVNode, U as createApp, f as onMounted, X as onUnmounted, R as withDirectives, v as unref, Y as vModelText, y as nextTick, L as normalizeStyle, u as watch, Z as withKeys, _ as createTextVNode, I as createVNode, h as h$1, $ as readonly, s as getCurrentInstance, o as onBeforeUnmount, j as reactive, b as onBeforeMount, i as inject, a0 as onActivated, a1 as onDeactivated, a2 as Comment, d as defineComponent, a as provide, g as Teleport, t as toRef, a3 as renderSlot, a4 as isVNode, D as shallowRef, w as watchEffect, T as Transition, a5 as mergeProps, a6 as vShow, a7 as cloneVNode, a8 as Text$2, m as markRaw, N as createBlock, J as withCtx, a9 as useCssVars, V as resolveDynamicComponent, aa as normalizeProps, ab as guardReactiveProps } from "./vue-BnBKJwCW.es.js";
5
5
  import "./jszip.min-DCl8qkFO.es.js";
6
6
  import { E as EventEmitter$1 } from "./eventemitter3-CwrdEv8r.es.js";
@@ -12927,9 +12927,43 @@ const prepareCommentsForExport = (doc2, tr, schema, comments = []) => {
12927
12927
  comments.forEach((c2) => {
12928
12928
  commentMap.set(c2.commentId, c2);
12929
12929
  });
12930
+ const trackedChangeSpanById = /* @__PURE__ */ new Map();
12931
+ const trackedChangeMarksById = /* @__PURE__ */ new Map();
12932
+ doc2.descendants((node, pos) => {
12933
+ const trackedChangeMark = node.marks?.find((mark) => TRACK_CHANGE_MARKS$1.includes(mark.type.name));
12934
+ if (!trackedChangeMark) return;
12935
+ const trackedChangeId = trackedChangeMark.attrs?.id;
12936
+ if (!trackedChangeId) return;
12937
+ const existing = trackedChangeSpanById.get(trackedChangeId);
12938
+ const startPos = pos;
12939
+ const endPos = pos + node.nodeSize;
12940
+ if (!existing) {
12941
+ trackedChangeSpanById.set(trackedChangeId, { startPos, endPos });
12942
+ } else {
12943
+ existing.startPos = Math.min(existing.startPos, startPos);
12944
+ existing.endPos = Math.max(existing.endPos, endPos);
12945
+ }
12946
+ const marksEntry = trackedChangeMarksById.get(trackedChangeId) || {};
12947
+ if (trackedChangeMark.type?.name === TrackInsertMarkName$1 && !marksEntry.insertMark) {
12948
+ marksEntry.insertMark = trackedChangeMark;
12949
+ }
12950
+ if (trackedChangeMark.type?.name === TrackDeleteMarkName$1 && !marksEntry.deleteMark) {
12951
+ marksEntry.deleteMark = trackedChangeMark;
12952
+ }
12953
+ trackedChangeMarksById.set(trackedChangeId, marksEntry);
12954
+ });
12955
+ const getThreadingParentId = (comment) => {
12956
+ if (!comment) return comment?.parentCommentId;
12957
+ const usesRangeThreading = comment.threadingStyleOverride === "range-based" || comment.threadingMethod === "range-based" || comment.originalXmlStructure?.hasCommentsExtended === false;
12958
+ if (usesRangeThreading && comment.threadingParentCommentId) {
12959
+ return comment.threadingParentCommentId;
12960
+ }
12961
+ return comment.parentCommentId;
12962
+ };
12930
12963
  const startNodes = [];
12931
12964
  const endNodes = [];
12932
12965
  const seen = /* @__PURE__ */ new Set();
12966
+ const trackedChangeCommentMeta = /* @__PURE__ */ new Map();
12933
12967
  doc2.descendants((node, pos) => {
12934
12968
  const commentMarks = node.marks?.filter((mark) => mark.type.name === CommentMarkName$1) || [];
12935
12969
  commentMarks.forEach((commentMark) => {
@@ -12937,9 +12971,21 @@ const prepareCommentsForExport = (doc2, tr, schema, comments = []) => {
12937
12971
  const { commentId } = attrs;
12938
12972
  if (commentId === "pending") return;
12939
12973
  if (seen.has(commentId)) return;
12940
- seen.add(commentId);
12941
12974
  const comment = commentMap.get(commentId);
12942
- const parentCommentId = comment?.parentCommentId;
12975
+ const parentCommentId = getThreadingParentId(comment);
12976
+ const trackedChangeMark = node.marks?.find((mark) => TRACK_CHANGE_MARKS$1.includes(mark.type.name));
12977
+ const trackedChangeId = trackedChangeMark?.attrs?.id;
12978
+ const trackedSpan = trackedChangeId ? trackedChangeSpanById.get(trackedChangeId) : null;
12979
+ if (trackedSpan) {
12980
+ trackedChangeCommentMeta.set(commentId, {
12981
+ comment,
12982
+ parentCommentId,
12983
+ trackedChangeId
12984
+ });
12985
+ seen.add(commentId);
12986
+ return;
12987
+ }
12988
+ seen.add(commentId);
12943
12989
  const commentStartNodeAttrs = getPreparedComment(commentMark.attrs);
12944
12990
  const startNode = schema.nodes.commentRangeStart.create(commentStartNodeAttrs);
12945
12991
  startNodes.push({
@@ -12955,7 +13001,7 @@ const prepareCommentsForExport = (doc2, tr, schema, comments = []) => {
12955
13001
  commentId,
12956
13002
  parentCommentId
12957
13003
  });
12958
- const childComments = comments.filter((c2) => c2.parentCommentId === commentId).sort((a, b2) => a.createdTime - b2.createdTime);
13004
+ const childComments = comments.filter((c2) => getThreadingParentId(c2) === commentId).sort((a, b2) => a.createdTime - b2.createdTime);
12959
13005
  childComments.forEach((c2) => {
12960
13006
  if (seen.has(c2.commentId)) return;
12961
13007
  seen.add(c2.commentId);
@@ -12968,47 +13014,74 @@ const prepareCommentsForExport = (doc2, tr, schema, comments = []) => {
12968
13014
  pos,
12969
13015
  node: childStartNode,
12970
13016
  commentId: c2.commentId,
12971
- parentCommentId: c2.parentCommentId
13017
+ parentCommentId: getThreadingParentId(c2)
12972
13018
  });
12973
13019
  const childEndNode = schema.nodes.commentRangeEnd.create(childMark);
12974
13020
  endNodes.push({
12975
13021
  pos: pos + node.nodeSize,
12976
13022
  node: childEndNode,
12977
13023
  commentId: c2.commentId,
12978
- parentCommentId: c2.parentCommentId
13024
+ parentCommentId: getThreadingParentId(c2)
12979
13025
  });
12980
13026
  });
12981
13027
  });
12982
- const trackedChangeMark = node.marks?.find((mark) => TRACK_CHANGE_MARKS$1.includes(mark.type.name));
12983
- if (trackedChangeMark) {
12984
- const trackedChangeId = trackedChangeMark.attrs?.id;
12985
- if (trackedChangeId) {
12986
- const childComments = comments.filter((c2) => c2.parentCommentId === trackedChangeId && !c2.trackedChange).sort((a, b2) => a.createdTime - b2.createdTime);
12987
- childComments.forEach((c2) => {
12988
- if (seen.has(c2.commentId)) return;
12989
- seen.add(c2.commentId);
12990
- const childMark = getPreparedComment({
12991
- commentId: c2.commentId,
12992
- internal: c2.isInternal
12993
- });
12994
- const childStartNode = schema.nodes.commentRangeStart.create(childMark);
12995
- startNodes.push({
12996
- pos,
12997
- node: childStartNode,
12998
- commentId: c2.commentId,
12999
- parentCommentId: c2.parentCommentId
13000
- });
13001
- const childEndNode = schema.nodes.commentRangeEnd.create(childMark);
13002
- endNodes.push({
13003
- pos: pos + node.nodeSize,
13004
- node: childEndNode,
13005
- commentId: c2.commentId,
13006
- parentCommentId: c2.parentCommentId
13007
- });
13008
- });
13009
- }
13010
- }
13011
13028
  });
13029
+ if (trackedChangeSpanById.size > 0) {
13030
+ trackedChangeCommentMeta.forEach(({ comment, parentCommentId, trackedChangeId }) => {
13031
+ if (!comment || !trackedChangeSpanById.has(trackedChangeId)) return;
13032
+ const span = trackedChangeSpanById.get(trackedChangeId);
13033
+ if (!span) return;
13034
+ const childMark = getPreparedComment({
13035
+ commentId: comment.commentId,
13036
+ internal: comment.isInternal
13037
+ });
13038
+ const trackedMarks = trackedChangeMarksById.get(trackedChangeId) || {};
13039
+ const startMarks = trackedMarks.insertMark ? [trackedMarks.insertMark] : trackedMarks.deleteMark ? [trackedMarks.deleteMark] : void 0;
13040
+ const endMarks = trackedMarks.deleteMark ? [trackedMarks.deleteMark] : trackedMarks.insertMark ? [trackedMarks.insertMark] : void 0;
13041
+ const childStartNode = schema.nodes.commentRangeStart.create(childMark, null, startMarks);
13042
+ startNodes.push({
13043
+ pos: span.startPos,
13044
+ node: childStartNode,
13045
+ commentId: comment.commentId,
13046
+ parentCommentId
13047
+ });
13048
+ const childEndNode = schema.nodes.commentRangeEnd.create(childMark, null, endMarks);
13049
+ endNodes.push({
13050
+ pos: span.endPos,
13051
+ node: childEndNode,
13052
+ commentId: comment.commentId,
13053
+ parentCommentId
13054
+ });
13055
+ });
13056
+ comments.filter((comment) => trackedChangeSpanById.has(comment.parentCommentId) && !comment.trackedChange).sort((a, b2) => a.createdTime - b2.createdTime).forEach((comment) => {
13057
+ if (seen.has(comment.commentId)) return;
13058
+ seen.add(comment.commentId);
13059
+ const span = trackedChangeSpanById.get(comment.parentCommentId);
13060
+ if (!span) return;
13061
+ const childMark = getPreparedComment({
13062
+ commentId: comment.commentId,
13063
+ internal: comment.isInternal
13064
+ });
13065
+ const parentCommentId = getThreadingParentId(comment);
13066
+ const trackedMarks = trackedChangeMarksById.get(comment.parentCommentId) || {};
13067
+ const startMarks = trackedMarks.insertMark ? [trackedMarks.insertMark] : trackedMarks.deleteMark ? [trackedMarks.deleteMark] : void 0;
13068
+ const endMarks = trackedMarks.deleteMark ? [trackedMarks.deleteMark] : trackedMarks.insertMark ? [trackedMarks.insertMark] : void 0;
13069
+ const childStartNode = schema.nodes.commentRangeStart.create(childMark, null, startMarks);
13070
+ startNodes.push({
13071
+ pos: span.startPos,
13072
+ node: childStartNode,
13073
+ commentId: comment.commentId,
13074
+ parentCommentId
13075
+ });
13076
+ const childEndNode = schema.nodes.commentRangeEnd.create(childMark, null, endMarks);
13077
+ endNodes.push({
13078
+ pos: span.endPos,
13079
+ node: childEndNode,
13080
+ commentId: comment.commentId,
13081
+ parentCommentId
13082
+ });
13083
+ });
13084
+ }
13012
13085
  startNodes.sort((a, b2) => {
13013
13086
  if (a.pos !== b2.pos) return a.pos - b2.pos;
13014
13087
  const aIsParentOfB = a.commentId === b2.parentCommentId;
@@ -15771,7 +15844,7 @@ const canUseDOM = () => {
15771
15844
  return false;
15772
15845
  }
15773
15846
  };
15774
- const summaryVersion = "1.6.2-next.1";
15847
+ const summaryVersion = "1.7.0-next.10";
15775
15848
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
15776
15849
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
15777
15850
  function mapAttributes(attrs) {
@@ -18064,19 +18137,22 @@ class Editor extends EventEmitter {
18064
18137
  }
18065
18138
  if (comments.length) {
18066
18139
  const commentsXml = this.converter.schemaToXml(this.converter.convertedXml["word/comments.xml"].elements[0]);
18067
- const commentsExtendedXml = this.converter.schemaToXml(
18068
- this.converter.convertedXml["word/commentsExtended.xml"].elements[0]
18069
- );
18070
- const commentsExtensibleXml = this.converter.schemaToXml(
18071
- this.converter.convertedXml["word/commentsExtensible.xml"].elements[0]
18072
- );
18073
- const commentsIdsXml = this.converter.schemaToXml(
18074
- this.converter.convertedXml["word/commentsIds.xml"].elements[0]
18075
- );
18076
18140
  updatedDocs["word/comments.xml"] = String(commentsXml);
18077
- updatedDocs["word/commentsExtended.xml"] = String(commentsExtendedXml);
18078
- updatedDocs["word/commentsExtensible.xml"] = String(commentsExtensibleXml);
18079
- updatedDocs["word/commentsIds.xml"] = String(commentsIdsXml);
18141
+ const commentsExtended = this.converter.convertedXml["word/commentsExtended.xml"];
18142
+ if (commentsExtended?.elements?.[0]) {
18143
+ const commentsExtendedXml = this.converter.schemaToXml(commentsExtended.elements[0]);
18144
+ updatedDocs["word/commentsExtended.xml"] = String(commentsExtendedXml);
18145
+ }
18146
+ const commentsExtensible = this.converter.convertedXml["word/commentsExtensible.xml"];
18147
+ if (commentsExtensible?.elements?.[0]) {
18148
+ const commentsExtensibleXml = this.converter.schemaToXml(commentsExtensible.elements[0]);
18149
+ updatedDocs["word/commentsExtensible.xml"] = String(commentsExtensibleXml);
18150
+ }
18151
+ const commentsIds = this.converter.convertedXml["word/commentsIds.xml"];
18152
+ if (commentsIds?.elements?.[0]) {
18153
+ const commentsIdsXml = this.converter.schemaToXml(commentsIds.elements[0]);
18154
+ updatedDocs["word/commentsIds.xml"] = String(commentsIdsXml);
18155
+ }
18080
18156
  }
18081
18157
  const zipper = new DocxZipper();
18082
18158
  if (getUpdatedDocs) {
@@ -18438,7 +18514,7 @@ class Editor extends EventEmitter {
18438
18514
  * Process collaboration migrations
18439
18515
  */
18440
18516
  processCollaborationMigrations() {
18441
- console.debug("[checkVersionMigrations] Current editor version", "1.6.2-next.1");
18517
+ console.debug("[checkVersionMigrations] Current editor version", "1.7.0-next.10");
18442
18518
  if (!this.options.ydoc) return;
18443
18519
  const metaMap = this.options.ydoc.getMap("meta");
18444
18520
  let docVersion = metaMap.get("version");
@@ -20530,18 +20606,22 @@ class EpochPositionMapper {
20530
20606
  function computeTabStops$1(context) {
20531
20607
  const { explicitStops, defaultTabInterval, paragraphIndent } = context;
20532
20608
  const leftIndent = paragraphIndent.left ?? 0;
20609
+ const hanging = paragraphIndent.hanging ?? 0;
20610
+ const effectiveMinIndent = Math.max(0, leftIndent - hanging);
20533
20611
  const clearPositions = explicitStops.filter((stop) => stop.val === "clear").map((stop) => stop.pos);
20534
- const stops = explicitStops.filter((stop) => stop.val !== "clear");
20535
- const maxExplicit = stops.reduce((max2, stop) => Math.max(max2, stop.pos), 0);
20536
- const hasExplicit = stops.length > 0;
20537
- const defaultStart = hasExplicit ? Math.max(maxExplicit, leftIndent ?? 0) : 0;
20538
- let pos = hasExplicit ? defaultStart : 0;
20539
- const targetLimit = Math.max(defaultStart, leftIndent ?? 0) + 14400;
20612
+ const filteredExplicitStops = explicitStops.filter((stop) => stop.val !== "clear").filter((stop) => stop.pos >= effectiveMinIndent);
20613
+ const maxExplicit = filteredExplicitStops.reduce((max2, stop) => Math.max(max2, stop.pos), 0);
20614
+ const hasExplicit = filteredExplicitStops.length > 0;
20615
+ const stops = [...filteredExplicitStops];
20616
+ const defaultStart = hasExplicit ? Math.max(maxExplicit, leftIndent) : 0;
20617
+ let pos = defaultStart;
20618
+ const targetLimit = Math.max(defaultStart, leftIndent) + 14400;
20540
20619
  while (pos < targetLimit) {
20541
20620
  pos += defaultTabInterval;
20542
- const hasExplicitStop = stops.some((s) => Math.abs(s.pos - pos) < 20);
20621
+ const hasExplicitStop = filteredExplicitStops.some((s) => Math.abs(s.pos - pos) < 20);
20543
20622
  const hasClearStop = clearPositions.some((clearPos) => Math.abs(clearPos - pos) < 20);
20544
- if (!hasExplicitStop && !hasClearStop) {
20623
+ const isValidDefault = pos >= leftIndent;
20624
+ if (!hasExplicitStop && !hasClearStop && isValidDefault) {
20545
20625
  stops.push({
20546
20626
  val: "start",
20547
20627
  pos,
@@ -20549,7 +20629,7 @@ function computeTabStops$1(context) {
20549
20629
  });
20550
20630
  }
20551
20631
  }
20552
- return stops.filter((stop) => stop.pos >= leftIndent).sort((a, b2) => a.pos - b2.pos);
20632
+ return stops.sort((a, b2) => a.pos - b2.pos);
20553
20633
  }
20554
20634
  function layoutWithTabs(runs, stops, lineWidth, options = {}) {
20555
20635
  const result = [];
@@ -24492,6 +24572,69 @@ const resolveTableCellBorders = (tableBorders, rowIndex, colIndex, totalRows, to
24492
24572
  right: borderValueToSpec(isLastCol ? tableBorders?.right : null)
24493
24573
  };
24494
24574
  };
24575
+ const clampNumber = (value, min2, max2) => Math.min(max2, Math.max(min2, value));
24576
+ const mergeSortedSegments = (segments) => {
24577
+ if (segments.length <= 1) return segments;
24578
+ const merged = [];
24579
+ let current = segments[0];
24580
+ for (let i = 1; i < segments.length; i += 1) {
24581
+ const next = segments[i];
24582
+ if (next.start <= current.end) {
24583
+ current = { start: current.start, end: Math.max(current.end, next.end) };
24584
+ continue;
24585
+ }
24586
+ merged.push(current);
24587
+ current = next;
24588
+ }
24589
+ merged.push(current);
24590
+ return merged;
24591
+ };
24592
+ const applySquareWrapExclusionsToLines = (renderedLines, exclusions, contentWidthPx, alignmentOffsetY) => {
24593
+ if (renderedLines.length === 0 || exclusions.length === 0 || contentWidthPx <= 0) return;
24594
+ renderedLines.forEach((line) => {
24595
+ const paddingLeft = line.el.style.paddingLeft;
24596
+ const paddingRight = line.el.style.paddingRight;
24597
+ if (paddingLeft && paddingLeft !== "0px" || paddingRight && paddingRight !== "0px") {
24598
+ return;
24599
+ }
24600
+ const lineTop = line.top + alignmentOffsetY;
24601
+ const lineBottom = lineTop + line.height;
24602
+ const excludedSegments = [];
24603
+ for (const ex of exclusions) {
24604
+ if (lineBottom <= ex.top || lineTop >= ex.bottom) continue;
24605
+ if (ex.wrapText !== "bothSides") continue;
24606
+ const start2 = clampNumber(ex.left, 0, contentWidthPx);
24607
+ const end2 = clampNumber(ex.right, 0, contentWidthPx);
24608
+ if (end2 <= start2) continue;
24609
+ excludedSegments.push({ start: start2, end: end2 });
24610
+ }
24611
+ if (excludedSegments.length === 0) return;
24612
+ excludedSegments.sort((a, b2) => a.start - b2.start);
24613
+ const merged = mergeSortedSegments(excludedSegments);
24614
+ let bestStart = 0;
24615
+ let bestWidth = 0;
24616
+ let cursor = 0;
24617
+ for (const seg of merged) {
24618
+ const gapWidth = seg.start - cursor;
24619
+ if (gapWidth > bestWidth) {
24620
+ bestStart = cursor;
24621
+ bestWidth = gapWidth;
24622
+ }
24623
+ cursor = Math.max(cursor, seg.end);
24624
+ }
24625
+ const tailWidth = contentWidthPx - cursor;
24626
+ if (tailWidth > bestWidth) {
24627
+ bestStart = cursor;
24628
+ bestWidth = tailWidth;
24629
+ }
24630
+ if (bestWidth <= 0 || bestStart === 0 && bestWidth >= contentWidthPx) return;
24631
+ const marginLeft = bestStart;
24632
+ const marginRight = Math.max(0, contentWidthPx - (bestStart + bestWidth));
24633
+ line.el.style.boxSizing = "border-box";
24634
+ line.el.style.marginLeft = `${marginLeft}px`;
24635
+ line.el.style.marginRight = `${marginRight}px`;
24636
+ });
24637
+ };
24495
24638
  function isStructuredContentMetadata(sdt) {
24496
24639
  return sdt !== null && sdt !== void 0 && typeof sdt === "object" && "type" in sdt && sdt.type === "structuredContent";
24497
24640
  }
@@ -24604,6 +24747,50 @@ function renderListMarker(params2) {
24604
24747
  lineContainer.appendChild(lineEl);
24605
24748
  return lineContainer;
24606
24749
  }
24750
+ function applyTableCellLineIndentation(params2) {
24751
+ const {
24752
+ lineEl,
24753
+ line,
24754
+ indent,
24755
+ indentLeftPx,
24756
+ hasListMarkerLayout,
24757
+ lineIndex,
24758
+ localStartLine,
24759
+ suppressFirstLineIndent
24760
+ } = params2;
24761
+ const paraIndentLeft = indent?.left ?? 0;
24762
+ const paraIndentRight = indent?.right ?? 0;
24763
+ const firstLineOffset = suppressFirstLineIndent ? 0 : (indent?.firstLine ?? 0) - (indent?.hanging ?? 0);
24764
+ const isFirstLine = lineIndex === 0 && localStartLine === 0;
24765
+ const hasExplicitSegmentPositioning = line.segments?.some((seg) => seg.x !== void 0) ?? false;
24766
+ if (hasListMarkerLayout && indentLeftPx) {
24767
+ if (!hasExplicitSegmentPositioning) {
24768
+ lineEl.style.paddingLeft = `${indentLeftPx}px`;
24769
+ }
24770
+ } else {
24771
+ if (hasExplicitSegmentPositioning) {
24772
+ if (isFirstLine && firstLineOffset !== 0) {
24773
+ const effectiveLeftIndent = paraIndentLeft < 0 ? 0 : paraIndentLeft;
24774
+ const adjustedPadding = effectiveLeftIndent + firstLineOffset;
24775
+ if (adjustedPadding > 0) {
24776
+ lineEl.style.paddingLeft = `${adjustedPadding}px`;
24777
+ }
24778
+ }
24779
+ } else if (paraIndentLeft && paraIndentLeft > 0) {
24780
+ lineEl.style.paddingLeft = `${paraIndentLeft}px`;
24781
+ } else if (!isFirstLine && indent?.hanging && indent.hanging > 0 && (paraIndentLeft == null || paraIndentLeft >= 0)) {
24782
+ lineEl.style.paddingLeft = `${indent.hanging}px`;
24783
+ }
24784
+ }
24785
+ if (paraIndentRight && paraIndentRight > 0) {
24786
+ lineEl.style.paddingRight = `${paraIndentRight}px`;
24787
+ }
24788
+ if (isFirstLine && firstLineOffset && !hasExplicitSegmentPositioning) {
24789
+ lineEl.style.textIndent = `${firstLineOffset}px`;
24790
+ } else if (firstLineOffset && hasExplicitSegmentPositioning) {
24791
+ lineEl.style.textIndent = "0px";
24792
+ }
24793
+ }
24607
24794
  const applyInlineStyles = (el, styles) => {
24608
24795
  Object.entries(styles).forEach(([key2, value]) => {
24609
24796
  if (value != null && value !== "" && key2 in el.style) {
@@ -24776,6 +24963,7 @@ const renderTableCell = (deps) => {
24776
24963
  content.style.justifyContent = "flex-start";
24777
24964
  }
24778
24965
  cellEl.appendChild(content);
24966
+ content.style.zIndex = "0";
24779
24967
  const blockLineCounts = [];
24780
24968
  for (let i = 0; i < Math.min(blockMeasures.length, cellBlocks.length); i++) {
24781
24969
  const bm = blockMeasures[i];
@@ -24788,6 +24976,12 @@ const renderTableCell = (deps) => {
24788
24976
  const totalLines = blockLineCounts.reduce((a, b2) => a + b2, 0);
24789
24977
  const globalFromLine = fromLine ?? 0;
24790
24978
  const globalToLine = toLine === -1 || toLine === void 0 ? totalLines : toLine;
24979
+ const contentWidthPx = Math.max(0, cellMeasure.width - paddingLeft - paddingRight);
24980
+ const contentHeightPx = Math.max(0, rowHeight - paddingTop - paddingBottom);
24981
+ const paragraphTopById = /* @__PURE__ */ new Map();
24982
+ let flowCursorY = 0;
24983
+ const anchoredBlocks = [];
24984
+ const renderedLines = [];
24791
24985
  let cumulativeLineCount = 0;
24792
24986
  for (let i = 0; i < Math.min(blockMeasures.length, cellBlocks.length); i++) {
24793
24987
  const blockMeasure = blockMeasures[i];
@@ -24810,9 +25004,14 @@ const renderTableCell = (deps) => {
24810
25004
  });
24811
25005
  tableWrapper.appendChild(tableEl);
24812
25006
  content.appendChild(tableWrapper);
25007
+ flowCursorY += tableMeasure.totalHeight;
24813
25008
  continue;
24814
25009
  }
24815
25010
  if (blockMeasure.kind === "image" && block?.kind === "image") {
25011
+ if (block.anchor?.isAnchored) {
25012
+ anchoredBlocks.push({ block, measure: blockMeasure });
25013
+ continue;
25014
+ }
24816
25015
  const imageWrapper = doc2.createElement("div");
24817
25016
  imageWrapper.style.position = "relative";
24818
25017
  imageWrapper.style.width = `${blockMeasure.width}px`;
@@ -24835,9 +25034,14 @@ const renderTableCell = (deps) => {
24835
25034
  imgEl.style.display = "block";
24836
25035
  imageWrapper.appendChild(imgEl);
24837
25036
  content.appendChild(imageWrapper);
25037
+ flowCursorY += blockMeasure.height;
24838
25038
  continue;
24839
25039
  }
24840
25040
  if (blockMeasure.kind === "drawing" && block?.kind === "drawing") {
25041
+ if (block.anchor?.isAnchored) {
25042
+ anchoredBlocks.push({ block, measure: blockMeasure });
25043
+ continue;
25044
+ }
24841
25045
  const drawingWrapper = doc2.createElement("div");
24842
25046
  drawingWrapper.style.position = "relative";
24843
25047
  drawingWrapper.style.width = `${blockMeasure.width}px`;
@@ -24880,16 +25084,19 @@ const renderTableCell = (deps) => {
24880
25084
  }
24881
25085
  drawingWrapper.appendChild(drawingInner);
24882
25086
  content.appendChild(drawingWrapper);
25087
+ flowCursorY += blockMeasure.height;
24883
25088
  continue;
24884
25089
  }
24885
25090
  if (blockMeasure.kind === "paragraph" && block?.kind === "paragraph") {
24886
25091
  const paragraphMeasure = blockMeasure;
24887
25092
  const lines = paragraphMeasure.lines;
24888
25093
  const blockLineCount = lines?.length || 0;
25094
+ paragraphTopById.set(block.id, flowCursorY);
24889
25095
  const wordLayout = block.attrs?.wordLayout ?? null;
24890
25096
  const markerLayout = wordLayout?.marker;
24891
25097
  const markerMeasure = paragraphMeasure.marker;
24892
25098
  const indentLeftPx = markerMeasure?.indentLeft ?? wordLayout?.indentLeftPx ?? (block.attrs?.indent && typeof block.attrs.indent.left === "number" ? block.attrs.indent.left : 0);
25099
+ const suppressFirstLineIndent = block.attrs?.suppressFirstLineIndent === true;
24893
25100
  const blockStartGlobal = cumulativeLineCount;
24894
25101
  const blockEndGlobal = cumulativeLineCount + blockLineCount;
24895
25102
  if (blockEndGlobal <= globalFromLine) {
@@ -24919,6 +25126,7 @@ const renderTableCell = (deps) => {
24919
25126
  for (let lineIdx = localStartLine; lineIdx < localEndLine && lineIdx < lines.length; lineIdx++) {
24920
25127
  const line = lines[lineIdx];
24921
25128
  const isLastLine = lineIdx === lines.length - 1;
25129
+ const lineTop = flowCursorY + renderedHeight;
24922
25130
  const lineEl = renderLine(
24923
25131
  block,
24924
25132
  line,
@@ -24938,35 +25146,20 @@ const renderTableCell = (deps) => {
24938
25146
  markerMeasure,
24939
25147
  indentLeftPx
24940
25148
  });
25149
+ renderedLines.push({ el: lineContainer, top: lineTop, height: line.lineHeight });
24941
25150
  paraWrapper.appendChild(lineContainer);
24942
25151
  } else {
24943
- if (markerLayout && indentLeftPx) {
24944
- lineEl.style.paddingLeft = `${indentLeftPx}px`;
24945
- } else {
24946
- const indent = block.attrs?.indent;
24947
- if (indent) {
24948
- const leftIndent = typeof indent.left === "number" ? indent.left : 0;
24949
- const hanging = typeof indent.hanging === "number" ? indent.hanging : 0;
24950
- const firstLine = typeof indent.firstLine === "number" ? indent.firstLine : 0;
24951
- const isFirstLine = lineIdx === 0 && localStartLine === 0;
24952
- const firstLineOffset = firstLine - hanging;
24953
- if (isFirstLine) {
24954
- if (leftIndent > 0) {
24955
- lineEl.style.paddingLeft = `${leftIndent}px`;
24956
- }
24957
- if (firstLineOffset !== 0) {
24958
- lineEl.style.textIndent = `${firstLineOffset}px`;
24959
- }
24960
- } else {
24961
- if (leftIndent > 0) {
24962
- lineEl.style.paddingLeft = `${leftIndent}px`;
24963
- }
24964
- }
24965
- if (typeof indent.right === "number" && indent.right > 0) {
24966
- lineEl.style.paddingRight = `${indent.right}px`;
24967
- }
24968
- }
24969
- }
25152
+ applyTableCellLineIndentation({
25153
+ lineEl,
25154
+ line,
25155
+ indent: block.attrs?.indent,
25156
+ indentLeftPx,
25157
+ hasListMarkerLayout: Boolean(markerLayout),
25158
+ lineIndex: lineIdx,
25159
+ localStartLine,
25160
+ suppressFirstLineIndent
25161
+ });
25162
+ renderedLines.push({ el: lineEl, top: lineTop, height: line.lineHeight });
24970
25163
  paraWrapper.appendChild(lineEl);
24971
25164
  }
24972
25165
  renderedHeight += line.lineHeight;
@@ -24979,15 +25172,124 @@ const renderTableCell = (deps) => {
24979
25172
  if (renderedHeight > 0) {
24980
25173
  paraWrapper.style.height = `${renderedHeight}px`;
24981
25174
  }
25175
+ flowCursorY += renderedHeight;
24982
25176
  if (renderedEntireBlock) {
24983
25177
  const spacingAfter = block.attrs?.spacing?.after;
24984
25178
  if (typeof spacingAfter === "number" && spacingAfter > 0) {
24985
25179
  paraWrapper.style.marginBottom = `${spacingAfter}px`;
25180
+ flowCursorY += spacingAfter;
24986
25181
  }
24987
25182
  }
24988
25183
  cumulativeLineCount += blockLineCount;
24989
25184
  }
24990
25185
  }
25186
+ const verticalAlign = cell?.attrs?.verticalAlign;
25187
+ const remainingSpace = contentHeightPx - flowCursorY;
25188
+ const alignmentOffsetY = verticalAlign === "center" ? Math.max(0, remainingSpace / 2) : verticalAlign === "bottom" ? Math.max(0, remainingSpace) : 0;
25189
+ const wrapExclusions = [];
25190
+ for (const entry of anchoredBlocks) {
25191
+ const anchoredBlock = entry.block;
25192
+ const anchoredMeasure = entry.measure;
25193
+ const anchor = anchoredBlock.anchor;
25194
+ if (!anchor || !anchor.isAnchored) {
25195
+ continue;
25196
+ }
25197
+ const objectWidth = anchoredMeasure.width;
25198
+ const objectHeight = anchoredMeasure.height;
25199
+ const left2 = anchor.offsetH ?? 0;
25200
+ const top2 = anchor.offsetV ?? 0;
25201
+ const behindDoc = anchor.behindDoc === true || anchoredBlock.wrap?.type === "None" && anchoredBlock.wrap?.behindDoc;
25202
+ const zIndex = anchoredBlock.kind === "drawing" && typeof anchoredBlock.zIndex === "number" ? anchoredBlock.zIndex : behindDoc ? -1 : 1;
25203
+ const wrap = anchoredBlock.wrap;
25204
+ if (!behindDoc && wrap?.type === "Square") {
25205
+ const wrapText = wrap.wrapText ?? "bothSides";
25206
+ const distLeft = anchoredBlock.padding?.left ?? 0;
25207
+ const distRight = anchoredBlock.padding?.right ?? 0;
25208
+ const distTop = anchoredBlock.padding?.top ?? 0;
25209
+ const distBottom = anchoredBlock.padding?.bottom ?? 0;
25210
+ wrapExclusions.push({
25211
+ left: left2 - distLeft,
25212
+ right: left2 + objectWidth + distRight,
25213
+ top: top2 - distTop,
25214
+ bottom: top2 + objectHeight + distBottom,
25215
+ wrapText
25216
+ });
25217
+ }
25218
+ if (anchoredBlock.kind === "image") {
25219
+ const imageWrapper = doc2.createElement("div");
25220
+ imageWrapper.style.position = "absolute";
25221
+ imageWrapper.style.left = `${left2}px`;
25222
+ imageWrapper.style.top = `${top2}px`;
25223
+ imageWrapper.style.width = `${objectWidth}px`;
25224
+ imageWrapper.style.height = `${objectHeight}px`;
25225
+ imageWrapper.style.maxWidth = "100%";
25226
+ imageWrapper.style.boxSizing = "border-box";
25227
+ imageWrapper.style.zIndex = String(zIndex);
25228
+ applySdtDataset(imageWrapper, anchoredBlock.attrs?.sdt);
25229
+ const imgEl = doc2.createElement("img");
25230
+ imgEl.classList.add("superdoc-table-image");
25231
+ if (anchoredBlock.src) {
25232
+ imgEl.src = anchoredBlock.src;
25233
+ }
25234
+ imgEl.alt = anchoredBlock.alt ?? "";
25235
+ imgEl.style.width = "100%";
25236
+ imgEl.style.height = "100%";
25237
+ imgEl.style.objectFit = anchoredBlock.objectFit ?? "contain";
25238
+ if (anchoredBlock.objectFit === "cover") {
25239
+ imgEl.style.objectPosition = "left top";
25240
+ }
25241
+ imgEl.style.display = "block";
25242
+ imageWrapper.appendChild(imgEl);
25243
+ content.appendChild(imageWrapper);
25244
+ } else {
25245
+ const drawingWrapper = doc2.createElement("div");
25246
+ drawingWrapper.style.position = "absolute";
25247
+ drawingWrapper.style.left = `${left2}px`;
25248
+ drawingWrapper.style.top = `${top2}px`;
25249
+ drawingWrapper.style.width = `${objectWidth}px`;
25250
+ drawingWrapper.style.height = `${objectHeight}px`;
25251
+ drawingWrapper.style.maxWidth = "100%";
25252
+ drawingWrapper.style.boxSizing = "border-box";
25253
+ drawingWrapper.style.zIndex = String(zIndex);
25254
+ applySdtDataset(drawingWrapper, anchoredBlock.attrs);
25255
+ const drawingInner = doc2.createElement("div");
25256
+ drawingInner.classList.add("superdoc-table-drawing");
25257
+ drawingInner.style.width = "100%";
25258
+ drawingInner.style.height = "100%";
25259
+ drawingInner.style.display = "flex";
25260
+ drawingInner.style.alignItems = "center";
25261
+ drawingInner.style.justifyContent = "center";
25262
+ drawingInner.style.overflow = "hidden";
25263
+ if (anchoredBlock.drawingKind === "image" && "src" in anchoredBlock && anchoredBlock.src) {
25264
+ const img = doc2.createElement("img");
25265
+ img.classList.add("superdoc-drawing-image");
25266
+ img.src = anchoredBlock.src;
25267
+ img.alt = anchoredBlock.alt ?? "";
25268
+ img.style.width = "100%";
25269
+ img.style.height = "100%";
25270
+ img.style.objectFit = anchoredBlock.objectFit ?? "contain";
25271
+ if (anchoredBlock.objectFit === "cover") {
25272
+ img.style.objectPosition = "left top";
25273
+ }
25274
+ drawingInner.appendChild(img);
25275
+ } else if (renderDrawingContent) {
25276
+ const drawingContent = renderDrawingContent(anchoredBlock);
25277
+ drawingContent.style.width = "100%";
25278
+ drawingContent.style.height = "100%";
25279
+ drawingInner.appendChild(drawingContent);
25280
+ } else {
25281
+ const placeholder = doc2.createElement("div");
25282
+ placeholder.style.width = "100%";
25283
+ placeholder.style.height = "100%";
25284
+ placeholder.style.background = "repeating-linear-gradient(45deg, rgba(15,23,42,0.1), rgba(15,23,42,0.1) 6px, rgba(15,23,42,0.2) 6px, rgba(15,23,42,0.2) 12px)";
25285
+ placeholder.style.border = "1px dashed rgba(15, 23, 42, 0.3)";
25286
+ drawingInner.appendChild(placeholder);
25287
+ }
25288
+ drawingWrapper.appendChild(drawingInner);
25289
+ content.appendChild(drawingWrapper);
25290
+ }
25291
+ }
25292
+ applySquareWrapExclusionsToLines(renderedLines, wrapExclusions, contentWidthPx, alignmentOffsetY);
24991
25293
  }
24992
25294
  return { cellElement: cellEl };
24993
25295
  };
@@ -27433,13 +27735,13 @@ class DomPainter {
27433
27735
  const filters = [];
27434
27736
  if (block.gain != null || block.blacklevel != null) {
27435
27737
  if (block.gain && typeof block.gain === "string" && block.gain.endsWith("f")) {
27436
- const contrast = Math.max(0, parseInt(block.gain) / 65536);
27738
+ const contrast = Math.max(0, parseInt(block.gain) / 65536) * (2 / 3);
27437
27739
  if (contrast > 0) {
27438
27740
  filters.push(`contrast(${contrast})`);
27439
27741
  }
27440
27742
  }
27441
27743
  if (block.blacklevel && typeof block.blacklevel === "string" && block.blacklevel.endsWith("f")) {
27442
- const brightness = Math.max(0, 1 + parseInt(block.blacklevel) / 327 / 100) + 0.5;
27744
+ const brightness = Math.max(0, 1 + parseInt(block.blacklevel) / 327 / 100) * 1.3;
27443
27745
  if (brightness > 0) {
27444
27746
  filters.push(`brightness(${brightness})`);
27445
27747
  }
@@ -27493,7 +27795,7 @@ class DomPainter {
27493
27795
  }
27494
27796
  transforms.push(`scale(${scale})`);
27495
27797
  innerWrapper.style.transform = transforms.join(" ");
27496
- innerWrapper.appendChild(this.renderDrawingContent(block, fragment));
27798
+ innerWrapper.appendChild(this.renderDrawingContent(block, fragment, context));
27497
27799
  fragmentEl.appendChild(innerWrapper);
27498
27800
  return fragmentEl;
27499
27801
  } catch (error) {
@@ -27501,7 +27803,7 @@ class DomPainter {
27501
27803
  return this.createErrorPlaceholder(fragment.blockId, error);
27502
27804
  }
27503
27805
  }
27504
- renderDrawingContent(block, fragment) {
27806
+ renderDrawingContent(block, fragment, context) {
27505
27807
  if (!this.doc) {
27506
27808
  throw new Error("DomPainter: document is not available");
27507
27809
  }
@@ -27509,10 +27811,10 @@ class DomPainter {
27509
27811
  return this.createDrawingImageElement(block);
27510
27812
  }
27511
27813
  if (block.drawingKind === "vectorShape") {
27512
- return this.createVectorShapeElement(block, fragment.geometry, true);
27814
+ return this.createVectorShapeElement(block, fragment.geometry, true, 1, 1, context);
27513
27815
  }
27514
27816
  if (block.drawingKind === "shapeGroup") {
27515
- return this.createShapeGroupElement(block);
27817
+ return this.createShapeGroupElement(block, context);
27516
27818
  }
27517
27819
  return this.createDrawingPlaceholder();
27518
27820
  }
@@ -27533,7 +27835,7 @@ class DomPainter {
27533
27835
  img.style.display = "block";
27534
27836
  return img;
27535
27837
  }
27536
- createVectorShapeElement(block, geometry, applyTransforms = false, groupScaleX = 1, groupScaleY = 1) {
27838
+ createVectorShapeElement(block, geometry, applyTransforms = false, groupScaleX = 1, groupScaleY = 1, context) {
27537
27839
  const container = this.doc.createElement("div");
27538
27840
  container.classList.add("superdoc-vector-shape");
27539
27841
  container.style.width = "100%";
@@ -27573,7 +27875,8 @@ class DomPainter {
27573
27875
  block.textVerticalAlign,
27574
27876
  block.textInsets,
27575
27877
  groupScaleX,
27576
- groupScaleY
27878
+ groupScaleY,
27879
+ context
27577
27880
  );
27578
27881
  contentContainer.appendChild(textDiv);
27579
27882
  }
@@ -27589,7 +27892,8 @@ class DomPainter {
27589
27892
  block.textVerticalAlign,
27590
27893
  block.textInsets,
27591
27894
  groupScaleX,
27592
- groupScaleY
27895
+ groupScaleY,
27896
+ context
27593
27897
  );
27594
27898
  contentContainer.appendChild(textDiv);
27595
27899
  }
@@ -27637,7 +27941,7 @@ class DomPainter {
27637
27941
  * @param groupScaleX - Scale factor applied by parent group (for counter-scaling)
27638
27942
  * @param groupScaleY - Scale factor applied by parent group (for counter-scaling)
27639
27943
  */
27640
- createFallbackTextElement(textContent2, textAlign, textVerticalAlign, textInsets, groupScaleX = 1, groupScaleY = 1) {
27944
+ createFallbackTextElement(textContent2, textAlign, textVerticalAlign, textInsets, groupScaleX = 1, groupScaleY = 1, context) {
27641
27945
  const textDiv = this.doc.createElement("div");
27642
27946
  textDiv.style.position = "absolute";
27643
27947
  textDiv.style.top = "0";
@@ -27685,6 +27989,15 @@ class DomPainter {
27685
27989
  currentParagraph.style.width = "100%";
27686
27990
  currentParagraph.style.minWidth = "0";
27687
27991
  currentParagraph.style.whiteSpace = "normal";
27992
+ const resolvePartText = (part) => {
27993
+ if (part.fieldType === "PAGE") {
27994
+ return context?.pageNumberText ?? String(context?.pageNumber ?? 1);
27995
+ }
27996
+ if (part.fieldType === "NUMPAGES") {
27997
+ return String(context?.totalPages ?? 1);
27998
+ }
27999
+ return part.text;
28000
+ };
27688
28001
  textContent2.parts.forEach((part) => {
27689
28002
  if (part.isLineBreak) {
27690
28003
  textDiv.appendChild(currentParagraph);
@@ -27697,7 +28010,7 @@ class DomPainter {
27697
28010
  }
27698
28011
  } else {
27699
28012
  const span = this.doc.createElement("span");
27700
- span.textContent = part.text;
28013
+ span.textContent = resolvePartText(part);
27701
28014
  if (part.formatting) {
27702
28015
  if (part.formatting.bold) {
27703
28016
  span.style.fontWeight = "bold";
@@ -27705,6 +28018,9 @@ class DomPainter {
27705
28018
  if (part.formatting.italic) {
27706
28019
  span.style.fontStyle = "italic";
27707
28020
  }
28021
+ if (part.formatting.fontFamily) {
28022
+ span.style.fontFamily = part.formatting.fontFamily;
28023
+ }
27708
28024
  if (part.formatting.color) {
27709
28025
  const validatedColor = validateHexColor(part.formatting.color);
27710
28026
  if (validatedColor) {
@@ -27919,7 +28235,7 @@ class DomPainter {
27919
28235
  target.style.removeProperty("transform-origin");
27920
28236
  }
27921
28237
  }
27922
- createShapeGroupElement(block) {
28238
+ createShapeGroupElement(block, context) {
27923
28239
  const groupEl = this.doc.createElement("div");
27924
28240
  groupEl.classList.add("superdoc-shape-group");
27925
28241
  groupEl.style.position = "relative";
@@ -27927,8 +28243,8 @@ class DomPainter {
27927
28243
  groupEl.style.height = "100%";
27928
28244
  const groupTransform = block.groupTransform;
27929
28245
  let contentContainer = groupEl;
27930
- let groupScaleX = 1;
27931
- let groupScaleY = 1;
28246
+ const groupScaleX = 1;
28247
+ const groupScaleY = 1;
27932
28248
  if (groupTransform) {
27933
28249
  const inner = this.doc.createElement("div");
27934
28250
  inner.style.position = "absolute";
@@ -27944,13 +28260,6 @@ class DomPainter {
27944
28260
  if (offsetX || offsetY) {
27945
28261
  transforms.push(`translate(${-offsetX}px, ${-offsetY}px)`);
27946
28262
  }
27947
- const targetWidth = groupTransform.width ?? block.geometry.width ?? childWidth;
27948
- const targetHeight = groupTransform.height ?? block.geometry.height ?? childHeight;
27949
- groupScaleX = childWidth ? targetWidth / childWidth : 1;
27950
- groupScaleY = childHeight ? targetHeight / childHeight : 1;
27951
- if (groupScaleX !== 1 || groupScaleY !== 1) {
27952
- transforms.push(`scale(${groupScaleX}, ${groupScaleY})`);
27953
- }
27954
28263
  if (transforms.length > 0) {
27955
28264
  inner.style.transformOrigin = "top left";
27956
28265
  inner.style.transform = transforms.join(" ");
@@ -27959,7 +28268,7 @@ class DomPainter {
27959
28268
  contentContainer = inner;
27960
28269
  }
27961
28270
  block.shapes.forEach((child) => {
27962
- const childContent = this.createGroupChildContent(child, groupScaleX, groupScaleY);
28271
+ const childContent = this.createGroupChildContent(child, groupScaleX, groupScaleY, context);
27963
28272
  if (!childContent) return;
27964
28273
  const attrs = child.attrs ?? {};
27965
28274
  const wrapper = this.doc.createElement("div");
@@ -27992,7 +28301,7 @@ class DomPainter {
27992
28301
  });
27993
28302
  return groupEl;
27994
28303
  }
27995
- createGroupChildContent(child, groupScaleX = 1, groupScaleY = 1) {
28304
+ createGroupChildContent(child, groupScaleX = 1, groupScaleY = 1, context) {
27996
28305
  if (child.shapeType === "vectorShape" && "fillColor" in child.attrs) {
27997
28306
  const attrs = child.attrs;
27998
28307
  const childGeometry = {
@@ -28020,9 +28329,11 @@ class DomPainter {
28020
28329
  strokeWidth: attrs.strokeWidth,
28021
28330
  lineEnds: attrs.lineEnds,
28022
28331
  textContent: attrs.textContent,
28023
- textAlign: attrs.textAlign
28332
+ textAlign: attrs.textAlign,
28333
+ textVerticalAlign: attrs.textVerticalAlign,
28334
+ textInsets: attrs.textInsets
28024
28335
  };
28025
- return this.createVectorShapeElement(vectorChild, childGeometry, false, groupScaleX, groupScaleY);
28336
+ return this.createVectorShapeElement(vectorChild, childGeometry, false, groupScaleX, groupScaleY, context);
28026
28337
  }
28027
28338
  if (child.shapeType === "image" && "src" in child.attrs) {
28028
28339
  const attrs = child.attrs;
@@ -28062,10 +28373,10 @@ class DomPainter {
28062
28373
  return this.createDrawingImageElement(block);
28063
28374
  }
28064
28375
  if (block.drawingKind === "shapeGroup") {
28065
- return this.createShapeGroupElement(block);
28376
+ return this.createShapeGroupElement(block, context);
28066
28377
  }
28067
28378
  if (block.drawingKind === "vectorShape") {
28068
- return this.createVectorShapeElement(block, block.geometry, false);
28379
+ return this.createVectorShapeElement(block, block.geometry, false, 1, 1, context);
28069
28380
  }
28070
28381
  return this.createDrawingPlaceholder();
28071
28382
  };
@@ -28515,12 +28826,18 @@ class DomPainter {
28515
28826
  }
28516
28827
  if (run.size) {
28517
28828
  if (run.size.width) {
28518
- annotation.style.width = `${run.size.width}px`;
28519
- annotation.style.display = "inline-block";
28520
- annotation.style.overflow = "hidden";
28829
+ const requiresImage = run.variant === "image" || run.variant === "signature";
28830
+ if (!requiresImage || run.imageSrc) {
28831
+ annotation.style.width = `${run.size.width}px`;
28832
+ annotation.style.display = "inline-block";
28833
+ annotation.style.overflow = "hidden";
28834
+ }
28521
28835
  }
28522
- if (run.size.height) {
28523
- annotation.style.height = `${run.size.height}px`;
28836
+ if (run.size.height && run.variant !== "html") {
28837
+ const requiresImage = run.variant === "image" || run.variant === "signature";
28838
+ if (!requiresImage || run.imageSrc) {
28839
+ annotation.style.height = `${run.size.height}px`;
28840
+ }
28524
28841
  }
28525
28842
  }
28526
28843
  if (run.fontFamily) {
@@ -28580,6 +28897,8 @@ class DomPainter {
28580
28897
  content.appendChild(img);
28581
28898
  annotation.style.display = "inline-block";
28582
28899
  content.style.display = "inline-block";
28900
+ annotation.style.lineHeight = "normal";
28901
+ content.style.lineHeight = "normal";
28583
28902
  } else {
28584
28903
  content.textContent = run.displayLabel || (run.variant === "signature" ? "Signature" : "");
28585
28904
  }
@@ -28607,9 +28926,11 @@ class DomPainter {
28607
28926
  }
28608
28927
  case "html": {
28609
28928
  if (run.rawHtml && typeof run.rawHtml === "string") {
28610
- content.textContent = run.displayLabel;
28929
+ content.innerHTML = run.rawHtml.trim();
28611
28930
  annotation.style.display = "inline-block";
28612
28931
  content.style.display = "inline-block";
28932
+ annotation.style.lineHeight = "normal";
28933
+ content.style.lineHeight = "normal";
28613
28934
  } else {
28614
28935
  content.textContent = run.displayLabel;
28615
28936
  }
@@ -29565,6 +29886,33 @@ const deriveBlockVersion = (block) => {
29565
29886
  if (run.kind === "tab") {
29566
29887
  return [run.text ?? "", "tab"].join(",");
29567
29888
  }
29889
+ if (run.kind === "fieldAnnotation") {
29890
+ const size2 = run.size ? `${run.size.width ?? ""}x${run.size.height ?? ""}` : "";
29891
+ const highlighted = run.highlighted !== false ? 1 : 0;
29892
+ return [
29893
+ "field",
29894
+ run.variant ?? "",
29895
+ run.displayLabel ?? "",
29896
+ run.fieldColor ?? "",
29897
+ run.borderColor ?? "",
29898
+ highlighted,
29899
+ run.hidden ? 1 : 0,
29900
+ run.visibility ?? "",
29901
+ run.imageSrc ?? "",
29902
+ run.linkUrl ?? "",
29903
+ run.rawHtml ?? "",
29904
+ size2,
29905
+ run.fontFamily ?? "",
29906
+ run.fontSize ?? "",
29907
+ run.textColor ?? "",
29908
+ run.textHighlight ?? "",
29909
+ run.bold ? 1 : 0,
29910
+ run.italic ? 1 : 0,
29911
+ run.underline ? 1 : 0,
29912
+ run.fieldId ?? "",
29913
+ run.fieldType ?? ""
29914
+ ].join(",");
29915
+ }
29568
29916
  const textRun = run;
29569
29917
  return [
29570
29918
  textRun.text ?? "",
@@ -32580,6 +32928,16 @@ function computeNextSectionPropsAtBreak(blocks) {
32580
32928
  });
32581
32929
  return nextSectionPropsAtBreak;
32582
32930
  }
32931
+ const SINGLE_COLUMN_DEFAULT = { count: 1, gap: 0 };
32932
+ function getColumnConfig(blockColumns) {
32933
+ return blockColumns ? { count: blockColumns.count, gap: blockColumns.gap } : { ...SINGLE_COLUMN_DEFAULT };
32934
+ }
32935
+ function isColumnConfigChanging(blockColumns, activeColumns) {
32936
+ if (blockColumns) {
32937
+ return blockColumns.count !== activeColumns.count || blockColumns.gap !== activeColumns.gap;
32938
+ }
32939
+ return activeColumns.count > 1;
32940
+ }
32583
32941
  function scheduleSectionBreak(block, state, baseMargins, maxHeaderContentHeight = 0, maxFooterContentHeight = 0) {
32584
32942
  const next = { ...state };
32585
32943
  const calcRequiredTopMargin = (headerDistance, baseTop) => {
@@ -32633,10 +32991,8 @@ function scheduleSectionBreak(block, state, baseMargins, maxHeaderContentHeight
32633
32991
  next.activeRightMargin = rightMargin;
32634
32992
  next.pendingRightMargin = rightMargin;
32635
32993
  }
32636
- if (block.columns) {
32637
- next.activeColumns = { count: block.columns.count, gap: block.columns.gap };
32638
- next.pendingColumns = null;
32639
- }
32994
+ next.activeColumns = getColumnConfig(block.columns);
32995
+ next.pendingColumns = null;
32640
32996
  return { decision: { forcePageBreak: false, forceMidPageRegion: false }, state: next };
32641
32997
  }
32642
32998
  const headerPx = block.margins?.header;
@@ -32684,33 +33040,25 @@ function scheduleSectionBreak(block, state, baseMargins, maxHeaderContentHeight
32684
33040
  next.pendingOrientation = block.orientation;
32685
33041
  }
32686
33042
  const sectionType = block.type ?? "continuous";
32687
- const isColumnsChanging = !!block.columns && (block.columns.count !== next.activeColumns.count || block.columns.gap !== next.activeColumns.gap);
33043
+ const isColumnsChanging = isColumnConfigChanging(block.columns, next.activeColumns);
32688
33044
  if (block.attrs?.requirePageBoundary) {
32689
- if (block.columns) {
32690
- next.pendingColumns = { count: block.columns.count, gap: block.columns.gap };
32691
- }
33045
+ next.pendingColumns = getColumnConfig(block.columns);
32692
33046
  return { decision: { forcePageBreak: true, forceMidPageRegion: false }, state: next };
32693
33047
  }
32694
33048
  switch (sectionType) {
32695
33049
  case "nextPage": {
32696
- if (block.columns) {
32697
- next.pendingColumns = { count: block.columns.count, gap: block.columns.gap };
32698
- }
33050
+ next.pendingColumns = getColumnConfig(block.columns);
32699
33051
  return { decision: { forcePageBreak: true, forceMidPageRegion: false }, state: next };
32700
33052
  }
32701
33053
  case "evenPage": {
32702
- if (block.columns) {
32703
- next.pendingColumns = { count: block.columns.count, gap: block.columns.gap };
32704
- }
33054
+ next.pendingColumns = getColumnConfig(block.columns);
32705
33055
  return {
32706
33056
  decision: { forcePageBreak: true, forceMidPageRegion: false, requiredParity: "even" },
32707
33057
  state: next
32708
33058
  };
32709
33059
  }
32710
33060
  case "oddPage": {
32711
- if (block.columns) {
32712
- next.pendingColumns = { count: block.columns.count, gap: block.columns.gap };
32713
- }
33061
+ next.pendingColumns = getColumnConfig(block.columns);
32714
33062
  return {
32715
33063
  decision: { forcePageBreak: true, forceMidPageRegion: false, requiredParity: "odd" },
32716
33064
  state: next
@@ -32719,11 +33067,10 @@ function scheduleSectionBreak(block, state, baseMargins, maxHeaderContentHeight
32719
33067
  case "continuous":
32720
33068
  default: {
32721
33069
  if (isColumnsChanging) {
33070
+ next.pendingColumns = getColumnConfig(block.columns);
32722
33071
  return { decision: { forcePageBreak: false, forceMidPageRegion: true }, state: next };
32723
33072
  }
32724
- if (block.columns) {
32725
- next.pendingColumns = { count: block.columns.count, gap: block.columns.gap };
32726
- }
33073
+ next.pendingColumns = getColumnConfig(block.columns);
32727
33074
  return { decision: { forcePageBreak: false, forceMidPageRegion: false }, state: next };
32728
33075
  }
32729
33076
  }
@@ -32768,6 +33115,28 @@ function applyPendingToActive(state) {
32768
33115
  next.pendingOrientation = null;
32769
33116
  return next;
32770
33117
  }
33118
+ const isTextRun$3 = (run) => {
33119
+ const runWithKind = run;
33120
+ return !runWithKind.kind || runWithKind.kind === "text";
33121
+ };
33122
+ const isEmptyTextParagraph = (block) => {
33123
+ const runs = block.runs;
33124
+ if (!runs || runs.length === 0) return true;
33125
+ if (runs.length !== 1) return false;
33126
+ const run = runs[0];
33127
+ if (!isTextRun$3(run)) return false;
33128
+ return typeof run.text === "string" && run.text.length === 0;
33129
+ };
33130
+ const shouldSuppressSpacingForEmpty = (block, side) => {
33131
+ if (!isEmptyTextParagraph(block)) return false;
33132
+ const attrs = block.attrs;
33133
+ const spacingExplicit = attrs?.spacingExplicit;
33134
+ if (!spacingExplicit) return false;
33135
+ if (side === "before") {
33136
+ return !spacingExplicit.before;
33137
+ }
33138
+ return !spacingExplicit.after;
33139
+ };
32771
33140
  function normalizeLines(measure) {
32772
33141
  if (measure.lines.length > 0) {
32773
33142
  return measure.lines;
@@ -32827,7 +33196,7 @@ const getParagraphAttrs = (block) => {
32827
33196
  const asString = (value) => {
32828
33197
  return typeof value === "string" ? value : void 0;
32829
33198
  };
32830
- const asBoolean = (value) => {
33199
+ const asBoolean$1 = (value) => {
32831
33200
  if (value === true || value === 1) return true;
32832
33201
  if (typeof value === "string") {
32833
33202
  const normalized = value.toLowerCase();
@@ -33007,10 +33376,17 @@ function layoutParagraphBlock(ctx2, anchors) {
33007
33376
  let fromLine = 0;
33008
33377
  const attrs = getParagraphAttrs(block);
33009
33378
  const spacing = attrs?.spacing ?? {};
33379
+ const spacingExplicit = attrs?.spacingExplicit;
33010
33380
  const styleId = asString(attrs?.styleId);
33011
- const contextualSpacing = asBoolean(attrs?.contextualSpacing);
33381
+ const contextualSpacing = asBoolean$1(attrs?.contextualSpacing);
33012
33382
  let spacingBefore = Math.max(0, Number(spacing.before ?? spacing.lineSpaceBefore ?? 0));
33013
- const spacingAfter = Math.max(0, Number(spacing.after ?? spacing.lineSpaceAfter ?? 0));
33383
+ let spacingAfter = ctx2.overrideSpacingAfter ?? Math.max(0, Number(spacing.after ?? spacing.lineSpaceAfter ?? 0));
33384
+ const emptyTextParagraph = isEmptyTextParagraph(block);
33385
+ if (emptyTextParagraph && spacingExplicit) {
33386
+ if (!spacingExplicit.before) spacingBefore = 0;
33387
+ if (!spacingExplicit.after) spacingAfter = 0;
33388
+ }
33389
+ const baseSpacingBefore = spacingBefore;
33014
33390
  let appliedSpacingBefore = spacingBefore === 0;
33015
33391
  let lastState = null;
33016
33392
  const isPositionedFrame = frame?.wrap === "none";
@@ -33104,6 +33480,21 @@ function layoutParagraphBlock(ctx2, anchors) {
33104
33480
  state.trailingSpacing = 0;
33105
33481
  }
33106
33482
  }
33483
+ const keepLines = attrs?.keepLines === true;
33484
+ if (keepLines && fromLine === 0) {
33485
+ const prevTrailing = state.trailingSpacing ?? 0;
33486
+ const neededSpacingBefore = Math.max(spacingBefore - prevTrailing, 0);
33487
+ const pageContentHeight = state.contentBottom - state.topMargin;
33488
+ const fullHeight = lines.reduce((sum, line) => sum + (line.lineHeight || 0), 0);
33489
+ const fitsOnBlankPage = fullHeight + baseSpacingBefore <= pageContentHeight;
33490
+ const remainingHeightAfterSpacing = state.contentBottom - (state.cursorY + neededSpacingBefore);
33491
+ if (fitsOnBlankPage && state.page.fragments.length > 0 && fullHeight > remainingHeightAfterSpacing) {
33492
+ state = advanceColumn(state);
33493
+ spacingBefore = baseSpacingBefore;
33494
+ appliedSpacingBefore = spacingBefore === 0;
33495
+ continue;
33496
+ }
33497
+ }
33107
33498
  if (!appliedSpacingBefore && spacingBefore > 0) {
33108
33499
  while (!appliedSpacingBefore) {
33109
33500
  const prevTrailing = state.trailingSpacing ?? 0;
@@ -34228,6 +34619,86 @@ function computeDisplayPageNumber(pages, sections) {
34228
34619
  }
34229
34620
  return result;
34230
34621
  }
34622
+ const DEFAULT_BALANCING_CONFIG = {
34623
+ // Max 10 iterations to find balance
34624
+ minColumnHeight: 20
34625
+ // Minimum 20px content per column
34626
+ };
34627
+ function getFragmentHeight(fragment, measureMap) {
34628
+ if (fragment.kind === "para") {
34629
+ const measure = measureMap.get(fragment.blockId);
34630
+ if (!measure || measure.kind !== "paragraph" || !measure.lines) {
34631
+ return 0;
34632
+ }
34633
+ let sum = 0;
34634
+ const fromLine = fragment.fromLine ?? 0;
34635
+ const toLine = fragment.toLine ?? measure.lines.length;
34636
+ for (let i = fromLine; i < toLine; i++) {
34637
+ sum += measure.lines[i]?.lineHeight ?? 0;
34638
+ }
34639
+ return sum;
34640
+ }
34641
+ if (fragment.kind === "image" || fragment.kind === "drawing" || fragment.kind === "table") {
34642
+ if (typeof fragment.height === "number") {
34643
+ return fragment.height;
34644
+ }
34645
+ const measure = measureMap.get(fragment.blockId);
34646
+ if (measure && typeof measure.height === "number") {
34647
+ return measure.height;
34648
+ }
34649
+ }
34650
+ return 0;
34651
+ }
34652
+ function balancePageColumns(fragments, columns, margins, topMargin, measureMap) {
34653
+ if (columns.count <= 1 || fragments.length === 0) {
34654
+ return;
34655
+ }
34656
+ const columnX = (columnIndex) => {
34657
+ return margins.left + columnIndex * (columns.width + columns.gap);
34658
+ };
34659
+ const rowMap = /* @__PURE__ */ new Map();
34660
+ fragments.forEach((fragment, idx) => {
34661
+ const y2 = Math.round(fragment.y);
34662
+ if (!rowMap.has(y2)) {
34663
+ rowMap.set(y2, []);
34664
+ }
34665
+ const height = getFragmentHeight(fragment, measureMap);
34666
+ rowMap.get(y2).push({
34667
+ fragment,
34668
+ height,
34669
+ originalIndex: idx
34670
+ });
34671
+ });
34672
+ const sortedRows = [...rowMap.entries()].sort((a, b2) => a[0] - b2[0]);
34673
+ let totalHeight = 0;
34674
+ for (const [, rowFragments] of sortedRows) {
34675
+ const maxHeight = Math.max(...rowFragments.map((f) => f.height));
34676
+ totalHeight += maxHeight;
34677
+ }
34678
+ const targetHeight = totalHeight / columns.count;
34679
+ if (targetHeight < DEFAULT_BALANCING_CONFIG.minColumnHeight) {
34680
+ return;
34681
+ }
34682
+ let currentColumn = 0;
34683
+ let currentColumnHeight = 0;
34684
+ let currentY = topMargin;
34685
+ for (const [, rowFragments] of sortedRows) {
34686
+ const rowHeight = Math.max(...rowFragments.map((f) => f.height));
34687
+ if (currentColumnHeight > 0 && currentColumnHeight + rowHeight >= targetHeight && currentColumn < columns.count - 1) {
34688
+ currentColumn++;
34689
+ currentColumnHeight = 0;
34690
+ currentY = topMargin;
34691
+ }
34692
+ const colX = columnX(currentColumn);
34693
+ for (const info of rowFragments) {
34694
+ info.fragment.x = colX;
34695
+ info.fragment.y = currentY;
34696
+ info.fragment.width = columns.width;
34697
+ }
34698
+ currentColumnHeight += rowHeight;
34699
+ currentY += rowHeight;
34700
+ }
34701
+ }
34231
34702
  function resolvePageNumberTokens(layout, blocks, measures, numberingCtx) {
34232
34703
  const affectedBlockIds = /* @__PURE__ */ new Set();
34233
34704
  const updatedBlocks = /* @__PURE__ */ new Map();
@@ -34317,11 +34788,13 @@ function hasHeight(fragment) {
34317
34788
  function getParagraphSpacingBefore(block) {
34318
34789
  const spacing = block.attrs?.spacing;
34319
34790
  const value = spacing?.before ?? spacing?.lineSpaceBefore;
34791
+ if (shouldSuppressSpacingForEmpty(block, "before")) return 0;
34320
34792
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
34321
34793
  }
34322
34794
  function getParagraphSpacingAfter$1(block) {
34323
34795
  const spacing = block.attrs?.spacing;
34324
34796
  const value = spacing?.after ?? spacing?.lineSpaceAfter;
34797
+ if (shouldSuppressSpacingForEmpty(block, "after")) return 0;
34325
34798
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
34326
34799
  }
34327
34800
  function getMeasureHeight(block, measure) {
@@ -34344,9 +34817,123 @@ function getMeasureHeight(block, measure) {
34344
34817
  }
34345
34818
  }
34346
34819
  }
34820
+ function computeKeepNextChains(blocks) {
34821
+ const chains = /* @__PURE__ */ new Map();
34822
+ const processedIndices = /* @__PURE__ */ new Set();
34823
+ for (let i = 0; i < blocks.length; i++) {
34824
+ if (processedIndices.has(i)) continue;
34825
+ const block = blocks[i];
34826
+ if (block.kind !== "paragraph") continue;
34827
+ const paraBlock = block;
34828
+ if (paraBlock.attrs?.keepNext !== true) continue;
34829
+ const memberIndices = [i];
34830
+ let endIndex = i;
34831
+ for (let j = i + 1; j < blocks.length; j++) {
34832
+ const nextBlock = blocks[j];
34833
+ if (nextBlock.kind === "sectionBreak" || nextBlock.kind === "pageBreak" || nextBlock.kind === "columnBreak") {
34834
+ break;
34835
+ }
34836
+ if (nextBlock.kind !== "paragraph") {
34837
+ break;
34838
+ }
34839
+ const nextPara = nextBlock;
34840
+ if (nextPara.attrs?.keepNext === true) {
34841
+ memberIndices.push(j);
34842
+ endIndex = j;
34843
+ processedIndices.add(j);
34844
+ } else {
34845
+ break;
34846
+ }
34847
+ }
34848
+ const anchorIndex = endIndex + 1 < blocks.length ? endIndex + 1 : -1;
34849
+ if (anchorIndex !== -1) {
34850
+ const anchorBlock = blocks[anchorIndex];
34851
+ if (anchorBlock.kind === "sectionBreak" || anchorBlock.kind === "pageBreak" || anchorBlock.kind === "columnBreak") {
34852
+ if (memberIndices.length > 1) {
34853
+ chains.set(i, {
34854
+ startIndex: i,
34855
+ endIndex,
34856
+ memberIndices,
34857
+ anchorIndex: -1
34858
+ });
34859
+ }
34860
+ continue;
34861
+ }
34862
+ }
34863
+ chains.set(i, {
34864
+ startIndex: i,
34865
+ endIndex,
34866
+ memberIndices,
34867
+ anchorIndex
34868
+ });
34869
+ }
34870
+ return chains;
34871
+ }
34872
+ function calculateChainHeight(chain, blocks, measures, state) {
34873
+ let totalHeight = 0;
34874
+ let prevStyleId;
34875
+ let prevSpacingAfter = 0;
34876
+ let prevContextualSpacing = false;
34877
+ let isFirstMember = true;
34878
+ for (const memberIndex of chain.memberIndices) {
34879
+ const block = blocks[memberIndex];
34880
+ const measure = measures[memberIndex];
34881
+ if (!measure) continue;
34882
+ const spacingBefore = getParagraphSpacingBefore(block);
34883
+ const spacingAfter = getParagraphSpacingAfter$1(block);
34884
+ const styleId = typeof block.attrs?.styleId === "string" ? block.attrs?.styleId : void 0;
34885
+ const contextualSpacing = block.attrs?.contextualSpacing === true;
34886
+ if (isFirstMember) {
34887
+ const prevTrailing = Number.isFinite(state.trailingSpacing) && state.trailingSpacing > 0 ? state.trailingSpacing : 0;
34888
+ const sameAsLastOnPage = styleId && state.lastParagraphStyleId === styleId;
34889
+ const effectiveSpacingBefore = contextualSpacing && sameAsLastOnPage ? 0 : Math.max(spacingBefore - prevTrailing, 0);
34890
+ totalHeight += effectiveSpacingBefore;
34891
+ isFirstMember = false;
34892
+ } else {
34893
+ const sameStyle = styleId && prevStyleId && styleId === prevStyleId;
34894
+ const effectiveSpacingAfterPrev = prevContextualSpacing && sameStyle ? 0 : prevSpacingAfter;
34895
+ const effectiveSpacingBefore = contextualSpacing && sameStyle ? 0 : spacingBefore;
34896
+ const interParagraphSpacing = Math.max(effectiveSpacingAfterPrev, effectiveSpacingBefore);
34897
+ totalHeight += interParagraphSpacing;
34898
+ }
34899
+ totalHeight += getMeasureHeight(block, measure);
34900
+ prevStyleId = styleId;
34901
+ prevSpacingAfter = spacingAfter;
34902
+ prevContextualSpacing = contextualSpacing;
34903
+ }
34904
+ if (chain.anchorIndex !== -1) {
34905
+ const anchorBlock = blocks[chain.anchorIndex];
34906
+ const anchorMeasure = measures[chain.anchorIndex];
34907
+ if (anchorBlock && anchorMeasure) {
34908
+ if (anchorBlock.kind === "paragraph" && anchorMeasure.kind === "paragraph") {
34909
+ const anchorSpacingBefore = getParagraphSpacingBefore(anchorBlock);
34910
+ const anchorStyleId = typeof anchorBlock.attrs?.styleId === "string" ? anchorBlock.attrs?.styleId : void 0;
34911
+ const anchorContextualSpacing = anchorBlock.attrs?.contextualSpacing === true;
34912
+ const sameStyle = anchorStyleId && prevStyleId && anchorStyleId === prevStyleId;
34913
+ const effectiveSpacingAfterPrev = prevContextualSpacing && sameStyle ? 0 : prevSpacingAfter;
34914
+ const effectiveAnchorSpacingBefore = anchorContextualSpacing && sameStyle ? 0 : anchorSpacingBefore;
34915
+ const interParagraphSpacing = Math.max(effectiveSpacingAfterPrev, effectiveAnchorSpacingBefore);
34916
+ const firstLineHeight = anchorMeasure.lines[0]?.lineHeight;
34917
+ const anchorHeight = typeof firstLineHeight === "number" && Number.isFinite(firstLineHeight) && firstLineHeight > 0 ? firstLineHeight : getMeasureHeight(anchorBlock, anchorMeasure);
34918
+ totalHeight += interParagraphSpacing + anchorHeight;
34919
+ } else {
34920
+ totalHeight += prevSpacingAfter + getMeasureHeight(anchorBlock, anchorMeasure);
34921
+ }
34922
+ }
34923
+ }
34924
+ return totalHeight;
34925
+ }
34347
34926
  const DEFAULT_PAGE_SIZE$2 = { w: 612, h: 792 };
34348
34927
  const DEFAULT_MARGINS$2 = { top: 72, right: 72, bottom: 72, left: 72 };
34349
34928
  const COLUMN_EPSILON$1 = 1e-4;
34929
+ const asBoolean = (value) => {
34930
+ if (value === true || value === 1) return true;
34931
+ if (typeof value === "string") {
34932
+ const normalized = value.toLowerCase();
34933
+ return normalized === "true" || normalized === "1" || normalized === "on";
34934
+ }
34935
+ return false;
34936
+ };
34350
34937
  const layoutDebugEnabled$1 = typeof process$1 !== "undefined" && typeof process$1.env !== "undefined" && Boolean(process$1.env.SD_DEBUG_LAYOUT);
34351
34938
  const layoutLog = (...args) => {
34352
34939
  if (!layoutDebugEnabled$1) return;
@@ -34459,7 +35046,7 @@ function layoutDocument(blocks, measures, options = {}) {
34459
35046
  let activeOrientation = null;
34460
35047
  let pendingOrientation = null;
34461
35048
  let activeVAlign = null;
34462
- let pendingVAlign = null;
35049
+ let pendingVAlign = void 0;
34463
35050
  const paginatorMargins = { left: activeLeftMargin, right: activeRightMargin };
34464
35051
  const floatManager = createFloatingObjectManager(
34465
35052
  normalizeColumns(activeColumns, activePageSize.w - (activeLeftMargin + activeRightMargin)),
@@ -34516,6 +35103,9 @@ function layoutDocument(blocks, measures, options = {}) {
34516
35103
  if (block.columns) {
34517
35104
  next.activeColumns = { count: block.columns.count, gap: block.columns.gap };
34518
35105
  next.pendingColumns = null;
35106
+ } else {
35107
+ next.activeColumns = { count: 1, gap: 0 };
35108
+ next.pendingColumns = null;
34519
35109
  }
34520
35110
  if (block.headerRefs || block.footerRefs) {
34521
35111
  const baseSectionRefs = pendingSectionRefs ?? activeSectionRefs;
@@ -34575,7 +35165,7 @@ function layoutDocument(blocks, measures, options = {}) {
34575
35165
  if (block.pageSize) next.pendingPageSize = { w: block.pageSize.w, h: block.pageSize.h };
34576
35166
  if (block.orientation) next.pendingOrientation = block.orientation;
34577
35167
  const sectionType = block.type ?? "continuous";
34578
- const isColumnsChanging = !!block.columns && (block.columns.count !== next.activeColumns.count || block.columns.gap !== next.activeColumns.gap);
35168
+ const isColumnsChanging = block.columns && (block.columns.count !== next.activeColumns.count || block.columns.gap !== next.activeColumns.gap) || !block.columns && next.activeColumns.count > 1;
34579
35169
  const sectionIndexRaw = block.attrs?.sectionIndex;
34580
35170
  const metadataIndex = typeof sectionIndexRaw === "number" ? sectionIndexRaw : Number(sectionIndexRaw ?? NaN);
34581
35171
  if (Number.isFinite(metadataIndex)) {
@@ -34596,26 +35186,28 @@ function layoutDocument(blocks, measures, options = {}) {
34596
35186
  pendingSectionRefs = mergeSectionRefs(baseSectionRefs, nextSectionRefs);
34597
35187
  layoutLog(`[Layout] Compat fallback: Scheduled pendingSectionRefs:`, pendingSectionRefs);
34598
35188
  }
35189
+ const getColumnConfig2 = () => block.columns ? { count: block.columns.count, gap: block.columns.gap } : { count: 1, gap: 0 };
34599
35190
  if (block.attrs?.requirePageBoundary) {
34600
- if (block.columns) next.pendingColumns = { count: block.columns.count, gap: block.columns.gap };
35191
+ next.pendingColumns = getColumnConfig2();
34601
35192
  return { decision: { forcePageBreak: true, forceMidPageRegion: false }, state: next };
34602
35193
  }
34603
35194
  if (sectionType === "nextPage") {
34604
- if (block.columns) next.pendingColumns = { count: block.columns.count, gap: block.columns.gap };
35195
+ next.pendingColumns = getColumnConfig2();
34605
35196
  return { decision: { forcePageBreak: true, forceMidPageRegion: false }, state: next };
34606
35197
  }
34607
35198
  if (sectionType === "evenPage") {
34608
- if (block.columns) next.pendingColumns = { count: block.columns.count, gap: block.columns.gap };
35199
+ next.pendingColumns = getColumnConfig2();
34609
35200
  return { decision: { forcePageBreak: true, forceMidPageRegion: false, requiredParity: "even" }, state: next };
34610
35201
  }
34611
35202
  if (sectionType === "oddPage") {
34612
- if (block.columns) next.pendingColumns = { count: block.columns.count, gap: block.columns.gap };
35203
+ next.pendingColumns = getColumnConfig2();
34613
35204
  return { decision: { forcePageBreak: true, forceMidPageRegion: false, requiredParity: "odd" }, state: next };
34614
35205
  }
34615
35206
  if (isColumnsChanging) {
35207
+ next.pendingColumns = getColumnConfig2();
34616
35208
  return { decision: { forcePageBreak: false, forceMidPageRegion: true }, state: next };
34617
35209
  }
34618
- if (block.columns) next.pendingColumns = { count: block.columns.count, gap: block.columns.gap };
35210
+ next.pendingColumns = getColumnConfig2();
34619
35211
  return { decision: { forcePageBreak: false, forceMidPageRegion: false }, state: next };
34620
35212
  };
34621
35213
  const createPage = (number, pageMargins, pageSizeOverride) => {
@@ -34632,6 +35224,10 @@ function layoutDocument(blocks, measures, options = {}) {
34632
35224
  }
34633
35225
  if (activeVAlign && activeVAlign !== "top") {
34634
35226
  page.vAlign = activeVAlign;
35227
+ page.baseMargins = {
35228
+ top: activeSectionBaseTopMargin,
35229
+ bottom: activeSectionBaseBottomMargin
35230
+ };
34635
35231
  }
34636
35232
  return page;
34637
35233
  };
@@ -34666,6 +35262,9 @@ function layoutDocument(blocks, measures, options = {}) {
34666
35262
  ...initialSectionMetadata.footerRefs && { footerRefs: initialSectionMetadata.footerRefs }
34667
35263
  };
34668
35264
  }
35265
+ if (initialSectionMetadata?.vAlign) {
35266
+ activeVAlign = initialSectionMetadata.vAlign;
35267
+ }
34669
35268
  let activeSectionIndex = initialSectionMetadata?.sectionIndex ?? 0;
34670
35269
  let pendingSectionIndex = null;
34671
35270
  const sectionFirstPageNumbers = /* @__PURE__ */ new Map();
@@ -34752,9 +35351,9 @@ function layoutDocument(blocks, measures, options = {}) {
34752
35351
  activeSectionIndex = pendingSectionIndex;
34753
35352
  pendingSectionIndex = null;
34754
35353
  }
34755
- if (pendingVAlign !== null) {
35354
+ if (pendingVAlign !== void 0) {
34756
35355
  activeVAlign = pendingVAlign;
34757
- pendingVAlign = null;
35356
+ pendingVAlign = void 0;
34758
35357
  }
34759
35358
  if (pendingSectionBaseTopMargin !== null) {
34760
35359
  activeSectionBaseTopMargin = pendingSectionBaseTopMargin;
@@ -34935,6 +35534,13 @@ function layoutDocument(blocks, measures, options = {}) {
34935
35534
  floatManager.registerDrawing(entry.block, entry.measure, anchorY, state.columnIndex, state.page.number);
34936
35535
  preRegisteredPositions.set(entry.block.id, { anchorX, anchorY, pageNumber: state.page.number });
34937
35536
  }
35537
+ const keepNextChains = computeKeepNextChains(blocks);
35538
+ const midChainIndices = /* @__PURE__ */ new Set();
35539
+ for (const chain of keepNextChains.values()) {
35540
+ for (let i = 1; i < chain.memberIndices.length; i++) {
35541
+ midChainIndices.add(chain.memberIndices[i]);
35542
+ }
35543
+ }
34938
35544
  for (let index2 = 0; index2 < blocks.length; index2 += 1) {
34939
35545
  const block = blocks[index2];
34940
35546
  const measure = measures[index2];
@@ -35038,14 +35644,13 @@ function layoutDocument(blocks, measures, options = {}) {
35038
35644
  pendingSectionBaseBottomMargin = typeof blockBottomMargin === "number" ? blockBottomMargin : margins.bottom;
35039
35645
  }
35040
35646
  }
35041
- if (effectiveBlock.vAlign) {
35042
- const isFirstSection2 = effectiveBlock.attrs?.isFirstSection && states.length === 0;
35043
- if (isFirstSection2) {
35044
- activeVAlign = effectiveBlock.vAlign;
35045
- pendingVAlign = null;
35046
- } else {
35047
- pendingVAlign = effectiveBlock.vAlign;
35048
- }
35647
+ const sectionVAlign = effectiveBlock.vAlign ?? null;
35648
+ const isFirstSectionForVAlign = effectiveBlock.attrs?.isFirstSection && states.length === 0;
35649
+ if (isFirstSectionForVAlign) {
35650
+ activeVAlign = sectionVAlign;
35651
+ pendingVAlign = void 0;
35652
+ } else {
35653
+ pendingVAlign = sectionVAlign;
35049
35654
  }
35050
35655
  if (effectiveBlock.headerRefs || effectiveBlock.footerRefs) {
35051
35656
  const baseSectionRefs = pendingSectionRefs ?? activeSectionRefs;
@@ -35085,14 +35690,10 @@ function layoutDocument(blocks, measures, options = {}) {
35085
35690
  pendingNumbering = { ...effectiveBlock.numbering };
35086
35691
  }
35087
35692
  }
35088
- if (breakInfo.forceMidPageRegion && block.columns) {
35693
+ if (breakInfo.forceMidPageRegion && updatedState.pendingColumns) {
35089
35694
  let state = paginator.ensurePage();
35090
35695
  const columnIndexBefore = state.columnIndex;
35091
- const rawCount = block.columns.count;
35092
- const validatedCount = typeof rawCount === "number" && Number.isFinite(rawCount) && rawCount > 0 ? Math.max(1, Math.floor(rawCount)) : 1;
35093
- const rawGap = block.columns.gap;
35094
- const validatedGap = typeof rawGap === "number" && Number.isFinite(rawGap) && rawGap >= 0 ? Math.max(0, rawGap) : 0;
35095
- const newColumns = { count: validatedCount, gap: validatedGap };
35696
+ const newColumns = updatedState.pendingColumns;
35096
35697
  if (columnIndexBefore >= newColumns.count) {
35097
35698
  state = paginator.startNewPage();
35098
35699
  }
@@ -35156,7 +35757,24 @@ function layoutDocument(blocks, measures, options = {}) {
35156
35757
  placedAnchoredTableIds.add(tableBlock.id);
35157
35758
  }
35158
35759
  }
35159
- if (paraBlock.attrs?.keepNext === true) {
35760
+ const chain = keepNextChains.get(index2);
35761
+ if (midChainIndices.has(index2)) ;
35762
+ else if (chain) {
35763
+ let state = paginator.ensurePage();
35764
+ const availableHeight = state.contentBottom - state.cursorY;
35765
+ const firstMemberBlock = blocks[chain.startIndex];
35766
+ const firstMemberStyleId = typeof firstMemberBlock.attrs?.styleId === "string" ? firstMemberBlock.attrs?.styleId : void 0;
35767
+ const firstMemberContextualSpacing = firstMemberBlock.attrs?.contextualSpacing === true;
35768
+ const contextualSpacingApplies = firstMemberContextualSpacing && firstMemberStyleId && state.lastParagraphStyleId === firstMemberStyleId;
35769
+ const prevTrailing = Number.isFinite(state.trailingSpacing) && state.trailingSpacing > 0 ? state.trailingSpacing : 0;
35770
+ const effectiveAvailableHeight = contextualSpacingApplies ? availableHeight + prevTrailing : availableHeight;
35771
+ const chainHeight = calculateChainHeight(chain, blocks, measures, state);
35772
+ const pageContentHeight = state.contentBottom - state.topMargin;
35773
+ const chainFitsOnBlankPage = chainHeight <= pageContentHeight;
35774
+ if (chainFitsOnBlankPage && chainHeight > effectiveAvailableHeight && state.page.fragments.length > 0) {
35775
+ state = paginator.advanceColumn(state);
35776
+ }
35777
+ } else if (paraBlock.attrs?.keepNext === true) {
35160
35778
  const nextBlock = blocks[index2 + 1];
35161
35779
  const nextMeasure = measures[index2 + 1];
35162
35780
  if (nextBlock && nextMeasure && nextBlock.kind !== "sectionBreak" && nextBlock.kind !== "pageBreak" && nextBlock.kind !== "columnBreak") {
@@ -35164,11 +35782,23 @@ function layoutDocument(blocks, measures, options = {}) {
35164
35782
  if (!shouldSkipAnchoredTable) {
35165
35783
  let state = paginator.ensurePage();
35166
35784
  const availableHeight = state.contentBottom - state.cursorY;
35785
+ const spacingBefore = getParagraphSpacingBefore(paraBlock);
35167
35786
  const spacingAfter = getParagraphSpacingAfter$1(paraBlock);
35787
+ const prevTrailing = Number.isFinite(state.trailingSpacing) && state.trailingSpacing > 0 ? state.trailingSpacing : 0;
35788
+ const currentStyleId = typeof paraBlock.attrs?.styleId === "string" ? paraBlock.attrs?.styleId : void 0;
35789
+ const currentContextualSpacing = asBoolean(paraBlock.attrs?.contextualSpacing);
35790
+ const contextualSpacingApplies = currentContextualSpacing && currentStyleId && state.lastParagraphStyleId === currentStyleId;
35791
+ const effectiveSpacingBefore = contextualSpacingApplies ? 0 : Math.max(spacingBefore - prevTrailing, 0);
35168
35792
  const currentHeight = getMeasureHeight(paraBlock, measure);
35169
35793
  const nextHeight = getMeasureHeight(nextBlock, nextMeasure);
35170
35794
  const nextIsParagraph = nextBlock.kind === "paragraph" && nextMeasure.kind === "paragraph";
35171
35795
  const nextSpacingBefore = nextIsParagraph ? getParagraphSpacingBefore(nextBlock) : 0;
35796
+ const nextStyleId = nextIsParagraph && typeof nextBlock.attrs?.styleId === "string" ? nextBlock.attrs?.styleId : void 0;
35797
+ const nextContextualSpacing = nextIsParagraph && asBoolean(nextBlock.attrs?.contextualSpacing);
35798
+ const sameStyleAsNext = currentStyleId && nextStyleId && nextStyleId === currentStyleId;
35799
+ const effectiveSpacingAfter = currentContextualSpacing && sameStyleAsNext ? 0 : spacingAfter;
35800
+ const effectiveNextSpacingBefore = nextContextualSpacing && sameStyleAsNext ? 0 : nextSpacingBefore;
35801
+ const interParagraphSpacing = nextIsParagraph ? Math.max(effectiveSpacingAfter, effectiveNextSpacingBefore) : effectiveSpacingAfter;
35172
35802
  const nextFirstLineHeight = (() => {
35173
35803
  if (!nextIsParagraph) {
35174
35804
  return nextHeight;
@@ -35179,13 +35809,26 @@ function layoutDocument(blocks, measures, options = {}) {
35179
35809
  }
35180
35810
  return nextHeight;
35181
35811
  })();
35182
- const combinedHeight = nextIsParagraph ? currentHeight + Math.max(spacingAfter, nextSpacingBefore) + nextFirstLineHeight : currentHeight + spacingAfter + nextHeight;
35183
- if (combinedHeight > availableHeight && state.page.fragments.length > 0) {
35812
+ const combinedHeight = nextIsParagraph ? effectiveSpacingBefore + currentHeight + interParagraphSpacing + nextFirstLineHeight : effectiveSpacingBefore + currentHeight + spacingAfter + nextHeight;
35813
+ const effectiveAvailableHeight = contextualSpacingApplies ? availableHeight + prevTrailing : availableHeight;
35814
+ if (combinedHeight > effectiveAvailableHeight && state.page.fragments.length > 0) {
35184
35815
  state = paginator.advanceColumn(state);
35185
35816
  }
35186
35817
  }
35187
35818
  }
35188
35819
  }
35820
+ let overrideSpacingAfter;
35821
+ const curStyleId = typeof paraBlock.attrs?.styleId === "string" ? paraBlock.attrs.styleId : void 0;
35822
+ const curContextualSpacing = asBoolean(paraBlock.attrs?.contextualSpacing);
35823
+ if (curContextualSpacing && curStyleId) {
35824
+ const nextBlock = index2 < blocks.length - 1 ? blocks[index2 + 1] : null;
35825
+ if (nextBlock?.kind === "paragraph") {
35826
+ const nextStyleId = typeof nextBlock.attrs?.styleId === "string" ? nextBlock.attrs?.styleId : void 0;
35827
+ if (nextStyleId === curStyleId) {
35828
+ overrideSpacingAfter = 0;
35829
+ }
35830
+ }
35831
+ }
35189
35832
  layoutParagraphBlock(
35190
35833
  {
35191
35834
  block,
@@ -35195,7 +35838,8 @@ function layoutDocument(blocks, measures, options = {}) {
35195
35838
  advanceColumn: paginator.advanceColumn,
35196
35839
  columnX,
35197
35840
  floatManager,
35198
- remeasureParagraph: options.remeasureParagraph
35841
+ remeasureParagraph: options.remeasureParagraph,
35842
+ overrideSpacingAfter
35199
35843
  },
35200
35844
  anchorsForPara ? {
35201
35845
  anchoredDrawings: anchorsForPara,
@@ -35326,11 +35970,17 @@ function layoutDocument(blocks, measures, options = {}) {
35326
35970
  pages.pop();
35327
35971
  }
35328
35972
  for (const page of pages) {
35329
- if (!page.vAlign || page.vAlign === "top") continue;
35330
- if (page.fragments.length === 0) continue;
35973
+ if (!page.vAlign || page.vAlign === "top") {
35974
+ continue;
35975
+ }
35976
+ if (page.fragments.length === 0) {
35977
+ continue;
35978
+ }
35331
35979
  const pageSizeForPage = page.size ?? pageSize;
35332
- const contentTop = page.margins?.top ?? margins.top;
35333
- const contentBottom = pageSizeForPage.h - (page.margins?.bottom ?? margins.bottom);
35980
+ const baseTop = page.baseMargins?.top ?? page.margins?.top ?? margins.top;
35981
+ const baseBottom = page.baseMargins?.bottom ?? page.margins?.bottom ?? margins.bottom;
35982
+ const contentTop = baseTop;
35983
+ const contentBottom = pageSizeForPage.h - baseBottom;
35334
35984
  const contentHeight = contentBottom - contentTop;
35335
35985
  let minY = Infinity;
35336
35986
  let maxY = -Infinity;
@@ -35364,6 +36014,58 @@ function layoutDocument(blocks, measures, options = {}) {
35364
36014
  }
35365
36015
  }
35366
36016
  }
36017
+ if (activeColumns.count > 1) {
36018
+ const contentWidth = pageSize.w - (activeLeftMargin + activeRightMargin);
36019
+ const normalizedCols = normalizeColumns(activeColumns, contentWidth);
36020
+ const measureMap = /* @__PURE__ */ new Map();
36021
+ const blockSectionMap = /* @__PURE__ */ new Map();
36022
+ blocks.forEach((block, idx) => {
36023
+ const measure = measures[idx];
36024
+ if (measure) {
36025
+ measureMap.set(block.id, measure);
36026
+ }
36027
+ const blockWithAttrs = block;
36028
+ const sectionIdx = blockWithAttrs.attrs?.sectionIndex;
36029
+ if (typeof sectionIdx === "number") {
36030
+ blockSectionMap.set(block.id, sectionIdx);
36031
+ }
36032
+ });
36033
+ for (const page of pages) {
36034
+ if (page === pages[pages.length - 1] && page.fragments.length > 0) {
36035
+ const uniqueXPositions = new Set(page.fragments.map((f) => Math.round(f.x)));
36036
+ const hasExplicitColumnStructure = uniqueXPositions.size > 1;
36037
+ if (hasExplicitColumnStructure) {
36038
+ continue;
36039
+ }
36040
+ const uniqueWidths = new Set(page.fragments.map((f) => Math.round(f.width)));
36041
+ const hasMixedColumnWidths = uniqueWidths.size > 1;
36042
+ if (hasMixedColumnWidths) {
36043
+ continue;
36044
+ }
36045
+ const fragmentSections = /* @__PURE__ */ new Set();
36046
+ for (const f of page.fragments) {
36047
+ const section = blockSectionMap.get(f.blockId);
36048
+ if (section !== void 0) {
36049
+ fragmentSections.add(section);
36050
+ }
36051
+ }
36052
+ const hasMixedSections = fragmentSections.size > 1;
36053
+ const fragmentsToBalance = hasMixedSections ? page.fragments.filter((f) => {
36054
+ const fragSection = blockSectionMap.get(f.blockId);
36055
+ return fragSection === activeSectionIndex;
36056
+ }) : page.fragments;
36057
+ if (fragmentsToBalance.length > 0) {
36058
+ balancePageColumns(
36059
+ fragmentsToBalance,
36060
+ normalizedCols,
36061
+ { left: activeLeftMargin },
36062
+ activeTopMargin,
36063
+ measureMap
36064
+ );
36065
+ }
36066
+ }
36067
+ }
36068
+ }
35367
36069
  return {
35368
36070
  pageSize,
35369
36071
  pages,
@@ -35490,6 +36192,29 @@ function normalizeColumns(input, contentWidth) {
35490
36192
  width
35491
36193
  };
35492
36194
  }
36195
+ const fieldAnnotationKey = (run) => {
36196
+ if (run.kind !== "fieldAnnotation") return "";
36197
+ const annotation = run;
36198
+ const sizeKey = annotation.size ? `${annotation.size.width ?? ""}x${annotation.size.height ?? ""}` : "";
36199
+ const highlightKey = annotation.highlighted === false ? "nohl" : "hl";
36200
+ const hiddenKey = annotation.hidden ? "hidden" : "";
36201
+ return [
36202
+ annotation.variant ?? "",
36203
+ annotation.displayLabel ?? "",
36204
+ annotation.imageSrc ?? "",
36205
+ annotation.rawHtml ?? "",
36206
+ annotation.linkUrl ?? "",
36207
+ annotation.fontFamily ?? "",
36208
+ annotation.fontSize ?? "",
36209
+ annotation.bold ? "b" : "",
36210
+ annotation.italic ? "i" : "",
36211
+ annotation.underline ? "u" : "",
36212
+ highlightKey,
36213
+ hiddenKey,
36214
+ annotation.visibility ?? "",
36215
+ sizeKey
36216
+ ].join("|");
36217
+ };
35493
36218
  const hasTrackedChange = (run) => {
35494
36219
  return "trackedChange" in run && run.trackedChange !== void 0 && run.trackedChange !== null;
35495
36220
  };
@@ -35703,7 +36428,10 @@ const hashRuns = (block) => {
35703
36428
  const srcHash = imgRun.src.slice(0, 50);
35704
36429
  return `img:${srcHash}:${imgRun.width}x${imgRun.height}`;
35705
36430
  }
35706
- const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation" ? "" : run.text ?? "";
36431
+ if (run.kind === "fieldAnnotation") {
36432
+ return `fa:${fieldAnnotationKey(run)}`;
36433
+ }
36434
+ const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
35707
36435
  const bold = "bold" in run ? run.bold : false;
35708
36436
  const italic = "italic" in run ? run.italic : false;
35709
36437
  const color = "color" in run ? run.color : void 0;
@@ -36581,6 +37309,13 @@ const TAB_EPSILON$1 = 0.1;
36581
37309
  const WIDTH_FUDGE_PX = 0.5;
36582
37310
  const twipsToPx$2 = (twips) => twips / TWIPS_PER_PX$1;
36583
37311
  const pxToTwips$1 = (px) => Math.round(px * TWIPS_PER_PX$1);
37312
+ const sanitizeIndent$1 = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : 0;
37313
+ const sanitizeDecimalSeparator$1 = (value) => value === "," ? "," : ".";
37314
+ const getRunWidth = (run) => {
37315
+ const width = run.width;
37316
+ return typeof width === "number" ? width : 0;
37317
+ };
37318
+ const isLineBreakRun$1 = (run) => run.kind === "lineBreak" || run.kind === "break" && run.breakType === "line";
36584
37319
  const markerFontString = (run) => {
36585
37320
  const size2 = run?.fontSize ?? 16;
36586
37321
  const family = run?.fontFamily ?? "Arial";
@@ -36590,10 +37325,10 @@ const markerFontString = (run) => {
36590
37325
  };
36591
37326
  const buildTabStopsPx$1 = (indent, tabs, tabIntervalTwips) => {
36592
37327
  const paragraphIndentTwips = {
36593
- left: pxToTwips$1(Math.max(0, indent?.left ?? 0)),
36594
- right: pxToTwips$1(Math.max(0, indent?.right ?? 0)),
36595
- firstLine: pxToTwips$1(Math.max(0, indent?.firstLine ?? 0)),
36596
- hanging: pxToTwips$1(Math.max(0, indent?.hanging ?? 0))
37328
+ left: pxToTwips$1(sanitizeIndent$1(indent?.left)),
37329
+ right: pxToTwips$1(sanitizeIndent$1(indent?.right)),
37330
+ firstLine: pxToTwips$1(sanitizeIndent$1(indent?.firstLine)),
37331
+ hanging: pxToTwips$1(sanitizeIndent$1(indent?.hanging))
36597
37332
  };
36598
37333
  const stops = computeTabStops$1({
36599
37334
  explicitStops: tabs ?? [],
@@ -36612,7 +37347,7 @@ const getNextTabStopPx$1 = (currentX, tabStops, startIndex) => {
36612
37347
  index2 += 1;
36613
37348
  }
36614
37349
  if (index2 < tabStops.length) {
36615
- return { target: tabStops[index2].pos, nextIndex: index2 + 1 };
37350
+ return { target: tabStops[index2].pos, nextIndex: index2 + 1, stop: tabStops[index2] };
36616
37351
  }
36617
37352
  return { target: currentX + twipsToPx$2(DEFAULT_TAB_INTERVAL_TWIPS$1), nextIndex: index2 };
36618
37353
  };
@@ -36630,6 +37365,211 @@ function measureRunSliceWidth(run, fromChar, toChar) {
36630
37365
  const metrics = context.measureText(text);
36631
37366
  return metrics.width;
36632
37367
  }
37368
+ const scanTabAlignmentGroup = (runs, startRunIndex, startChar, decimalSeparator) => {
37369
+ let totalWidth = 0;
37370
+ let beforeDecimalWidth;
37371
+ let foundDecimal = false;
37372
+ let endRun = startRunIndex;
37373
+ let endChar = startChar;
37374
+ for (let r2 = startRunIndex; r2 < runs.length; r2 += 1) {
37375
+ const run = runs[r2];
37376
+ if (!run) continue;
37377
+ if (run.kind === "tab") {
37378
+ return { totalWidth, beforeDecimalWidth, endRun, endChar, resumeRun: r2, resumeChar: 0 };
37379
+ }
37380
+ if (isLineBreakRun$1(run)) {
37381
+ return { totalWidth, beforeDecimalWidth, endRun, endChar, resumeRun: r2, resumeChar: 0 };
37382
+ }
37383
+ const text = runText(run);
37384
+ if (!text) {
37385
+ const runWidth = getRunWidth(run);
37386
+ if (runWidth > 0) {
37387
+ totalWidth += runWidth;
37388
+ endRun = r2;
37389
+ endChar = 1;
37390
+ }
37391
+ continue;
37392
+ }
37393
+ const sliceStart = r2 === startRunIndex ? startChar : 0;
37394
+ if (sliceStart >= text.length) continue;
37395
+ const tabIndex = text.indexOf(" ", sliceStart);
37396
+ const effectiveEnd = tabIndex >= 0 ? tabIndex : text.length;
37397
+ if (effectiveEnd > sliceStart) {
37398
+ const sliceWidth = measureRunSliceWidth(run, sliceStart, effectiveEnd);
37399
+ if (!foundDecimal) {
37400
+ const decimalIndex = text.slice(sliceStart, effectiveEnd).indexOf(decimalSeparator);
37401
+ if (decimalIndex >= 0) {
37402
+ foundDecimal = true;
37403
+ const beforeWidth = decimalIndex > 0 ? measureRunSliceWidth(run, sliceStart, sliceStart + decimalIndex) : 0;
37404
+ beforeDecimalWidth = totalWidth + beforeWidth;
37405
+ }
37406
+ }
37407
+ totalWidth += sliceWidth;
37408
+ endRun = r2;
37409
+ endChar = effectiveEnd;
37410
+ }
37411
+ if (tabIndex >= 0) {
37412
+ return { totalWidth, beforeDecimalWidth, endRun, endChar, resumeRun: r2, resumeChar: tabIndex };
37413
+ }
37414
+ }
37415
+ return { totalWidth, beforeDecimalWidth, endRun, endChar, resumeRun: runs.length, resumeChar: 0 };
37416
+ };
37417
+ const measureTabAlignmentGroupInLine = (runs, line, startRunIndex, startChar, decimalSeparator) => {
37418
+ let totalWidth = 0;
37419
+ let beforeDecimalWidth;
37420
+ let foundDecimal = false;
37421
+ for (let r2 = startRunIndex; r2 <= line.toRun; r2 += 1) {
37422
+ const run = runs[r2];
37423
+ if (!run) continue;
37424
+ if (run.kind === "tab") break;
37425
+ if (isLineBreakRun$1(run)) break;
37426
+ const text = runText(run);
37427
+ if (!text) {
37428
+ totalWidth += getRunWidth(run);
37429
+ continue;
37430
+ }
37431
+ const sliceStart = r2 === startRunIndex ? startChar : 0;
37432
+ const sliceEnd = r2 === line.toRun ? line.toChar : text.length;
37433
+ if (sliceStart >= sliceEnd) continue;
37434
+ const slice2 = text.slice(sliceStart, sliceEnd);
37435
+ const tabIndex = slice2.indexOf(" ");
37436
+ const effectiveSlice = tabIndex >= 0 ? slice2.slice(0, tabIndex) : slice2;
37437
+ const effectiveSliceEnd = tabIndex >= 0 ? sliceStart + tabIndex : sliceEnd;
37438
+ if (effectiveSlice.length > 0) {
37439
+ const sliceWidth = measureRunSliceWidth(run, sliceStart, effectiveSliceEnd);
37440
+ totalWidth += sliceWidth;
37441
+ if (!foundDecimal) {
37442
+ const decimalIndex = effectiveSlice.indexOf(decimalSeparator);
37443
+ if (decimalIndex >= 0) {
37444
+ foundDecimal = true;
37445
+ const beforeWidth = decimalIndex > 0 ? measureRunSliceWidth(run, sliceStart, sliceStart + decimalIndex) : 0;
37446
+ beforeDecimalWidth = totalWidth - sliceWidth + beforeWidth;
37447
+ }
37448
+ }
37449
+ }
37450
+ if (tabIndex >= 0) {
37451
+ break;
37452
+ }
37453
+ }
37454
+ return { totalWidth, beforeDecimalWidth };
37455
+ };
37456
+ const applyTabLayoutToLines = (lines, runs, tabStops, decimalSeparator, indentLeft, rawFirstLineOffset) => {
37457
+ lines.forEach((line, lineIndex) => {
37458
+ let cursorX = 0;
37459
+ let lineWidth = 0;
37460
+ let tabStopCursor = 0;
37461
+ let pendingTabAlignStartX = null;
37462
+ const segments = [];
37463
+ const leaders = [];
37464
+ const effectiveIndent = lineIndex === 0 ? indentLeft + rawFirstLineOffset : indentLeft;
37465
+ const maxAbsWidth = typeof line.maxWidth === "number" && Number.isFinite(line.maxWidth) ? line.maxWidth + effectiveIndent : Number.POSITIVE_INFINITY;
37466
+ const applyTab = (startRunIndex, startChar, run) => {
37467
+ const originX = cursorX;
37468
+ const absCurrentX = cursorX + effectiveIndent;
37469
+ const { target, nextIndex, stop } = getNextTabStopPx$1(absCurrentX, tabStops, tabStopCursor);
37470
+ tabStopCursor = nextIndex;
37471
+ const clampedTarget = Number.isFinite(maxAbsWidth) ? Math.min(target, maxAbsWidth) : target;
37472
+ const relativeTarget = clampedTarget - effectiveIndent;
37473
+ lineWidth = Math.max(lineWidth, relativeTarget);
37474
+ if (stop?.leader && stop.leader !== "none") {
37475
+ const from3 = Math.min(originX, relativeTarget);
37476
+ const to = Math.max(originX, relativeTarget);
37477
+ leaders.push({ from: from3, to, style: stop.leader });
37478
+ }
37479
+ const stopVal = stop?.val ?? "start";
37480
+ if (stopVal === "end" || stopVal === "center" || stopVal === "decimal") {
37481
+ const groupMeasure = measureTabAlignmentGroupInLine(runs, line, startRunIndex, startChar, decimalSeparator);
37482
+ if (groupMeasure.totalWidth > 0) {
37483
+ let groupStartX;
37484
+ if (stopVal === "end") {
37485
+ groupStartX = Math.max(0, relativeTarget - groupMeasure.totalWidth);
37486
+ } else if (stopVal === "center") {
37487
+ groupStartX = Math.max(0, relativeTarget - groupMeasure.totalWidth / 2);
37488
+ } else {
37489
+ const beforeDecimal = groupMeasure.beforeDecimalWidth ?? groupMeasure.totalWidth;
37490
+ groupStartX = Math.max(0, relativeTarget - beforeDecimal);
37491
+ }
37492
+ pendingTabAlignStartX = groupStartX;
37493
+ } else {
37494
+ cursorX = Math.max(cursorX, relativeTarget);
37495
+ }
37496
+ } else {
37497
+ cursorX = Math.max(cursorX, relativeTarget);
37498
+ }
37499
+ if (run && run.kind === "tab") {
37500
+ run.width = Math.max(0, relativeTarget - originX);
37501
+ }
37502
+ };
37503
+ for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
37504
+ const run = runs[runIndex];
37505
+ if (!run) continue;
37506
+ if (run.kind === "tab") {
37507
+ applyTab(runIndex + 1, 0, run);
37508
+ continue;
37509
+ }
37510
+ const text = runText(run);
37511
+ if (!text) {
37512
+ cursorX += getRunWidth(run);
37513
+ lineWidth = Math.max(lineWidth, cursorX);
37514
+ continue;
37515
+ }
37516
+ const sliceStart = runIndex === line.fromRun ? line.fromChar : 0;
37517
+ const sliceEnd = runIndex === line.toRun ? line.toChar : text.length;
37518
+ if (sliceStart >= sliceEnd) continue;
37519
+ let segmentStart = sliceStart;
37520
+ for (let i = sliceStart; i < sliceEnd; i += 1) {
37521
+ if (text[i] !== " ") continue;
37522
+ if (i > segmentStart) {
37523
+ const segmentWidth = measureRunSliceWidth(run, segmentStart, i);
37524
+ const segment = {
37525
+ runIndex,
37526
+ fromChar: segmentStart,
37527
+ toChar: i,
37528
+ width: segmentWidth
37529
+ };
37530
+ if (pendingTabAlignStartX != null) {
37531
+ segment.x = pendingTabAlignStartX;
37532
+ cursorX = pendingTabAlignStartX + segmentWidth;
37533
+ pendingTabAlignStartX = null;
37534
+ } else {
37535
+ cursorX += segmentWidth;
37536
+ }
37537
+ lineWidth = Math.max(lineWidth, cursorX);
37538
+ segments.push(segment);
37539
+ }
37540
+ applyTab(runIndex, i + 1);
37541
+ segmentStart = i + 1;
37542
+ }
37543
+ if (segmentStart < sliceEnd) {
37544
+ const segmentWidth = measureRunSliceWidth(run, segmentStart, sliceEnd);
37545
+ const segment = {
37546
+ runIndex,
37547
+ fromChar: segmentStart,
37548
+ toChar: sliceEnd,
37549
+ width: segmentWidth
37550
+ };
37551
+ if (pendingTabAlignStartX != null) {
37552
+ segment.x = pendingTabAlignStartX;
37553
+ cursorX = pendingTabAlignStartX + segmentWidth;
37554
+ pendingTabAlignStartX = null;
37555
+ } else {
37556
+ cursorX += segmentWidth;
37557
+ }
37558
+ lineWidth = Math.max(lineWidth, cursorX);
37559
+ segments.push(segment);
37560
+ }
37561
+ }
37562
+ if (segments.length > 0) {
37563
+ line.segments = segments;
37564
+ }
37565
+ if (leaders.length > 0) {
37566
+ line.leaders = leaders;
37567
+ }
37568
+ if (lineWidth > 0) {
37569
+ line.width = Math.max(line.width, lineWidth);
37570
+ }
37571
+ });
37572
+ };
36633
37573
  function lineHeightForRuns(runs, fromRun, toRun) {
36634
37574
  let maxSize2 = 0;
36635
37575
  for (let i = fromRun; i <= toRun; i += 1) {
@@ -36658,13 +37598,14 @@ function remeasureParagraph(block, maxWidth, firstLineIndent = 0) {
36658
37598
  const attrs = block.attrs;
36659
37599
  const indent = attrs?.indent;
36660
37600
  const wordLayout = attrs?.wordLayout;
36661
- const rawIndentLeft = indent?.left ?? 0;
36662
- const rawIndentRight = indent?.right ?? 0;
37601
+ const rawIndentLeft = typeof indent?.left === "number" && Number.isFinite(indent.left) ? indent.left : 0;
37602
+ const rawIndentRight = typeof indent?.right === "number" && Number.isFinite(indent.right) ? indent.right : 0;
36663
37603
  const indentLeft = Math.max(0, rawIndentLeft);
36664
37604
  const indentRight = Math.max(0, rawIndentRight);
36665
37605
  const indentFirstLine = Math.max(0, indent?.firstLine ?? 0);
36666
37606
  const indentHanging = Math.max(0, indent?.hanging ?? 0);
36667
37607
  const baseFirstLineOffset = firstLineIndent || indentFirstLine - indentHanging;
37608
+ const rawFirstLineOffset = baseFirstLineOffset;
36668
37609
  const clampedFirstLineOffset = Math.max(0, baseFirstLineOffset);
36669
37610
  const hasNegativeIndent = rawIndentLeft < 0 || rawIndentRight < 0;
36670
37611
  const allowNegativeFirstLineOffset = !wordLayout?.marker && !hasNegativeIndent && baseFirstLineOffset < 0;
@@ -36691,11 +37632,13 @@ function remeasureParagraph(block, maxWidth, firstLineIndent = 0) {
36691
37632
  const treatAsHanging = !wordLayout?.marker && effectiveTextStartPx && indentLeft === 0 && indentHanging === 0;
36692
37633
  const firstLineWidth = typeof effectiveTextStartPx === "number" && effectiveTextStartPx > indentLeft && !treatAsHanging ? Math.max(1, maxWidth - effectiveTextStartPx - indentRight) : Math.max(1, contentWidth - effectiveFirstLineOffset);
36693
37634
  const tabStops = buildTabStopsPx$1(indent, attrs?.tabs, attrs?.tabIntervalTwips);
37635
+ const decimalSeparator = sanitizeDecimalSeparator$1(attrs?.decimalSeparator);
36694
37636
  let currentRun = 0;
36695
37637
  let currentChar = 0;
36696
37638
  while (currentRun < runs.length) {
36697
37639
  const isFirstLine = lines.length === 0;
36698
37640
  const effectiveMaxWidth = Math.max(1, isFirstLine ? firstLineWidth : contentWidth);
37641
+ const effectiveIndent = isFirstLine ? indentLeft + rawFirstLineOffset : indentLeft;
36699
37642
  const startRun = currentRun;
36700
37643
  const startChar = currentChar;
36701
37644
  let width = 0;
@@ -36706,13 +37649,50 @@ function remeasureParagraph(block, maxWidth, firstLineIndent = 0) {
36706
37649
  let endChar = currentChar;
36707
37650
  let tabStopCursor = 0;
36708
37651
  let didBreakInThisLine = false;
37652
+ let resumeRun = -1;
37653
+ let resumeChar = 0;
36709
37654
  for (let r2 = currentRun; r2 < runs.length; r2 += 1) {
36710
37655
  const run = runs[r2];
36711
37656
  if (run.kind === "tab") {
36712
- const { target, nextIndex } = getNextTabStopPx$1(width, tabStops, tabStopCursor);
36713
- const tabAdvance = Math.max(0, target - width);
37657
+ const absCurrentX = width + effectiveIndent;
37658
+ const { target, nextIndex, stop } = getNextTabStopPx$1(absCurrentX, tabStops, tabStopCursor);
37659
+ const maxAbsWidth = effectiveMaxWidth + effectiveIndent;
37660
+ const clampedTarget = Math.min(target, maxAbsWidth);
37661
+ const tabAdvance = Math.max(0, clampedTarget - absCurrentX);
36714
37662
  width += tabAdvance;
36715
37663
  tabStopCursor = nextIndex;
37664
+ if (stop && (stop.val === "end" || stop.val === "center" || stop.val === "decimal")) {
37665
+ const group = scanTabAlignmentGroup(runs, r2 + 1, 0, decimalSeparator);
37666
+ if (group.totalWidth > 0) {
37667
+ const relativeTarget = clampedTarget - effectiveIndent;
37668
+ let groupStartX;
37669
+ if (stop.val === "end") {
37670
+ groupStartX = Math.max(0, relativeTarget - group.totalWidth);
37671
+ } else if (stop.val === "center") {
37672
+ groupStartX = Math.max(0, relativeTarget - group.totalWidth / 2);
37673
+ } else {
37674
+ const beforeDecimal = group.beforeDecimalWidth ?? group.totalWidth;
37675
+ groupStartX = Math.max(0, relativeTarget - beforeDecimal);
37676
+ }
37677
+ const rightEdge = stop.val === "end" ? relativeTarget : groupStartX + group.totalWidth;
37678
+ width = Math.max(width, rightEdge);
37679
+ endRun = group.endRun;
37680
+ endChar = group.endChar;
37681
+ lastBreakRun = group.endRun;
37682
+ lastBreakChar = group.endChar;
37683
+ widthAtLastBreak = width;
37684
+ if (group.resumeRun >= runs.length) {
37685
+ didBreakInThisLine = true;
37686
+ break;
37687
+ }
37688
+ if (group.resumeRun > r2) {
37689
+ resumeRun = group.resumeRun;
37690
+ resumeChar = group.resumeChar;
37691
+ r2 = resumeRun - 1;
37692
+ continue;
37693
+ }
37694
+ }
37695
+ }
36716
37696
  endRun = r2;
36717
37697
  endChar = 1;
36718
37698
  lastBreakRun = r2;
@@ -36721,8 +37701,63 @@ function remeasureParagraph(block, maxWidth, firstLineIndent = 0) {
36721
37701
  continue;
36722
37702
  }
36723
37703
  const text = runText(run);
36724
- const start2 = r2 === currentRun ? currentChar : 0;
37704
+ const start2 = r2 === currentRun ? currentChar : r2 === resumeRun ? resumeChar : 0;
37705
+ if (r2 === resumeRun) {
37706
+ resumeRun = -1;
37707
+ }
36725
37708
  for (let c2 = start2; c2 < text.length; c2 += 1) {
37709
+ const ch = text[c2];
37710
+ if (ch === " ") {
37711
+ const absCurrentX = width + effectiveIndent;
37712
+ const { target, nextIndex, stop } = getNextTabStopPx$1(absCurrentX, tabStops, tabStopCursor);
37713
+ const maxAbsWidth = effectiveMaxWidth + effectiveIndent;
37714
+ const clampedTarget = Math.min(target, maxAbsWidth);
37715
+ const tabAdvance = Math.max(0, clampedTarget - absCurrentX);
37716
+ width += tabAdvance;
37717
+ tabStopCursor = nextIndex;
37718
+ if (stop && (stop.val === "end" || stop.val === "center" || stop.val === "decimal")) {
37719
+ const group = scanTabAlignmentGroup(runs, r2, c2 + 1, decimalSeparator);
37720
+ if (group.totalWidth > 0) {
37721
+ const relativeTarget = clampedTarget - effectiveIndent;
37722
+ let groupStartX;
37723
+ if (stop.val === "end") {
37724
+ groupStartX = Math.max(0, relativeTarget - group.totalWidth);
37725
+ } else if (stop.val === "center") {
37726
+ groupStartX = Math.max(0, relativeTarget - group.totalWidth / 2);
37727
+ } else {
37728
+ const beforeDecimal = group.beforeDecimalWidth ?? group.totalWidth;
37729
+ groupStartX = Math.max(0, relativeTarget - beforeDecimal);
37730
+ }
37731
+ const rightEdge = stop.val === "end" ? relativeTarget : groupStartX + group.totalWidth;
37732
+ width = Math.max(width, rightEdge);
37733
+ endRun = group.endRun;
37734
+ endChar = group.endChar;
37735
+ lastBreakRun = group.endRun;
37736
+ lastBreakChar = group.endChar;
37737
+ widthAtLastBreak = width;
37738
+ if (group.resumeRun >= runs.length) {
37739
+ didBreakInThisLine = true;
37740
+ break;
37741
+ }
37742
+ if (group.resumeRun > r2) {
37743
+ resumeRun = group.resumeRun;
37744
+ resumeChar = group.resumeChar;
37745
+ r2 = resumeRun - 1;
37746
+ break;
37747
+ }
37748
+ if (group.resumeRun === r2) {
37749
+ c2 = group.resumeChar - 1;
37750
+ continue;
37751
+ }
37752
+ }
37753
+ }
37754
+ endRun = r2;
37755
+ endChar = c2 + 1;
37756
+ lastBreakRun = r2;
37757
+ lastBreakChar = c2 + 1;
37758
+ widthAtLastBreak = width;
37759
+ continue;
37760
+ }
36726
37761
  const w = measureRunSliceWidth(run, c2, c2 + 1);
36727
37762
  if (width + w > effectiveMaxWidth - WIDTH_FUDGE_PX && width > 0) {
36728
37763
  if (lastBreakRun >= 0) {
@@ -36739,7 +37774,6 @@ function remeasureParagraph(block, maxWidth, firstLineIndent = 0) {
36739
37774
  width += w;
36740
37775
  endRun = r2;
36741
37776
  endChar = c2 + 1;
36742
- const ch = text[c2];
36743
37777
  if (ch === " " || ch === " " || ch === "-") {
36744
37778
  lastBreakRun = r2;
36745
37779
  lastBreakChar = c2 + 1;
@@ -36774,6 +37808,13 @@ function remeasureParagraph(block, maxWidth, firstLineIndent = 0) {
36774
37808
  currentChar = 0;
36775
37809
  }
36776
37810
  }
37811
+ const hasTabRun = runs.some((run) => run?.kind === "tab");
37812
+ const hasTextTab = runs.some(
37813
+ (run) => run?.kind === "text" && typeof run.text === "string" && run.text.includes(" ")
37814
+ );
37815
+ if (hasTabRun || hasTextTab) {
37816
+ applyTabLayoutToLines(lines, runs, tabStops, decimalSeparator, indentLeft, rawFirstLineOffset);
37817
+ }
36777
37818
  const totalHeight = lines.reduce((s, l) => s + l.lineHeight, 0);
36778
37819
  const marker = wordLayout?.marker;
36779
37820
  const markerInfo = marker ? {
@@ -36932,7 +37973,7 @@ const paragraphBlocksEqual = (a, b2) => {
36932
37973
  for (let i = 0; i < a.runs.length; i += 1) {
36933
37974
  const runA = a.runs[i];
36934
37975
  const runB = b2.runs[i];
36935
- if (("src" in runA || runA.kind === "lineBreak" || runA.kind === "break" || runA.kind === "fieldAnnotation" ? "" : runA.text) !== ("src" in runB || runB.kind === "lineBreak" || runB.kind === "break" || runB.kind === "fieldAnnotation" ? "" : runB.text) || ("bold" in runA ? runA.bold : false) !== ("bold" in runB ? runB.bold : false) || ("italic" in runA ? runA.italic : false) !== ("italic" in runB ? runB.italic : false) || ("color" in runA ? runA.color : void 0) !== ("color" in runB ? runB.color : void 0) || ("fontSize" in runA ? runA.fontSize : void 0) !== ("fontSize" in runB ? runB.fontSize : void 0) || ("fontFamily" in runA ? runA.fontFamily : void 0) !== ("fontFamily" in runB ? runB.fontFamily : void 0) || ("highlight" in runA ? runA.highlight : void 0) !== ("highlight" in runB ? runB.highlight : void 0) || getTrackedChangeKey(runA) !== getTrackedChangeKey(runB) || getCommentKey(runA) !== getCommentKey(runB)) {
37976
+ if (("src" in runA || runA.kind === "lineBreak" || runA.kind === "break" || runA.kind === "fieldAnnotation" ? "" : runA.text) !== ("src" in runB || runB.kind === "lineBreak" || runB.kind === "break" || runB.kind === "fieldAnnotation" ? "" : runB.text) || fieldAnnotationKey(runA) !== fieldAnnotationKey(runB) || ("bold" in runA ? runA.bold : false) !== ("bold" in runB ? runB.bold : false) || ("italic" in runA ? runA.italic : false) !== ("italic" in runB ? runB.italic : false) || ("color" in runA ? runA.color : void 0) !== ("color" in runB ? runB.color : void 0) || ("fontSize" in runA ? runA.fontSize : void 0) !== ("fontSize" in runB ? runB.fontSize : void 0) || ("fontFamily" in runA ? runA.fontFamily : void 0) !== ("fontFamily" in runB ? runB.fontFamily : void 0) || ("highlight" in runA ? runA.highlight : void 0) !== ("highlight" in runB ? runB.highlight : void 0) || getTrackedChangeKey(runA) !== getTrackedChangeKey(runB) || getCommentKey(runA) !== getCommentKey(runB)) {
36936
37977
  return false;
36937
37978
  }
36938
37979
  }
@@ -41972,18 +43013,29 @@ function setupInternalFieldAnnotationDragHandlers({
41972
43013
  const fieldId = event.data.fieldId;
41973
43014
  if (fieldId) {
41974
43015
  const targetPos = event.pmPosition;
43016
+ const pmStart = event.data.pmStart;
41975
43017
  let sourceStart = null;
41976
43018
  let sourceEnd = null;
41977
43019
  let sourceNode = null;
41978
- state.doc.descendants((node, pos) => {
41979
- if (node.type.name === "fieldAnnotation" && node.attrs.fieldId === fieldId) {
41980
- sourceStart = pos;
41981
- sourceEnd = pos + node.nodeSize;
41982
- sourceNode = node;
41983
- return false;
43020
+ if (pmStart != null) {
43021
+ const nodeAt = state.doc.nodeAt(pmStart);
43022
+ if (nodeAt?.type?.name === "fieldAnnotation") {
43023
+ sourceStart = pmStart;
43024
+ sourceEnd = pmStart + nodeAt.nodeSize;
43025
+ sourceNode = nodeAt;
41984
43026
  }
41985
- return true;
41986
- });
43027
+ }
43028
+ if (sourceStart == null || sourceEnd == null || !sourceNode) {
43029
+ state.doc.descendants((node, pos) => {
43030
+ if (node.type.name === "fieldAnnotation" && node.attrs.fieldId === fieldId) {
43031
+ sourceStart = pos;
43032
+ sourceEnd = pos + node.nodeSize;
43033
+ sourceNode = node;
43034
+ return false;
43035
+ }
43036
+ return true;
43037
+ });
43038
+ }
41987
43039
  if (sourceStart === null || sourceEnd === null || !sourceNode) {
41988
43040
  return;
41989
43041
  }
@@ -42299,7 +43351,7 @@ function getSectPrFromNode(node) {
42299
43351
  return isSectPrElement(sectPr) ? sectPr : null;
42300
43352
  }
42301
43353
  function createSectionBreakBlock(section, blockIdGen, extraAttrs) {
42302
- const result = {
43354
+ return {
42303
43355
  kind: "sectionBreak",
42304
43356
  id: blockIdGen("sectionBreak"),
42305
43357
  margins: section.margins ?? { header: 0, footer: 0 },
@@ -42317,7 +43369,6 @@ function createSectionBreakBlock(section, blockIdGen, extraAttrs) {
42317
43369
  ...section.footerRefs && { footerRefs: section.footerRefs },
42318
43370
  ...section.vAlign && { vAlign: section.vAlign }
42319
43371
  };
42320
- return result;
42321
43372
  }
42322
43373
  function shouldRequirePageBoundary(current, next) {
42323
43374
  if (!next) return false;
@@ -42353,14 +43404,33 @@ function shouldIgnoreSectionBreak(paragraph, index2, total, hasBodySectPr) {
42353
43404
  function findParagraphsWithSectPr(doc2) {
42354
43405
  const paragraphs = [];
42355
43406
  let paragraphIndex = 0;
43407
+ const getNodeChildren = (node) => {
43408
+ if (Array.isArray(node.content)) return node.content;
43409
+ const content = node.content;
43410
+ if (content && typeof content.forEach === "function") {
43411
+ const children = [];
43412
+ content.forEach((child) => {
43413
+ children.push(child);
43414
+ });
43415
+ return children;
43416
+ }
43417
+ return [];
43418
+ };
43419
+ const visitNode = (node) => {
43420
+ if (node.type === "paragraph") {
43421
+ if (hasSectPr(node)) {
43422
+ paragraphs.push({ index: paragraphIndex, node });
43423
+ }
43424
+ paragraphIndex++;
43425
+ return;
43426
+ }
43427
+ if (node.type === "index") {
43428
+ getNodeChildren(node).forEach(visitNode);
43429
+ }
43430
+ };
42356
43431
  if (doc2.content) {
42357
43432
  for (const node of doc2.content) {
42358
- if (node.type === "paragraph") {
42359
- if (hasSectPr(node)) {
42360
- paragraphs.push({ index: paragraphIndex, node });
42361
- }
42362
- paragraphIndex++;
42363
- }
43433
+ visitNode(node);
42364
43434
  }
42365
43435
  }
42366
43436
  return { paragraphs, totalCount: paragraphIndex };
@@ -42405,7 +43475,9 @@ function buildSectionRangesFromParagraphs(paragraphs, hasBodySectPr) {
42405
43475
  return ranges;
42406
43476
  }
42407
43477
  function publishSectionMetadata(sectionRanges, options) {
42408
- if (!options?.sectionMetadata) return;
43478
+ if (!options?.sectionMetadata) {
43479
+ return;
43480
+ }
42409
43481
  options.sectionMetadata.length = 0;
42410
43482
  sectionRanges.forEach((section) => {
42411
43483
  options.sectionMetadata?.push({
@@ -42413,7 +43485,8 @@ function publishSectionMetadata(sectionRanges, options) {
42413
43485
  headerRefs: section.headerRefs,
42414
43486
  footerRefs: section.footerRefs,
42415
43487
  numbering: section.numbering,
42416
- titlePg: section.titlePg
43488
+ titlePg: section.titlePg,
43489
+ vAlign: section.vAlign
42417
43490
  });
42418
43491
  });
42419
43492
  }
@@ -42506,6 +43579,8 @@ const ATOMIC_INLINE_TYPES = /* @__PURE__ */ new Set([
42506
43579
  "lineBreak",
42507
43580
  "page-number",
42508
43581
  "total-page-number",
43582
+ "indexEntry",
43583
+ "tab",
42509
43584
  "footnoteReference",
42510
43585
  "passthroughInline",
42511
43586
  "bookmarkEnd"
@@ -43117,6 +44192,26 @@ function normalizeTextInsets(value) {
43117
44192
  return { top: top2, right: right2, bottom: bottom2, left: left2 };
43118
44193
  }
43119
44194
  const OOXML_Z_INDEX_BASE = 251658240;
44195
+ const asOoxmlElement = (value) => {
44196
+ if (!value || typeof value !== "object") return void 0;
44197
+ const element = value;
44198
+ if (element.name == null && element.attributes == null && element.elements == null) return void 0;
44199
+ return element;
44200
+ };
44201
+ const findOoxmlChild = (parent, name) => {
44202
+ return parent?.elements?.find((child) => child?.name === name);
44203
+ };
44204
+ const getOoxmlAttribute = (element, key2) => {
44205
+ if (!element?.attributes) return void 0;
44206
+ const attrs = element.attributes;
44207
+ return attrs[key2] ?? attrs[key2.startsWith("w:") ? key2.slice(2) : `w:${key2}`];
44208
+ };
44209
+ const parseOoxmlNumber = (value) => {
44210
+ if (value == null) return void 0;
44211
+ const num = typeof value === "number" ? value : Number.parseInt(String(value), 10);
44212
+ return Number.isFinite(num) ? num : void 0;
44213
+ };
44214
+ const hasOwnProperty$d = (obj, key2) => Object.prototype.hasOwnProperty.call(obj, key2);
43120
44215
  function normalizeZIndex(originalAttributes) {
43121
44216
  if (!isPlainObject$2(originalAttributes)) return void 0;
43122
44217
  const relativeHeight = originalAttributes.relativeHeight;
@@ -45117,24 +46212,47 @@ const DEFAULT_DECIMAL_SEPARATOR$2 = ".";
45117
46212
  const isValidNumberingId = (numId) => {
45118
46213
  return numId != null && numId !== 0 && numId !== "0";
45119
46214
  };
45120
- const asOoxmlElement = (value) => {
45121
- if (!value || typeof value !== "object") return void 0;
45122
- const element = value;
45123
- if (element.name == null && element.attributes == null && element.elements == null) return void 0;
45124
- return element;
45125
- };
45126
- const findChild = (parent, name) => {
45127
- return parent?.elements?.find((child) => child?.name === name);
46215
+ const extractSpacingExplicitFromObject = (value) => {
46216
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
46217
+ const obj = value;
46218
+ const explicit = {};
46219
+ if (hasOwnProperty$d(obj, "before") || hasOwnProperty$d(obj, "lineSpaceBefore") || hasOwnProperty$d(obj, "beforeAutospacing") || hasOwnProperty$d(obj, "beforeAutoSpacing")) {
46220
+ explicit.before = true;
46221
+ }
46222
+ if (hasOwnProperty$d(obj, "after") || hasOwnProperty$d(obj, "lineSpaceAfter") || hasOwnProperty$d(obj, "afterAutospacing") || hasOwnProperty$d(obj, "afterAutoSpacing")) {
46223
+ explicit.after = true;
46224
+ }
46225
+ if (hasOwnProperty$d(obj, "line") || hasOwnProperty$d(obj, "lineRule")) {
46226
+ explicit.line = true;
46227
+ }
46228
+ return explicit;
45128
46229
  };
45129
- const getAttribute = (element, key2) => {
45130
- if (!element?.attributes) return void 0;
45131
- const attrs = element.attributes;
45132
- return attrs[key2] ?? attrs[key2.startsWith("w:") ? key2.slice(2) : `w:${key2}`];
46230
+ const extractSpacingExplicitFromOoxml = (value) => {
46231
+ const element = asOoxmlElement(value);
46232
+ if (!element) return {};
46233
+ const pPr = element.name === "w:pPr" ? element : findOoxmlChild(element, "w:pPr");
46234
+ const spacingEl = findOoxmlChild(pPr, "w:spacing");
46235
+ if (!spacingEl) return {};
46236
+ const explicit = {};
46237
+ if (getOoxmlAttribute(spacingEl, "w:before") != null || getOoxmlAttribute(spacingEl, "w:beforeAutospacing") != null || getOoxmlAttribute(spacingEl, "w:beforeAutoSpacing") != null) {
46238
+ explicit.before = true;
46239
+ }
46240
+ if (getOoxmlAttribute(spacingEl, "w:after") != null || getOoxmlAttribute(spacingEl, "w:afterAutospacing") != null || getOoxmlAttribute(spacingEl, "w:afterAutoSpacing") != null) {
46241
+ explicit.after = true;
46242
+ }
46243
+ if (getOoxmlAttribute(spacingEl, "w:line") != null || getOoxmlAttribute(spacingEl, "w:lineRule") != null) {
46244
+ explicit.line = true;
46245
+ }
46246
+ return explicit;
45133
46247
  };
45134
- const parseNumberAttr = (value) => {
45135
- if (value == null) return void 0;
45136
- const num = typeof value === "number" ? value : Number.parseInt(String(value), 10);
45137
- return Number.isFinite(num) ? num : void 0;
46248
+ const mergeSpacingExplicit = (...sources) => {
46249
+ const merged = {};
46250
+ for (const source of sources) {
46251
+ if (source.before) merged.before = true;
46252
+ if (source.after) merged.after = true;
46253
+ if (source.line) merged.line = true;
46254
+ }
46255
+ return merged;
45138
46256
  };
45139
46257
  const mergeSpacingSources = (base2, paragraphProps, attrs) => {
45140
46258
  const isObject2 = (v) => v !== null && typeof v === "object";
@@ -45180,13 +46298,13 @@ const normalizeJustification = (value) => {
45180
46298
  return void 0;
45181
46299
  };
45182
46300
  const extractIndentFromLevel = (lvl) => {
45183
- const pPr = findChild(lvl, "w:pPr");
45184
- const ind = findChild(pPr, "w:ind");
46301
+ const pPr = findOoxmlChild(lvl, "w:pPr");
46302
+ const ind = findOoxmlChild(pPr, "w:ind");
45185
46303
  if (!ind) return void 0;
45186
- const left2 = parseNumberAttr(getAttribute(ind, "w:left"));
45187
- const right2 = parseNumberAttr(getAttribute(ind, "w:right"));
45188
- const firstLine = parseNumberAttr(getAttribute(ind, "w:firstLine"));
45189
- const hanging = parseNumberAttr(getAttribute(ind, "w:hanging"));
46304
+ const left2 = parseOoxmlNumber(getOoxmlAttribute(ind, "w:left"));
46305
+ const right2 = parseOoxmlNumber(getOoxmlAttribute(ind, "w:right"));
46306
+ const firstLine = parseOoxmlNumber(getOoxmlAttribute(ind, "w:firstLine"));
46307
+ const hanging = parseOoxmlNumber(getOoxmlAttribute(ind, "w:hanging"));
45190
46308
  const indent = {};
45191
46309
  if (left2 != null) indent.left = left2;
45192
46310
  if (right2 != null) indent.right = right2;
@@ -45202,31 +46320,31 @@ const normalizeColor = (value) => {
45202
46320
  return `#${upper.toUpperCase()}`;
45203
46321
  };
45204
46322
  const extractMarkerRun = (lvl) => {
45205
- const rPr = findChild(lvl, "w:rPr");
46323
+ const rPr = findOoxmlChild(lvl, "w:rPr");
45206
46324
  if (!rPr) return void 0;
45207
46325
  const run = {};
45208
- const rFonts = findChild(rPr, "w:rFonts");
45209
- const font = getAttribute(rFonts, "w:ascii") ?? getAttribute(rFonts, "w:hAnsi") ?? getAttribute(rFonts, "w:eastAsia");
46326
+ const rFonts = findOoxmlChild(rPr, "w:rFonts");
46327
+ const font = getOoxmlAttribute(rFonts, "w:ascii") ?? getOoxmlAttribute(rFonts, "w:hAnsi") ?? getOoxmlAttribute(rFonts, "w:eastAsia");
45210
46328
  if (typeof font === "string" && font.trim()) {
45211
46329
  run.fontFamily = font;
45212
46330
  }
45213
- const sz = parseNumberAttr(getAttribute(findChild(rPr, "w:sz"), "w:val")) ?? parseNumberAttr(getAttribute(findChild(rPr, "w:szCs"), "w:val"));
46331
+ const sz = parseOoxmlNumber(getOoxmlAttribute(findOoxmlChild(rPr, "w:sz"), "w:val")) ?? parseOoxmlNumber(getOoxmlAttribute(findOoxmlChild(rPr, "w:szCs"), "w:val"));
45214
46332
  if (sz != null) {
45215
46333
  run.fontSize = sz / 2;
45216
46334
  }
45217
- const color = normalizeColor(getAttribute(findChild(rPr, "w:color"), "w:val"));
46335
+ const color = normalizeColor(getOoxmlAttribute(findOoxmlChild(rPr, "w:color"), "w:val"));
45218
46336
  if (color) run.color = color;
45219
- const boldEl = findChild(rPr, "w:b");
46337
+ const boldEl = findOoxmlChild(rPr, "w:b");
45220
46338
  if (boldEl) {
45221
- const boldVal = getAttribute(boldEl, "w:val");
46339
+ const boldVal = getOoxmlAttribute(boldEl, "w:val");
45222
46340
  if (boldVal == null || isTruthy(boldVal)) run.bold = true;
45223
46341
  }
45224
- const italicEl = findChild(rPr, "w:i");
46342
+ const italicEl = findOoxmlChild(rPr, "w:i");
45225
46343
  if (italicEl) {
45226
- const italicVal = getAttribute(italicEl, "w:val");
46344
+ const italicVal = getOoxmlAttribute(italicEl, "w:val");
45227
46345
  if (italicVal == null || isTruthy(italicVal)) run.italic = true;
45228
46346
  }
45229
- const spacingTwips = parseNumberAttr(getAttribute(findChild(rPr, "w:spacing"), "w:val"));
46347
+ const spacingTwips = parseOoxmlNumber(getOoxmlAttribute(findOoxmlChild(rPr, "w:spacing"), "w:val"));
45230
46348
  if (spacingTwips != null && Number.isFinite(spacingTwips)) {
45231
46349
  run.letterSpacing = twipsToPx$1(spacingTwips);
45232
46350
  }
@@ -45234,12 +46352,12 @@ const extractMarkerRun = (lvl) => {
45234
46352
  };
45235
46353
  const findNumFmtElement = (lvl) => {
45236
46354
  if (!lvl) return void 0;
45237
- const direct = findChild(lvl, "w:numFmt");
46355
+ const direct = findOoxmlChild(lvl, "w:numFmt");
45238
46356
  if (direct) return direct;
45239
- const alternate = findChild(lvl, "mc:AlternateContent");
45240
- const choice = findChild(alternate, "mc:Choice");
46357
+ const alternate = findOoxmlChild(lvl, "mc:AlternateContent");
46358
+ const choice = findOoxmlChild(alternate, "mc:Choice");
45241
46359
  if (choice) {
45242
- return findChild(choice, "w:numFmt");
46360
+ return findOoxmlChild(choice, "w:numFmt");
45243
46361
  }
45244
46362
  return void 0;
45245
46363
  };
@@ -45253,7 +46371,7 @@ const resolveNumberingFromContext = (numId, ilvl, numbering) => {
45253
46371
  if (!numDef) {
45254
46372
  return void 0;
45255
46373
  }
45256
- const abstractId = getAttribute(findChild(numDef, "w:abstractNumId"), "w:val");
46374
+ const abstractId = getOoxmlAttribute(findOoxmlChild(numDef, "w:abstractNumId"), "w:val");
45257
46375
  if (abstractId == null) {
45258
46376
  return void 0;
45259
46377
  }
@@ -45262,27 +46380,27 @@ const resolveNumberingFromContext = (numId, ilvl, numbering) => {
45262
46380
  return void 0;
45263
46381
  }
45264
46382
  let levelDef = abstract.elements?.find(
45265
- (el) => el?.name === "w:lvl" && parseNumberAttr(el.attributes?.["w:ilvl"]) === ilvl
46383
+ (el) => el?.name === "w:lvl" && parseOoxmlNumber(el.attributes?.["w:ilvl"]) === ilvl
45266
46384
  );
45267
46385
  const override = numDef.elements?.find(
45268
- (el) => el?.name === "w:lvlOverride" && parseNumberAttr(el.attributes?.["w:ilvl"]) === ilvl
46386
+ (el) => el?.name === "w:lvlOverride" && parseOoxmlNumber(el.attributes?.["w:ilvl"]) === ilvl
45269
46387
  );
45270
- const overrideLvl = findChild(override, "w:lvl");
46388
+ const overrideLvl = findOoxmlChild(override, "w:lvl");
45271
46389
  if (overrideLvl) {
45272
46390
  levelDef = overrideLvl;
45273
46391
  }
45274
- const startOverride = parseNumberAttr(getAttribute(findChild(override, "w:startOverride"), "w:val"));
46392
+ const startOverride = parseOoxmlNumber(getOoxmlAttribute(findOoxmlChild(override, "w:startOverride"), "w:val"));
45275
46393
  if (!levelDef) {
45276
46394
  return void 0;
45277
46395
  }
45278
46396
  const numFmtEl = findNumFmtElement(levelDef);
45279
- const lvlText = getAttribute(findChild(levelDef, "w:lvlText"), "w:val");
45280
- const start2 = startOverride ?? parseNumberAttr(getAttribute(findChild(levelDef, "w:start"), "w:val"));
45281
- const suffix2 = normalizeSuffix(getAttribute(findChild(levelDef, "w:suff"), "w:val"));
45282
- const lvlJc = normalizeJustification(getAttribute(findChild(levelDef, "w:lvlJc"), "w:val"));
46397
+ const lvlText = getOoxmlAttribute(findOoxmlChild(levelDef, "w:lvlText"), "w:val");
46398
+ const start2 = startOverride ?? parseOoxmlNumber(getOoxmlAttribute(findOoxmlChild(levelDef, "w:start"), "w:val"));
46399
+ const suffix2 = normalizeSuffix(getOoxmlAttribute(findOoxmlChild(levelDef, "w:suff"), "w:val"));
46400
+ const lvlJc = normalizeJustification(getOoxmlAttribute(findOoxmlChild(levelDef, "w:lvlJc"), "w:val"));
45283
46401
  const indent = extractIndentFromLevel(levelDef);
45284
46402
  const markerRun = extractMarkerRun(levelDef);
45285
- const numFmt = normalizeNumFmt(getAttribute(numFmtEl, "w:val"));
46403
+ const numFmt = normalizeNumFmt(getOoxmlAttribute(numFmtEl, "w:val"));
45286
46404
  return {
45287
46405
  format: numFmt,
45288
46406
  lvlText,
@@ -45375,6 +46493,7 @@ const cloneParagraphAttrs = (attrs) => {
45375
46493
  if (!attrs) return void 0;
45376
46494
  const clone = { ...attrs };
45377
46495
  if (attrs.spacing) clone.spacing = { ...attrs.spacing };
46496
+ if (attrs.spacingExplicit) clone.spacingExplicit = { ...attrs.spacingExplicit };
45378
46497
  if (attrs.indent) clone.indent = { ...attrs.indent };
45379
46498
  if (attrs.borders) {
45380
46499
  const borderClone = {};
@@ -45750,6 +46869,11 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
45750
46869
  const hydrated = hydrationOverride ?? hydrateParagraphStyleAttrs(para, converterContext);
45751
46870
  const mergedSpacing = mergeSpacingSources(hydrated?.spacing, paragraphProps.spacing, attrs.spacing);
45752
46871
  const normalizedSpacing = normalizeParagraphSpacing(mergedSpacing);
46872
+ const spacingExplicit = mergeSpacingExplicit(
46873
+ extractSpacingExplicitFromObject(paragraphProps.spacing),
46874
+ extractSpacingExplicitFromObject(attrs.spacing),
46875
+ extractSpacingExplicitFromOoxml(paragraphProps)
46876
+ );
45753
46877
  const normalizeIndentObject = (value) => {
45754
46878
  if (!value || typeof value !== "object") return;
45755
46879
  return normalizePxIndent(value) ?? convertIndentTwipsToPx(value);
@@ -45884,6 +47008,7 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
45884
47008
  paragraphAttrs.spacing.afterAutospacing = normalizedSpacing.afterAutospacing;
45885
47009
  }
45886
47010
  }
47011
+ paragraphAttrs.spacingExplicit = spacingExplicit;
45887
47012
  const contextualSpacingValue = normalizedSpacing?.contextualSpacing ?? safeGetProperty(paragraphProps, "contextualSpacing") ?? safeGetProperty(attrs, "contextualSpacing") ?? hydrated?.contextualSpacing;
45888
47013
  if (contextualSpacingValue != null) {
45889
47014
  paragraphAttrs.contextualSpacing = isTruthy(contextualSpacingValue);
@@ -45891,9 +47016,33 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
45891
47016
  const hasExplicitIndent = Boolean(normalizedIndent);
45892
47017
  const hasNumberingIndent = Boolean(computed2.numbering?.indent?.left || computed2.numbering?.indent?.hanging);
45893
47018
  if (hasExplicitIndent || hasNumberingIndent || bidi && adjustRightInd) {
45894
- const indentPx = indentPtToPx(indent);
45895
- if (indentPx) {
45896
- const adjustedIndent = bidi && adjustRightInd ? ensureBidiIndentPx({ ...indentPx }) : indentPx;
47019
+ const styleIndentPx = indentPtToPx(indent);
47020
+ if (styleIndentPx || normalizedIndent) {
47021
+ const mergedIndent = { ...styleIndentPx ?? {} };
47022
+ if (normalizedIndent) {
47023
+ if (normalizedIndent.left !== void 0) {
47024
+ if (normalizedIndent.left === 0) {
47025
+ delete mergedIndent.left;
47026
+ } else {
47027
+ mergedIndent.left = normalizedIndent.left;
47028
+ }
47029
+ }
47030
+ if (normalizedIndent.right !== void 0) {
47031
+ if (normalizedIndent.right === 0) {
47032
+ delete mergedIndent.right;
47033
+ } else {
47034
+ mergedIndent.right = normalizedIndent.right;
47035
+ }
47036
+ }
47037
+ if (normalizedIndent.firstLine !== void 0) mergedIndent.firstLine = normalizedIndent.firstLine;
47038
+ if (normalizedIndent.hanging !== void 0) mergedIndent.hanging = normalizedIndent.hanging;
47039
+ if (normalizedIndent.hanging !== void 0 && normalizedIndent.firstLine === void 0) {
47040
+ delete mergedIndent.firstLine;
47041
+ } else if (normalizedIndent.firstLine !== void 0 && normalizedIndent.hanging === void 0) {
47042
+ delete mergedIndent.hanging;
47043
+ }
47044
+ }
47045
+ const adjustedIndent = bidi && adjustRightInd ? ensureBidiIndentPx({ ...mergedIndent }) : mergedIndent;
45897
47046
  const finalIndent = bidi && adjustRightInd ? mirrorIndentForRtl({ ...adjustedIndent }) : adjustedIndent;
45898
47047
  paragraphAttrs.indent = finalIndent;
45899
47048
  } else if (bidi && adjustRightInd) {
@@ -46346,6 +47495,79 @@ function handleTableOfContentsNode(node, context) {
46346
47495
  }
46347
47496
  });
46348
47497
  }
47498
+ const getIndexChildren = (node) => {
47499
+ if (Array.isArray(node.content)) return node.content;
47500
+ const content = node.content;
47501
+ if (content && typeof content.forEach === "function") {
47502
+ const children = [];
47503
+ content.forEach((child) => {
47504
+ children.push(child);
47505
+ });
47506
+ return children;
47507
+ }
47508
+ return [];
47509
+ };
47510
+ function handleIndexNode(node, context) {
47511
+ const children = getIndexChildren(node);
47512
+ if (children.length === 0) return;
47513
+ const {
47514
+ blocks,
47515
+ recordBlockKind,
47516
+ nextBlockId,
47517
+ positions,
47518
+ defaultFont,
47519
+ defaultSize,
47520
+ styleContext,
47521
+ listCounterContext,
47522
+ trackedChangesConfig,
47523
+ bookmarks,
47524
+ hyperlinkConfig,
47525
+ sectionState,
47526
+ converters
47527
+ } = context;
47528
+ const paragraphToFlowBlocks2 = converters?.paragraphToFlowBlocks;
47529
+ if (!paragraphToFlowBlocks2) {
47530
+ return;
47531
+ }
47532
+ const { getListCounter, incrementListCounter, resetListCounter } = listCounterContext;
47533
+ children.forEach((child) => {
47534
+ if (child.type !== "paragraph") {
47535
+ return;
47536
+ }
47537
+ if (sectionState?.ranges?.length > 0) {
47538
+ const nextSection = sectionState.ranges[sectionState.currentSectionIndex + 1];
47539
+ if (nextSection && sectionState.currentParagraphIndex === nextSection.startParagraphIndex) {
47540
+ const currentSection = sectionState.ranges[sectionState.currentSectionIndex];
47541
+ const requiresPageBoundary = shouldRequirePageBoundary(currentSection, nextSection) || hasIntrinsicBoundarySignals();
47542
+ const extraAttrs = requiresPageBoundary ? { requirePageBoundary: true } : void 0;
47543
+ const sectionBreak = createSectionBreakBlock(nextSection, nextBlockId, extraAttrs);
47544
+ blocks.push(sectionBreak);
47545
+ recordBlockKind(sectionBreak.kind);
47546
+ sectionState.currentSectionIndex++;
47547
+ }
47548
+ }
47549
+ const paragraphBlocks = paragraphToFlowBlocks2(
47550
+ child,
47551
+ nextBlockId,
47552
+ positions,
47553
+ defaultFont,
47554
+ defaultSize,
47555
+ styleContext,
47556
+ { getListCounter, incrementListCounter, resetListCounter },
47557
+ trackedChangesConfig,
47558
+ bookmarks,
47559
+ hyperlinkConfig,
47560
+ void 0,
47561
+ // themeColors - not available in NodeHandlerContext
47562
+ context.converterContext
47563
+ );
47564
+ paragraphBlocks.forEach((block) => {
47565
+ blocks.push(block);
47566
+ recordBlockKind(block.kind);
47567
+ });
47568
+ sectionState.currentParagraphIndex++;
47569
+ });
47570
+ }
46349
47571
  function handleStructuredContentBlockNode(node, context) {
46350
47572
  if (!Array.isArray(node.content)) return;
46351
47573
  const {
@@ -47253,7 +48475,10 @@ function fieldAnnotationNodeToRun(node, positions, fieldMetadata) {
47253
48475
  }
47254
48476
  return run;
47255
48477
  }
47256
- const isTextRun = (run) => run.kind !== "tab";
48478
+ const isTextRun = (run) => {
48479
+ const kind = run.kind;
48480
+ return (kind === void 0 || kind === "text") && "text" in run;
48481
+ };
47257
48482
  const dataAttrsCompatible = (a, b2) => {
47258
48483
  const aAttrs = a.dataAttrs;
47259
48484
  const bAttrs = b2.dataAttrs;
@@ -47362,6 +48587,75 @@ const extractFirstTextRunFont = (para) => {
47362
48587
  const font = findFirstTextFont(para.content);
47363
48588
  return font;
47364
48589
  };
48590
+ const resolveRunFontFamily = (fontFamily2, docx) => {
48591
+ if (typeof fontFamily2 === "string" && fontFamily2.trim().length > 0) {
48592
+ return fontFamily2;
48593
+ }
48594
+ if (!fontFamily2 || typeof fontFamily2 !== "object") return void 0;
48595
+ const toCssFontFamily2 = SuperConverter.toCssFontFamily;
48596
+ const resolved = resolveDocxFontFamily(fontFamily2, docx ?? null, toCssFontFamily2);
48597
+ return resolved ?? void 0;
48598
+ };
48599
+ const parseRunFontSizePx = (fontSize2) => {
48600
+ if (typeof fontSize2 === "number" && Number.isFinite(fontSize2)) {
48601
+ return ptToPx(fontSize2 / HALF_POINTS_PER_POINT) ?? void 0;
48602
+ }
48603
+ if (typeof fontSize2 === "string") {
48604
+ const numeric = Number.parseFloat(fontSize2);
48605
+ if (!Number.isFinite(numeric)) return void 0;
48606
+ if (fontSize2.endsWith("pt")) {
48607
+ return ptToPx(numeric);
48608
+ }
48609
+ if (fontSize2.endsWith("px")) {
48610
+ return numeric;
48611
+ }
48612
+ return ptToPx(numeric / HALF_POINTS_PER_POINT) ?? void 0;
48613
+ }
48614
+ return void 0;
48615
+ };
48616
+ const extractParagraphMarkRunProps = (paragraphProps) => {
48617
+ const directRunProps = paragraphProps.runProperties;
48618
+ const directRunPropsElement = asOoxmlElement(directRunProps);
48619
+ if (directRunProps && isPlainObject$2(directRunProps) && !directRunPropsElement) {
48620
+ return directRunProps;
48621
+ }
48622
+ const element = asOoxmlElement(paragraphProps);
48623
+ const pPr = element ? element.name === "w:pPr" ? element : findOoxmlChild(element, "w:pPr") : void 0;
48624
+ const rPr = directRunPropsElement?.name === "w:rPr" ? directRunPropsElement : findOoxmlChild(pPr, "w:rPr");
48625
+ if (!rPr) return void 0;
48626
+ const runProps = {};
48627
+ const sz = parseOoxmlNumber(getOoxmlAttribute(findOoxmlChild(rPr, "w:sz"), "w:val")) ?? parseOoxmlNumber(getOoxmlAttribute(findOoxmlChild(rPr, "w:szCs"), "w:val"));
48628
+ if (sz != null) {
48629
+ runProps.fontSize = sz;
48630
+ }
48631
+ const rFonts = findOoxmlChild(rPr, "w:rFonts");
48632
+ if (rFonts) {
48633
+ const fontFamily2 = {};
48634
+ const keys2 = ["ascii", "hAnsi", "eastAsia", "cs", "val", "asciiTheme", "hAnsiTheme", "eastAsiaTheme", "cstheme"];
48635
+ for (const key2 of keys2) {
48636
+ const value = getOoxmlAttribute(rFonts, `w:${key2}`);
48637
+ if (value != null) {
48638
+ fontFamily2[key2] = value;
48639
+ }
48640
+ }
48641
+ if (Object.keys(fontFamily2).length > 0) {
48642
+ runProps.fontFamily = fontFamily2;
48643
+ }
48644
+ }
48645
+ return Object.keys(runProps).length > 0 ? runProps : void 0;
48646
+ };
48647
+ const applyParagraphMarkRunProps = (run, paragraphProps, converterContext) => {
48648
+ const runProps = extractParagraphMarkRunProps(paragraphProps);
48649
+ if (!runProps) return;
48650
+ const fontSizePx = parseRunFontSizePx(runProps.fontSize);
48651
+ if (fontSizePx != null) {
48652
+ run.fontSize = fontSizePx;
48653
+ }
48654
+ const fontFamily2 = resolveRunFontFamily(runProps.fontFamily, converterContext?.docx);
48655
+ if (fontFamily2) {
48656
+ run.fontFamily = fontFamily2;
48657
+ }
48658
+ };
47365
48659
  const applyBaseRunDefaults = (run, defaults, uiDisplayFallbackFont, fallbackSize) => {
47366
48660
  if (!run) return;
47367
48661
  if (defaults.fontFamily && run.fontFamily === uiDisplayFallbackFont) {
@@ -47452,6 +48746,13 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
47452
48746
  converterContext,
47453
48747
  paragraphHydration
47454
48748
  );
48749
+ if (paragraphAttrs && (!Array.isArray(paragraphAttrs.tabs) || paragraphAttrs.tabs.length === 0)) {
48750
+ const rawTabs = para.attrs?.tabs ?? para.attrs?.tabStops ?? paragraphProps.tabStops ?? paragraphProps.tabs;
48751
+ const normalizedTabs = normalizeOoxmlTabs(rawTabs);
48752
+ if (normalizedTabs && normalizedTabs.length > 0) {
48753
+ paragraphAttrs.tabs = normalizedTabs;
48754
+ }
48755
+ }
47455
48756
  if (paragraphAttrs?.spacing) {
47456
48757
  const spacing = { ...paragraphAttrs.spacing };
47457
48758
  const effectiveFontSize = baseRunDefaults.fontSizePx ?? defaultSize;
@@ -47511,6 +48812,8 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
47511
48812
  emptyRun.pmStart = paraPos.start + 1;
47512
48813
  emptyRun.pmEnd = paraPos.start + 1;
47513
48814
  }
48815
+ applyBaseRunDefaults(emptyRun, baseRunDefaults, defaultFont, defaultSize);
48816
+ applyParagraphMarkRunProps(emptyRun, paragraphProps, converterContext);
47514
48817
  let emptyParagraphAttrs = cloneParagraphAttrs(paragraphAttrs);
47515
48818
  if (isSectPrMarker) {
47516
48819
  if (emptyParagraphAttrs) {
@@ -49013,6 +50316,7 @@ const DEFAULT_DECIMAL_SEPARATOR$1 = ".";
49013
50316
  const nodeHandlers = {
49014
50317
  paragraph: handleParagraphNode,
49015
50318
  tableOfContents: handleTableOfContentsNode,
50319
+ index: handleIndexNode,
49016
50320
  structuredContentBlock: handleStructuredContentBlockNode,
49017
50321
  documentSection: handleDocumentSectionNode,
49018
50322
  table: handleTableNode,
@@ -50898,7 +52202,6 @@ function measureText(text, font, ctx2, _fontFamily, _letterSpacing) {
50898
52202
  const paintedWidth = (metrics.actualBoundingBoxLeft || 0) + (metrics.actualBoundingBoxRight || 0);
50899
52203
  return Math.max(advanceWidth, paintedWidth);
50900
52204
  }
50901
- const MIN_SINGLE_LINE_PX = 12 * 96 / 72;
50902
52205
  const WORD_SINGLE_LINE_SPACING_MULTIPLIER = 1.15;
50903
52206
  function calculateTypographyMetrics(fontSize2, spacing, fontInfo) {
50904
52207
  let ascent;
@@ -50912,7 +52215,27 @@ function calculateTypographyMetrics(fontSize2, spacing, fontInfo) {
50912
52215
  ascent = roundValue(fontSize2 * 0.8);
50913
52216
  descent = roundValue(fontSize2 * 0.2);
50914
52217
  }
50915
- const baseLineHeight = Math.max(fontSize2 * WORD_SINGLE_LINE_SPACING_MULTIPLIER, ascent + descent, MIN_SINGLE_LINE_PX);
52218
+ const baseLineHeight = Math.max(fontSize2 * WORD_SINGLE_LINE_SPACING_MULTIPLIER, ascent + descent);
52219
+ const lineHeight2 = roundValue(resolveLineHeight(spacing, baseLineHeight));
52220
+ return {
52221
+ ascent,
52222
+ descent,
52223
+ lineHeight: lineHeight2
52224
+ };
52225
+ }
52226
+ function calculateEmptyParagraphMetrics(fontSize2, spacing, fontInfo) {
52227
+ let ascent;
52228
+ let descent;
52229
+ if (fontInfo) {
52230
+ const ctx2 = getCanvasContext();
52231
+ const metrics = getFontMetrics(ctx2, fontInfo);
52232
+ ascent = roundValue(metrics.ascent);
52233
+ descent = roundValue(metrics.descent);
52234
+ } else {
52235
+ ascent = roundValue(fontSize2 * 0.8);
52236
+ descent = roundValue(fontSize2 * 0.2);
52237
+ }
52238
+ const baseLineHeight = Math.max(fontSize2, ascent + descent);
50916
52239
  const lineHeight2 = roundValue(resolveLineHeight(spacing, baseLineHeight));
50917
52240
  return {
50918
52241
  ascent,
@@ -50943,6 +52266,10 @@ function isImageRun(run) {
50943
52266
  function isLineBreakRun(run) {
50944
52267
  return run.kind === "lineBreak";
50945
52268
  }
52269
+ const isEmptyTextRun = (run) => {
52270
+ if (run.kind && run.kind !== "text") return false;
52271
+ return typeof run.text === "string" && run.text.length === 0;
52272
+ };
50946
52273
  function isFieldAnnotationRun(run) {
50947
52274
  return run.kind === "fieldAnnotation";
50948
52275
  }
@@ -51112,8 +52439,28 @@ async function measureParagraphBlock(block, maxWidth) {
51112
52439
  dropCapDescriptor.measuredHeight = dropCapMeasured.height;
51113
52440
  }
51114
52441
  }
52442
+ const emptyParagraphRun = block.runs.length === 1 && isEmptyTextRun(block.runs[0]) ? block.runs[0] : null;
52443
+ if (emptyParagraphRun) {
52444
+ const fontSize2 = emptyParagraphRun.fontSize ?? 12;
52445
+ const metrics = calculateEmptyParagraphMetrics(fontSize2, spacing, getFontInfoFromRun(emptyParagraphRun));
52446
+ const emptyLine = {
52447
+ fromRun: 0,
52448
+ fromChar: 0,
52449
+ toRun: 0,
52450
+ toChar: 0,
52451
+ width: 0,
52452
+ ...metrics
52453
+ };
52454
+ addBarTabsToLine(emptyLine);
52455
+ lines.push(emptyLine);
52456
+ return {
52457
+ kind: "paragraph",
52458
+ lines,
52459
+ totalHeight: metrics.lineHeight
52460
+ };
52461
+ }
51115
52462
  if (block.runs.length === 0) {
51116
- const metrics = calculateTypographyMetrics(12, spacing);
52463
+ const metrics = calculateEmptyParagraphMetrics(12, spacing);
51117
52464
  const emptyLine = {
51118
52465
  fromRun: 0,
51119
52466
  fromChar: 0,
@@ -51130,6 +52477,11 @@ async function measureParagraphBlock(block, maxWidth) {
51130
52477
  totalHeight: metrics.lineHeight
51131
52478
  };
51132
52479
  }
52480
+ const firstTextRunWithSize = block.runs.find(
52481
+ (run) => "text" in run && "fontSize" in run && typeof run.fontSize === "number"
52482
+ );
52483
+ const fallbackFontSize = firstTextRunWithSize?.fontSize ?? 12;
52484
+ const fallbackFontInfo = firstTextRunWithSize ? getFontInfoFromRun(firstTextRunWithSize) : void 0;
51133
52485
  let currentLine = null;
51134
52486
  const getEffectiveWidth = (baseWidth) => {
51135
52487
  if (dropCapMeasure && lines.length < dropCapMeasure.lines && dropCapMeasure.mode === "drop") {
@@ -51137,7 +52489,8 @@ async function measureParagraphBlock(block, maxWidth) {
51137
52489
  }
51138
52490
  return baseWidth;
51139
52491
  };
51140
- let lastFontSize = 12;
52492
+ let lastFontSize = fallbackFontSize;
52493
+ let hasSeenTextRun = false;
51141
52494
  let tabStopCursor = 0;
51142
52495
  let pendingTabAlignment = null;
51143
52496
  let pendingRunSpacing = 0;
@@ -51262,11 +52615,7 @@ async function measureParagraphBlock(block, maxWidth) {
51262
52615
  lines.push(completedLine);
51263
52616
  currentLine = null;
51264
52617
  } else {
51265
- const textRunWithSize = block.runs.find(
51266
- (r2) => r2.kind !== "tab" && r2.kind !== "lineBreak" && r2.kind !== "break" && !("src" in r2) && "fontSize" in r2
51267
- );
51268
- const fallbackSize = textRunWithSize?.fontSize ?? 12;
51269
- const metrics = calculateTypographyMetrics(fallbackSize, spacing);
52618
+ const metrics = calculateTypographyMetrics(fallbackFontSize, spacing, fallbackFontInfo);
51270
52619
  const emptyLine = {
51271
52620
  fromRun: runIndex,
51272
52621
  fromChar: 0,
@@ -51286,6 +52635,7 @@ async function measureParagraphBlock(block, maxWidth) {
51286
52635
  continue;
51287
52636
  }
51288
52637
  if (isLineBreakRun(run)) {
52638
+ const lineBreakFontInfo = hasSeenTextRun ? void 0 : fallbackFontInfo;
51289
52639
  if (currentLine) {
51290
52640
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
51291
52641
  const completedLine = {
@@ -51295,7 +52645,7 @@ async function measureParagraphBlock(block, maxWidth) {
51295
52645
  addBarTabsToLine(completedLine);
51296
52646
  lines.push(completedLine);
51297
52647
  } else {
51298
- const metrics = calculateTypographyMetrics(lastFontSize, spacing);
52648
+ const metrics = calculateTypographyMetrics(lastFontSize, spacing, lineBreakFontInfo);
51299
52649
  const emptyLine = {
51300
52650
  fromRun: runIndex,
51301
52651
  fromChar: 0,
@@ -51318,6 +52668,7 @@ async function measureParagraphBlock(block, maxWidth) {
51318
52668
  toChar: 0,
51319
52669
  width: 0,
51320
52670
  maxFontSize: lastFontSize,
52671
+ maxFontInfo: lineBreakFontInfo,
51321
52672
  maxWidth: nextLineMaxWidth,
51322
52673
  segments: [],
51323
52674
  spaceCount: 0
@@ -51510,8 +52861,21 @@ async function measureParagraphBlock(block, maxWidth) {
51510
52861
  const annotationFont = `${fontStyle} ${fontWeight} ${annotationFontSize}px ${annotationFontFamily}`;
51511
52862
  ctx2.font = annotationFont;
51512
52863
  const textWidth = displayText ? ctx2.measureText(displayText).width : 0;
51513
- const annotationWidth = textWidth + FIELD_ANNOTATION_PILL_PADDING;
51514
- const annotationHeight = annotationFontSize * FIELD_ANNOTATION_LINE_HEIGHT_MULTIPLIER + FIELD_ANNOTATION_VERTICAL_PADDING;
52864
+ const annotationHorizontalPadding = run.highlighted === false ? 0 : FIELD_ANNOTATION_PILL_PADDING;
52865
+ const annotationVerticalPadding = run.highlighted === false ? 0 : FIELD_ANNOTATION_VERTICAL_PADDING;
52866
+ const annotationWidth = textWidth + annotationHorizontalPadding;
52867
+ let annotationHeight = annotationFontSize * FIELD_ANNOTATION_LINE_HEIGHT_MULTIPLIER + annotationVerticalPadding;
52868
+ if (run.variant === "signature" && run.imageSrc) {
52869
+ const signatureHeight = 28 + annotationVerticalPadding;
52870
+ annotationHeight = Math.max(annotationHeight, signatureHeight);
52871
+ }
52872
+ if (run.variant === "image" && run.imageSrc && run.size?.height) {
52873
+ const imageHeight = run.size.height + annotationVerticalPadding;
52874
+ annotationHeight = Math.max(annotationHeight, imageHeight);
52875
+ }
52876
+ if (run.variant === "html" && run.size?.height) {
52877
+ annotationHeight = Math.max(annotationHeight, run.size.height);
52878
+ }
51515
52879
  let annotationStartX;
51516
52880
  if (pendingTabAlignment && currentLine) {
51517
52881
  annotationStartX = alignPendingTabForWidth(annotationWidth);
@@ -51598,6 +52962,7 @@ async function measureParagraphBlock(block, maxWidth) {
51598
52962
  continue;
51599
52963
  }
51600
52964
  lastFontSize = run.fontSize;
52965
+ hasSeenTextRun = true;
51601
52966
  const { font } = buildFontString(run);
51602
52967
  const tabSegments = run.text.split(" ");
51603
52968
  let charPosInRun = 0;
@@ -51708,7 +53073,10 @@ async function measureParagraphBlock(block, maxWidth) {
51708
53073
  trimTrailingWrapSpaces(currentLine);
51709
53074
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
51710
53075
  const lineBase = currentLine;
51711
- const completedLine = { ...lineBase, ...metrics };
53076
+ const completedLine = {
53077
+ ...lineBase,
53078
+ ...metrics
53079
+ };
51712
53080
  addBarTabsToLine(completedLine);
51713
53081
  lines.push(completedLine);
51714
53082
  tabStopCursor = 0;
@@ -51765,7 +53133,10 @@ async function measureParagraphBlock(block, maxWidth) {
51765
53133
  trimTrailingWrapSpaces(currentLine);
51766
53134
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
51767
53135
  const lineBase = currentLine;
51768
- const completedLine = { ...lineBase, ...metrics };
53136
+ const completedLine = {
53137
+ ...lineBase,
53138
+ ...metrics
53139
+ };
51769
53140
  addBarTabsToLine(completedLine);
51770
53141
  lines.push(completedLine);
51771
53142
  tabStopCursor = 0;
@@ -51810,7 +53181,10 @@ async function measureParagraphBlock(block, maxWidth) {
51810
53181
  trimTrailingWrapSpaces(currentLine);
51811
53182
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
51812
53183
  const lineBase = currentLine;
51813
- const completedLine = { ...lineBase, ...metrics };
53184
+ const completedLine = {
53185
+ ...lineBase,
53186
+ ...metrics
53187
+ };
51814
53188
  addBarTabsToLine(completedLine);
51815
53189
  lines.push(completedLine);
51816
53190
  tabStopCursor = 0;
@@ -52256,6 +53630,10 @@ async function measureTableBlock(block, constraints) {
52256
53630
  const measure = await measureBlock(block2, { maxWidth: contentWidth, maxHeight: Infinity });
52257
53631
  blockMeasures.push(measure);
52258
53632
  const blockHeight = "totalHeight" in measure ? measure.totalHeight : "height" in measure ? measure.height : 0;
53633
+ const isAnchoredOutOfFlow = (block2.kind === "image" || block2.kind === "drawing") && block2.anchor?.isAnchored === true && (block2.wrap?.type ?? "Inline") !== "Inline";
53634
+ if (isAnchoredOutOfFlow) {
53635
+ continue;
53636
+ }
52259
53637
  contentHeight += blockHeight;
52260
53638
  if (block2.kind === "paragraph") {
52261
53639
  const spacingAfter = block2.attrs?.spacing?.after;
@@ -52825,6 +54203,9 @@ class PresentationEditor extends EventEmitter {
52825
54203
  #remoteCursorUpdateScheduled = false;
52826
54204
  #epochMapper = new EpochPositionMapper();
52827
54205
  #layoutEpoch = 0;
54206
+ #htmlAnnotationHeights = /* @__PURE__ */ new Map();
54207
+ #htmlAnnotationMeasureEpoch = -1;
54208
+ #htmlAnnotationMeasureAttempts = 0;
52828
54209
  #domPositionIndex = new DomPositionIndex();
52829
54210
  #domIndexObserverManager = null;
52830
54211
  #debugLastPointer = null;
@@ -56083,6 +57464,7 @@ class PresentationEditor extends EventEmitter {
56083
57464
  this.#handleLayoutError("render", new Error("toFlowBlocks returned undefined blocks"));
56084
57465
  return;
56085
57466
  }
57467
+ this.#applyHtmlAnnotationMeasurements(blocks);
56086
57468
  const baseLayoutOptions = this.#resolveLayoutOptions(blocks, sectionMetadata);
56087
57469
  const footnotesLayoutInput = this.#buildFootnotesLayoutInput({
56088
57470
  converterContext,
@@ -56201,6 +57583,10 @@ class PresentationEditor extends EventEmitter {
56201
57583
  this.#rebuildDomPositionIndex();
56202
57584
  this.#domIndexObserverManager?.resume();
56203
57585
  this.#layoutEpoch = layoutEpoch;
57586
+ if (this.#updateHtmlAnnotationMeasurements(layoutEpoch)) {
57587
+ this.#pendingDocChange = true;
57588
+ this.#scheduleRerender();
57589
+ }
56204
57590
  this.#epochMapper.onLayoutComplete(layoutEpoch);
56205
57591
  this.#selectionSync.onLayoutComplete(layoutEpoch);
56206
57592
  layoutCompleted = true;
@@ -56250,6 +57636,68 @@ class PresentationEditor extends EventEmitter {
56250
57636
  }
56251
57637
  return this.#domPainter;
56252
57638
  }
57639
+ #applyHtmlAnnotationMeasurements(blocks) {
57640
+ if (this.#htmlAnnotationHeights.size === 0) return;
57641
+ blocks.forEach((block) => {
57642
+ if (block.kind !== "paragraph") return;
57643
+ block.runs.forEach((run) => {
57644
+ if (run.kind !== "fieldAnnotation" || run.variant !== "html") {
57645
+ return;
57646
+ }
57647
+ if (run.pmStart == null || run.pmEnd == null) {
57648
+ return;
57649
+ }
57650
+ const key2 = `${run.pmStart}-${run.pmEnd}`;
57651
+ const height = this.#htmlAnnotationHeights.get(key2);
57652
+ if (!height || height <= 0) {
57653
+ return;
57654
+ }
57655
+ const currentSize = run.size ?? {};
57656
+ if (currentSize.height === height) {
57657
+ return;
57658
+ }
57659
+ run.size = { ...currentSize, height };
57660
+ });
57661
+ });
57662
+ }
57663
+ #updateHtmlAnnotationMeasurements(layoutEpoch) {
57664
+ const nextHeights = new Map(this.#htmlAnnotationHeights);
57665
+ const annotations = this.#painterHost.querySelectorAll('.annotation[data-type="html"]');
57666
+ const threshold = 1;
57667
+ let changed = false;
57668
+ annotations.forEach((annotation) => {
57669
+ const element = annotation;
57670
+ const pmStart = element.dataset.pmStart;
57671
+ const pmEnd = element.dataset.pmEnd;
57672
+ if (!pmStart || !pmEnd) {
57673
+ return;
57674
+ }
57675
+ const height = element.offsetHeight;
57676
+ if (height <= 0) {
57677
+ return;
57678
+ }
57679
+ const key2 = `${pmStart}-${pmEnd}`;
57680
+ const prev = nextHeights.get(key2);
57681
+ if (prev != null && Math.abs(prev - height) <= threshold) {
57682
+ return;
57683
+ }
57684
+ nextHeights.set(key2, height);
57685
+ changed = true;
57686
+ });
57687
+ if (layoutEpoch !== this.#htmlAnnotationMeasureEpoch) {
57688
+ this.#htmlAnnotationMeasureEpoch = layoutEpoch;
57689
+ this.#htmlAnnotationMeasureAttempts = 0;
57690
+ }
57691
+ this.#htmlAnnotationHeights = nextHeights;
57692
+ if (!changed) {
57693
+ return false;
57694
+ }
57695
+ if (this.#htmlAnnotationMeasureAttempts >= 2) {
57696
+ return false;
57697
+ }
57698
+ this.#htmlAnnotationMeasureAttempts += 1;
57699
+ return true;
57700
+ }
56253
57701
  /**
56254
57702
  * Requests a local selection overlay update.
56255
57703
  *
@@ -68979,6 +70427,55 @@ const TableOfContents = Node$1.create({
68979
70427
  };
68980
70428
  }
68981
70429
  });
70430
+ const DocumentIndex = Node$1.create({
70431
+ name: "index",
70432
+ group: "block",
70433
+ content: "paragraph+",
70434
+ inline: false,
70435
+ addOptions() {
70436
+ return {
70437
+ htmlAttributes: {
70438
+ "data-id": "document-index",
70439
+ "aria-label": "Index"
70440
+ }
70441
+ };
70442
+ },
70443
+ parseDOM() {
70444
+ return [
70445
+ {
70446
+ tag: 'div[data-id="document-index"]'
70447
+ }
70448
+ ];
70449
+ },
70450
+ renderDOM({ htmlAttributes }) {
70451
+ return ["div", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
70452
+ },
70453
+ addAttributes() {
70454
+ return {
70455
+ instruction: {
70456
+ default: null,
70457
+ rendered: false
70458
+ },
70459
+ instructionTokens: {
70460
+ default: null,
70461
+ rendered: false
70462
+ },
70463
+ /**
70464
+ * @private
70465
+ * @category Attribute
70466
+ * @param {string} [sdBlockId] - Internal block tracking ID (not user-configurable)
70467
+ */
70468
+ sdBlockId: {
70469
+ default: null,
70470
+ keepOnSplit: false,
70471
+ parseDOM: (elem) => elem.getAttribute("data-sd-block-id"),
70472
+ renderDOM: (attrs) => {
70473
+ return attrs.sdBlockId ? { "data-sd-block-id": attrs.sdBlockId } : {};
70474
+ }
70475
+ }
70476
+ };
70477
+ }
70478
+ });
68982
70479
  function createGradient(gradientData, gradientId) {
68983
70480
  const { gradientType, stops, angle } = gradientData;
68984
70481
  if (!stops || stops.length === 0) {
@@ -69015,7 +70512,8 @@ function createGradient(gradientData, gradientId) {
69015
70512
  });
69016
70513
  return gradient;
69017
70514
  }
69018
- function createTextElement(textContent2, textAlign, width, height) {
70515
+ function createTextElement(textContent2, textAlign, width, height, options = {}) {
70516
+ const { textInsets, textVerticalAlign, pageNumber, totalPages } = options;
69019
70517
  const foreignObject = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject");
69020
70518
  foreignObject.setAttribute("x", "0");
69021
70519
  foreignObject.setAttribute("y", "0");
@@ -69026,8 +70524,19 @@ function createTextElement(textContent2, textAlign, width, height) {
69026
70524
  div2.style.height = "100%";
69027
70525
  div2.style.display = "flex";
69028
70526
  div2.style.flexDirection = "column";
69029
- div2.style.justifyContent = "center";
69030
- div2.style.padding = "10px";
70527
+ const verticalAlign = textVerticalAlign || "center";
70528
+ if (verticalAlign === "top") {
70529
+ div2.style.justifyContent = "flex-start";
70530
+ } else if (verticalAlign === "bottom") {
70531
+ div2.style.justifyContent = "flex-end";
70532
+ } else {
70533
+ div2.style.justifyContent = "center";
70534
+ }
70535
+ if (textInsets) {
70536
+ div2.style.padding = `${textInsets.top}px ${textInsets.right}px ${textInsets.bottom}px ${textInsets.left}px`;
70537
+ } else {
70538
+ div2.style.padding = "10px";
70539
+ }
69031
70540
  div2.style.boxSizing = "border-box";
69032
70541
  div2.style.wordWrap = "break-word";
69033
70542
  div2.style.overflowWrap = "break-word";
@@ -69041,6 +70550,15 @@ function createTextElement(textContent2, textAlign, width, height) {
69041
70550
  div2.style.textAlign = "left";
69042
70551
  }
69043
70552
  let currentParagraph = document.createElement("div");
70553
+ const resolveFieldText = (part) => {
70554
+ if (part.fieldType === "PAGE") {
70555
+ return pageNumber != null ? String(pageNumber) : "1";
70556
+ }
70557
+ if (part.fieldType === "NUMPAGES") {
70558
+ return totalPages != null ? String(totalPages) : "1";
70559
+ }
70560
+ return part.text;
70561
+ };
69044
70562
  textContent2.parts.forEach((part) => {
69045
70563
  if (part.isLineBreak) {
69046
70564
  div2.appendChild(currentParagraph);
@@ -69050,7 +70568,7 @@ function createTextElement(textContent2, textAlign, width, height) {
69050
70568
  }
69051
70569
  } else {
69052
70570
  const span = document.createElement("span");
69053
- span.textContent = part.text;
70571
+ span.textContent = resolveFieldText(part);
69054
70572
  if (part.formatting) {
69055
70573
  if (part.formatting.bold) {
69056
70574
  span.style.fontWeight = "bold";
@@ -69058,6 +70576,9 @@ function createTextElement(textContent2, textAlign, width, height) {
69058
70576
  if (part.formatting.italic) {
69059
70577
  span.style.fontStyle = "italic";
69060
70578
  }
70579
+ if (part.formatting.fontFamily) {
70580
+ span.style.fontFamily = part.formatting.fontFamily;
70581
+ }
69061
70582
  if (part.formatting.color) {
69062
70583
  span.style.color = `#${part.formatting.color}`;
69063
70584
  }
@@ -69248,7 +70769,14 @@ class VectorShapeView {
69248
70769
  this.applyLineEnds(svg, attrs);
69249
70770
  element.appendChild(svg);
69250
70771
  if (attrs.textContent && attrs.textContent.parts) {
69251
- const textElement = this.createTextElement(attrs.textContent, attrs.textAlign, attrs.width, attrs.height);
70772
+ const pageNumber = this.editor?.options?.currentPageNumber;
70773
+ const totalPages = this.editor?.options?.totalPageCount;
70774
+ const textElement = this.createTextElement(attrs.textContent, attrs.textAlign, attrs.width, attrs.height, {
70775
+ textVerticalAlign: attrs.textVerticalAlign,
70776
+ textInsets: attrs.textInsets,
70777
+ pageNumber,
70778
+ totalPages
70779
+ });
69252
70780
  if (textElement) {
69253
70781
  svg.appendChild(textElement);
69254
70782
  }
@@ -69580,8 +71108,8 @@ class VectorShapeView {
69580
71108
  applyAlphaToSVG(svg, alphaData) {
69581
71109
  applyAlphaToSVG(svg, alphaData);
69582
71110
  }
69583
- createTextElement(textContent2, textAlign, width, height) {
69584
- return createTextElement(textContent2, textAlign, width, height);
71111
+ createTextElement(textContent2, textAlign, width, height, options) {
71112
+ return createTextElement(textContent2, textAlign, width, height, options);
69585
71113
  }
69586
71114
  buildView() {
69587
71115
  const { element } = this.createElement();
@@ -69933,7 +71461,14 @@ class ShapeGroupView {
69933
71461
  }
69934
71462
  g2.appendChild(line);
69935
71463
  if (attrs.textContent && attrs.textContent.parts) {
69936
- const textGroup = this.createTextElement(attrs.textContent, attrs.textAlign, width, height);
71464
+ const pageNumber = this.editor?.options?.currentPageNumber;
71465
+ const totalPages = this.editor?.options?.totalPageCount;
71466
+ const textGroup = this.createTextElement(attrs.textContent, attrs.textAlign, width, height, {
71467
+ textVerticalAlign: attrs.textVerticalAlign,
71468
+ textInsets: attrs.textInsets,
71469
+ pageNumber,
71470
+ totalPages
71471
+ });
69937
71472
  if (textGroup) {
69938
71473
  g2.appendChild(textGroup);
69939
71474
  }
@@ -70027,15 +71562,22 @@ class ShapeGroupView {
70027
71562
  g2.appendChild(rect);
70028
71563
  }
70029
71564
  if (attrs.textContent && attrs.textContent.parts) {
70030
- const textGroup = this.createTextElement(attrs.textContent, attrs.textAlign, width, height);
71565
+ const pageNumber = this.editor?.options?.currentPageNumber;
71566
+ const totalPages = this.editor?.options?.totalPageCount;
71567
+ const textGroup = this.createTextElement(attrs.textContent, attrs.textAlign, width, height, {
71568
+ textVerticalAlign: attrs.textVerticalAlign,
71569
+ textInsets: attrs.textInsets,
71570
+ pageNumber,
71571
+ totalPages
71572
+ });
70031
71573
  if (textGroup) {
70032
71574
  g2.appendChild(textGroup);
70033
71575
  }
70034
71576
  }
70035
71577
  return g2;
70036
71578
  }
70037
- createTextElement(textContent2, textAlign, width, height) {
70038
- return createTextElement(textContent2, textAlign, width, height);
71579
+ createTextElement(textContent2, textAlign, width, height, options) {
71580
+ return createTextElement(textContent2, textAlign, width, height, options);
70039
71581
  }
70040
71582
  /**
70041
71583
  * Applies line end markers (arrowheads) to a target SVG element.
@@ -70285,6 +71827,47 @@ const PassthroughInline = Node$1.create({
70285
71827
  return sharedAttributes();
70286
71828
  }
70287
71829
  });
71830
+ const IndexEntry = Node$1.create({
71831
+ name: "indexEntry",
71832
+ group: "inline",
71833
+ inline: true,
71834
+ atom: true,
71835
+ draggable: false,
71836
+ selectable: false,
71837
+ content: "inline*",
71838
+ addOptions() {
71839
+ return {
71840
+ htmlAttributes: {
71841
+ contenteditable: false,
71842
+ "data-id": "document-index-entry",
71843
+ "aria-label": "Index entry",
71844
+ style: "display:none"
71845
+ }
71846
+ };
71847
+ },
71848
+ addAttributes() {
71849
+ return {
71850
+ instruction: {
71851
+ default: "",
71852
+ rendered: false
71853
+ },
71854
+ instructionTokens: {
71855
+ default: null,
71856
+ rendered: false
71857
+ },
71858
+ marksAsAttrs: {
71859
+ default: null,
71860
+ rendered: false
71861
+ }
71862
+ };
71863
+ },
71864
+ parseDOM() {
71865
+ return [{ tag: 'span[data-id="document-index-entry"]' }];
71866
+ },
71867
+ renderDOM({ htmlAttributes }) {
71868
+ return ["span", Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes), 0];
71869
+ }
71870
+ });
70288
71871
  const TextStyle = Mark.create({
70289
71872
  name: "textStyle",
70290
71873
  addOptions() {
@@ -77025,6 +78608,7 @@ const getStarterExtensions = () => {
77025
78608
  Strike,
77026
78609
  TabNode,
77027
78610
  TableOfContents,
78611
+ DocumentIndex,
77028
78612
  Text,
77029
78613
  TextAlign,
77030
78614
  TextStyle,
@@ -77058,6 +78642,7 @@ const getStarterExtensions = () => {
77058
78642
  PageNumber,
77059
78643
  TotalPageCount,
77060
78644
  PageReference,
78645
+ IndexEntry,
77061
78646
  ShapeContainer,
77062
78647
  ShapeTextbox,
77063
78648
  ContentBlock,
@@ -94434,6 +96019,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
94434
96019
  };
94435
96020
  const getExtensions = () => getStarterExtensions();
94436
96021
  const initEditor = async ({ content, media = {}, mediaFiles = {}, fonts = {} } = {}) => {
96022
+ if (!editorElem.value) return;
94437
96023
  const { editorCtor, ...editorOptions } = props.options || {};
94438
96024
  const EditorCtor = editorCtor ?? Editor;
94439
96025
  clearSelectedImage();
@@ -94742,7 +96328,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
94742
96328
  };
94743
96329
  }
94744
96330
  });
94745
- const SuperEditor = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-f5c4f915"]]);
96331
+ const SuperEditor = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-bb7d8a50"]]);
94746
96332
  const _hoisted_1 = ["innerHTML"];
94747
96333
  const _sfc_main = {
94748
96334
  __name: "SuperInput",