superdoc 1.2.1 → 1.3.0-next.1

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,10 +1,10 @@
1
- import { B as BIT8, M as MAX_SAFE_INTEGER, c as create, a as BITS7, u as utf8TextDecoder, b as create$1, s as setIfUndefined, d as create$2, f as from, e as floor$1, g as equalityDeep, w as writeVarUint, h as writeVarString, t as toUint8Array, i as createEncoder, j as createInjectionKey, k as toString, l as throwError, m as useSsrAdapter, n as configProviderInjectionKey, o as cssrAnchorMetaName, p as globalStyle, q as cB, r as c, v as isMounted, x as commonVariables$2, y as cM, z as cNotM, A as cE, C as derived, D as changeColor, E as insideModal, F as insidePopover, G as resolveWrappedSlot, H as on, I as warnOnce, J as useConfig, K as useMergedState, L as useMemo, N as useTheme, O as useRtl, P as createKey, Q as useThemeClass, R as createId, S as call, T as render, U as messageProviderInjectionKey, V as messageApiInjectionKey, W as fromBase64, X as onChange, Y as varStorage, Z as toBase64, _ as createUint8ArrayFromArrayBuffer, $ as offChange, a0 as writeVarUint8Array, a1 as map, a2 as length, a3 as isNode, a4 as min, a5 as pow, a6 as comments_module_events, a7 as getFileObject, a8 as getTrackChanges, a9 as CommentsPluginKey, aa as TrackChangesBasePluginKey, ab as Editor, ac as getRichTextExtensions, ad as ellipsisVerticalSvg, ae as xmarkIconSvg, af as checkIconSvg, ag as caretDownIconSvg, ah as commentIconSvg, ai as _export_sfc, aj as NDropdown, ak as SuperInput, al as vClickOutside, am as PresentationEditor, an as SuperEditor, ao as AIWriter, ap as NConfigProvider, aq as SuperToolbar } from "./index-DUHBiOz0.es.js";
2
- import "./SuperConverter-DrIt9cvV.es.js";
1
+ import { B as BIT8, M as MAX_SAFE_INTEGER, c as create, a as BITS7, u as utf8TextDecoder, b as create$1, s as setIfUndefined, d as create$2, f as from, e as floor$1, g as equalityDeep, w as writeVarUint, h as writeVarString, t as toUint8Array, i as createEncoder, j as createInjectionKey, k as toString, l as throwError, m as useSsrAdapter, n as configProviderInjectionKey, o as cssrAnchorMetaName, p as globalStyle, q as cB, r as c, v as isMounted, x as commonVariables$2, y as cM, z as cNotM, A as cE, C as derived, D as changeColor, E as insideModal, F as insidePopover, G as resolveWrappedSlot, H as on, I as warnOnce, J as useConfig, K as useMergedState, L as useMemo, N as useTheme, O as useRtl, P as createKey, Q as useThemeClass, R as createId, S as call, T as render, U as messageProviderInjectionKey, V as messageApiInjectionKey, W as fromBase64, X as onChange, Y as varStorage, Z as toBase64, _ as createUint8ArrayFromArrayBuffer, $ as offChange, a0 as writeVarUint8Array, a1 as map, a2 as length, a3 as isNode, a4 as min, a5 as pow, a6 as comments_module_events, a7 as getFileObject, a8 as getTrackChanges, a9 as CommentsPluginKey, aa as TrackChangesBasePluginKey, ab as Editor, ac as getRichTextExtensions, ad as ellipsisVerticalSvg, ae as xmarkIconSvg, af as checkIconSvg, ag as caretDownIconSvg, ah as commentIconSvg, ai as _export_sfc, aj as NDropdown, ak as SuperInput, al as vClickOutside, am as PresentationEditor, an as SuperEditor, ao as AIWriter, ap as NConfigProvider, aq as SuperToolbar } from "./index-wwGlJ58Z.es.js";
2
+ import "./SuperConverter-BXP6NikG.es.js";
3
3
  import { B as BlankDOCX } from "./blank-docx-ABm6XYAA.es.js";
4
4
  import { E as EventEmitter } from "./eventemitter3-CwrdEv8r.es.js";
5
5
  import { HocuspocusProvider, HocuspocusProviderWebsocket } from "@hocuspocus/provider";
6
6
  import "./jszip-B1fkPkPJ.es.js";
7
- import "./helpers-CAUq8coh.es.js";
7
+ import "./helpers-C8e9wR5l.es.js";
8
8
  import { i as inject, a as provide, c as computed, o as onBeforeUnmount, p as process$1, b as onBeforeMount, d as defineComponent, h, t as toRef, T as Transition, e as TransitionGroup, w as watchEffect, r as ref, f as onMounted, g as Teleport, F as Fragment, j as reactive, k as effectScope, m as markRaw, l as toRaw, n as isRef, q as isReactive, s as getCurrentInstance, u as watch, v as unref, x as hasInjectionContext, y as nextTick, z as getCurrentScope, A as onScopeDispose, B as toRefs, C as global, D as shallowRef, E as createElementBlock, G as openBlock, H as toDisplayString, I as createVNode, J as withCtx, K as createBaseVNode, L as normalizeStyle, M as createCommentVNode, N as createBlock, O as withModifiers, P as normalizeClass, Q as resolveDirective, R as withDirectives, S as renderList, U as createApp, V as resolveDynamicComponent, W as defineAsyncComponent } from "./vue-BnBKJwCW.es.js";
9
9
  import "./jszip.min-DCl8qkFO.es.js";
10
10
  import { createZip } from "../super-editor/file-zipper.es.js";
@@ -7444,7 +7444,7 @@ const _sfc_main = {
7444
7444
  __name: "SuperDoc",
7445
7445
  emits: ["selection-update"],
7446
7446
  setup(__props, { emit: __emit }) {
7447
- const PdfViewer = defineAsyncComponent(() => import("./PdfViewer-CfkEojYs.es.js"));
7447
+ const PdfViewer = defineAsyncComponent(() => import("./PdfViewer-CkOzQzPk.es.js"));
7448
7448
  const superdocStore = useSuperdocStore();
7449
7449
  const commentsStore = useCommentsStore();
7450
7450
  const {
@@ -8350,7 +8350,7 @@ class SuperDoc extends EventEmitter {
8350
8350
  this.config.colors = shuffleArray(this.config.colors);
8351
8351
  this.userColorMap = /* @__PURE__ */ new Map();
8352
8352
  this.colorIndex = 0;
8353
- this.version = "1.2.1";
8353
+ this.version = "1.3.0-next.1";
8354
8354
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
8355
8355
  this.superdocId = config.superdocId || v4();
8356
8356
  this.colors = this.config.colors;
@@ -1,6 +1,6 @@
1
1
  import { B as Buffer$2 } from "./jszip-B1fkPkPJ.es.js";
2
- import { t as twipsToInches, i as inchesToTwips, p as ptToTwips, l as linesToTwips, a as twipsToLines, b as pixelsToTwips, c as twipsToPixels$2, d as convertSizeToCSS, e as inchesToPixels } from "./helpers-CAUq8coh.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 liftTarget, u as canJoin, v as joinPoint, x as replaceStep$1, R as ReplaceAroundStep$1, y as htmlHandler, z as ReplaceStep, B as getResolvedParagraphProperties, C as changeListLevel, E as isList$1, G as updateNumberingProperties, L as ListHelpers, H as inputRulesPlugin, I as TrackDeleteMarkName$1, J as TrackInsertMarkName$1, K as TrackFormatMarkName$1, O as AddMarkStep, Q as RemoveMarkStep, U as CommandService, S as SuperConverter, V as EditorState, W as unflattenListsInHtml, X as SelectionRange, Y as Transform, Z as resolveParagraphProperties, _ as _getReferencedTableStyles, $ as decodeRPrFromMarks, a0 as calculateResolvedParagraphProperties, a1 as resolveRunProperties, a2 as encodeCSSFromPPr, a3 as encodeCSSFromRPr, a4 as generateOrderedListIndex, a5 as docxNumberingHelpers, a6 as InputRule, a7 as insertNewRelationship, a8 as kebabCase$1, a9 as getUnderlineCssString } from "./SuperConverter-DrIt9cvV.es.js";
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 liftTarget, u as canJoin, v as joinPoint, x as replaceStep$1, R as ReplaceAroundStep$1, y as htmlHandler, z as ReplaceStep, B as getResolvedParagraphProperties, C as changeListLevel, E as isList$1, G as updateNumberingProperties, L as ListHelpers, H as inputRulesPlugin, I as TrackDeleteMarkName$1, J as TrackInsertMarkName$1, K as TrackFormatMarkName$1, O as AddMarkStep, Q as RemoveMarkStep, U as CommandService, S as SuperConverter, V as EditorState, W as unflattenListsInHtml, X as SelectionRange, Y as Transform, Z as resolveParagraphProperties, _ as _getReferencedTableStyles, $ as decodeRPrFromMarks, a0 as calculateResolvedParagraphProperties, a1 as resolveRunProperties, a2 as encodeCSSFromPPr, a3 as encodeCSSFromRPr, a4 as generateOrderedListIndex, a5 as docxNumberingHelpers, a6 as InputRule, a7 as insertNewRelationship, a8 as kebabCase$1, a9 as getUnderlineCssString } from "./SuperConverter-BXP6NikG.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 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";
@@ -14898,7 +14898,7 @@ const canUseDOM = () => {
14898
14898
  return false;
14899
14899
  }
14900
14900
  };
14901
- const summaryVersion = "1.2.1";
14901
+ const summaryVersion = "1.3.0-next.1";
14902
14902
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
14903
14903
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
14904
14904
  function mapAttributes(attrs) {
@@ -17531,7 +17531,7 @@ class Editor extends EventEmitter {
17531
17531
  * Process collaboration migrations
17532
17532
  */
17533
17533
  processCollaborationMigrations() {
17534
- console.debug("[checkVersionMigrations] Current editor version", "1.2.1");
17534
+ console.debug("[checkVersionMigrations] Current editor version", "1.3.0-next.1");
17535
17535
  if (!this.options.ydoc) return;
17536
17536
  const metaMap = this.options.ydoc.getMap("meta");
17537
17537
  let docVersion = metaMap.get("version");
@@ -19790,6 +19790,15 @@ function calculateTabWidth(params2) {
19790
19790
  tabStopPosUsed: nextStop.pos
19791
19791
  };
19792
19792
  }
19793
+ const OOXML_PCT_DIVISOR = 5e3;
19794
+ function resolveColumnWidths(columns, availableWidth) {
19795
+ const columnCount = columns.length;
19796
+ const width = availableWidth / columnCount;
19797
+ return columns.map(() => width);
19798
+ }
19799
+ function measureRowHeights(cells, _columnWidths) {
19800
+ return cells.map(() => 20);
19801
+ }
19793
19802
  const SPACE_CHARS$1 = /* @__PURE__ */ new Set([" ", " "]);
19794
19803
  function shouldApplyJustify(params2) {
19795
19804
  const { alignment: alignment2, hasExplicitPositioning, isLastLineOfParagraph, paragraphEndsWithLineBreak, skipJustifyOverride } = params2;
@@ -20063,16 +20072,9 @@ function computeWrapExclusion(image, lineY, lineHeight2) {
20063
20072
  return null;
20064
20073
  }
20065
20074
  }
20066
- function resolveColumnWidths(columns, availableWidth) {
20067
- const columnCount = columns.length;
20068
- const width = availableWidth / columnCount;
20069
- return columns.map(() => width);
20070
- }
20071
- function measureRowHeights(cells, _columnWidths) {
20072
- return cells.map(() => 20);
20073
- }
20074
20075
  const Engines = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
20075
20076
  __proto__: null,
20077
+ OOXML_PCT_DIVISOR,
20076
20078
  calculateTabWidth,
20077
20079
  computeListIndent,
20078
20080
  computeTabStops: computeTabStops$1,
@@ -23174,6 +23176,37 @@ function renderListMarker(params2) {
23174
23176
  lineContainer.appendChild(lineEl);
23175
23177
  return lineContainer;
23176
23178
  }
23179
+ function applyParagraphBordersAndShading(paraWrapper, block) {
23180
+ const borders = block.attrs?.borders;
23181
+ if (borders) {
23182
+ paraWrapper.style.boxSizing = "border-box";
23183
+ const sideStyles = {
23184
+ top: { width: "border-top-width", style: "border-top-style", color: "border-top-color" },
23185
+ bottom: { width: "border-bottom-width", style: "border-bottom-style", color: "border-bottom-color" },
23186
+ left: { width: "border-left-width", style: "border-left-style", color: "border-left-color" },
23187
+ right: { width: "border-right-width", style: "border-right-style", color: "border-right-color" }
23188
+ };
23189
+ ["top", "bottom", "left", "right"].forEach((side) => {
23190
+ const border = borders[side];
23191
+ if (!border) return;
23192
+ const styleValue = border.style ?? "solid";
23193
+ let widthValue = typeof border.width === "number" ? Math.max(0, border.width) : 1;
23194
+ if (styleValue === "none") {
23195
+ widthValue = 0;
23196
+ }
23197
+ const cssKeys = sideStyles[side];
23198
+ paraWrapper.style.setProperty(cssKeys.style, styleValue);
23199
+ paraWrapper.style.setProperty(cssKeys.width, `${widthValue}px`);
23200
+ if (border.color) {
23201
+ paraWrapper.style.setProperty(cssKeys.color, border.color);
23202
+ }
23203
+ });
23204
+ }
23205
+ const shadingFill = block.attrs?.shading?.fill;
23206
+ if (shadingFill) {
23207
+ paraWrapper.style.backgroundColor = shadingFill;
23208
+ }
23209
+ }
23177
23210
  const renderTableCell = (deps) => {
23178
23211
  const {
23179
23212
  doc: doc2,
@@ -23336,6 +23369,9 @@ const renderTableCell = (deps) => {
23336
23369
  paraWrapper.style.left = "0";
23337
23370
  paraWrapper.style.width = "100%";
23338
23371
  applySdtDataset(paraWrapper, block.attrs?.sdt);
23372
+ applyParagraphBordersAndShading(paraWrapper, block);
23373
+ applyParagraphBorderStyles(paraWrapper, block.attrs?.borders);
23374
+ applyParagraphShadingStyles(paraWrapper, block.attrs?.shading);
23339
23375
  let renderedHeight = 0;
23340
23376
  for (let lineIdx = localStartLine; lineIdx < localEndLine && lineIdx < lines.length; lineIdx++) {
23341
23377
  const line = lines[lineIdx];
@@ -23366,15 +23402,26 @@ const renderTableCell = (deps) => {
23366
23402
  } else {
23367
23403
  const indent = block.attrs?.indent;
23368
23404
  if (indent) {
23369
- if (typeof indent.left === "number" && indent.left > 0) {
23370
- lineEl.style.paddingLeft = `${indent.left}px`;
23405
+ const leftIndent = typeof indent.left === "number" ? indent.left : 0;
23406
+ const hanging = typeof indent.hanging === "number" ? indent.hanging : 0;
23407
+ const firstLine = typeof indent.firstLine === "number" ? indent.firstLine : 0;
23408
+ const isFirstLine = lineIdx === 0 && localStartLine === 0;
23409
+ const firstLineOffset = firstLine - hanging;
23410
+ if (isFirstLine) {
23411
+ if (leftIndent > 0) {
23412
+ lineEl.style.paddingLeft = `${leftIndent}px`;
23413
+ }
23414
+ if (firstLineOffset !== 0) {
23415
+ lineEl.style.textIndent = `${firstLineOffset}px`;
23416
+ }
23417
+ } else {
23418
+ if (leftIndent > 0) {
23419
+ lineEl.style.paddingLeft = `${leftIndent}px`;
23420
+ }
23371
23421
  }
23372
23422
  if (typeof indent.right === "number" && indent.right > 0) {
23373
23423
  lineEl.style.paddingRight = `${indent.right}px`;
23374
23424
  }
23375
- if (lineIdx === 0 && typeof indent.firstLine === "number" && indent.firstLine !== 0) {
23376
- lineEl.style.textIndent = `${indent.firstLine}px`;
23377
- }
23378
23425
  }
23379
23426
  }
23380
23427
  paraWrapper.appendChild(lineEl);
@@ -31482,6 +31529,27 @@ function getCellPadding(cellIdx, blockRow) {
31482
31529
  function getCellTotalLines(cell) {
31483
31530
  return getCellLines(cell).length;
31484
31531
  }
31532
+ const ROW_HEIGHT_EPSILON = 0.1;
31533
+ function getRowContentHeight(blockRow, rowMeasure) {
31534
+ let contentHeight = 0;
31535
+ for (let cellIdx = 0; cellIdx < rowMeasure.cells.length; cellIdx++) {
31536
+ const cell = rowMeasure.cells[cellIdx];
31537
+ const cellPadding = getCellPadding(cellIdx, blockRow);
31538
+ const paddingTotal = cellPadding.top + cellPadding.bottom;
31539
+ const lines = getCellLines(cell);
31540
+ const linesHeight = lines.reduce((sum, line) => sum + (line.lineHeight || 0), 0);
31541
+ contentHeight = Math.max(contentHeight, linesHeight + paddingTotal);
31542
+ }
31543
+ return contentHeight;
31544
+ }
31545
+ function hasExplicitRowHeightSlack(blockRow, rowMeasure) {
31546
+ const rowHeightSpec = blockRow?.attrs?.rowHeight;
31547
+ if (!rowHeightSpec || rowHeightSpec.value == null || !Number.isFinite(rowHeightSpec.value)) {
31548
+ return false;
31549
+ }
31550
+ const contentHeight = getRowContentHeight(blockRow, rowMeasure);
31551
+ return rowMeasure.height > contentHeight + ROW_HEIGHT_EPSILON;
31552
+ }
31485
31553
  function mergePmRange(target, range) {
31486
31554
  if (typeof range.pmStart === "number") {
31487
31555
  target.pmStart = target.pmStart == null ? range.pmStart : Math.min(target.pmStart, range.pmStart);
@@ -31651,8 +31719,12 @@ function findSplitPoint(block, measure, startRow, availableHeight, fullPageHeigh
31651
31719
  let lastFitRow = startRow;
31652
31720
  for (let i = startRow; i < block.rows.length; i++) {
31653
31721
  const row = block.rows[i];
31654
- const rowHeight = measure.rows[i]?.height || 0;
31655
- const cantSplit = row.attrs?.tableRowProperties?.cantSplit === true;
31722
+ const rowMeasure = measure.rows[i];
31723
+ const rowHeight = rowMeasure?.height || 0;
31724
+ let cantSplit = row.attrs?.tableRowProperties?.cantSplit === true;
31725
+ if (rowMeasure && hasExplicitRowHeightSlack(row, rowMeasure) && (!fullPageHeight || rowHeight <= fullPageHeight)) {
31726
+ cantSplit = true;
31727
+ }
31656
31728
  if (accumulatedHeight + rowHeight <= availableHeight) {
31657
31729
  accumulatedHeight += rowHeight;
31658
31730
  lastFitRow = i + 1;
@@ -31743,7 +31815,10 @@ function layoutTableBlock({
31743
31815
  if (hasMeasuredRows && hasPriorFragments) {
31744
31816
  const firstRowCantSplit = block.rows[0]?.attrs?.tableRowProperties?.cantSplit === true;
31745
31817
  const firstRowHeight = measure.rows[0]?.height ?? measure.totalHeight ?? 0;
31746
- if (firstRowCantSplit) {
31818
+ const firstRowSlack = hasExplicitRowHeightSlack(block.rows[0], measure.rows[0]);
31819
+ const firstRowFitsPage = firstRowHeight <= state.contentBottom;
31820
+ const treatFirstRowAsCantSplit = firstRowCantSplit || firstRowSlack && firstRowFitsPage;
31821
+ if (treatFirstRowAsCantSplit) {
31747
31822
  if (firstRowHeight > availableHeight) {
31748
31823
  state = advanceColumn(state);
31749
31824
  }
@@ -32309,6 +32384,36 @@ const DEFAULT_PARAGRAPH_LINE_HEIGHT_PX = 20;
32309
32384
  function hasHeight(fragment) {
32310
32385
  return fragment.kind === "image" || fragment.kind === "drawing" || fragment.kind === "table";
32311
32386
  }
32387
+ function getParagraphSpacingBefore(block) {
32388
+ const spacing = block.attrs?.spacing;
32389
+ const value = spacing?.before ?? spacing?.lineSpaceBefore;
32390
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
32391
+ }
32392
+ function getParagraphSpacingAfter(block) {
32393
+ const spacing = block.attrs?.spacing;
32394
+ const value = spacing?.after ?? spacing?.lineSpaceAfter;
32395
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
32396
+ }
32397
+ function getMeasureHeight(block, measure) {
32398
+ switch (measure.kind) {
32399
+ case "paragraph":
32400
+ return measure.totalHeight;
32401
+ case "table":
32402
+ return measure.totalHeight;
32403
+ case "list":
32404
+ return measure.totalHeight;
32405
+ case "image":
32406
+ case "drawing":
32407
+ return measure.height;
32408
+ case "sectionBreak":
32409
+ case "pageBreak":
32410
+ case "columnBreak":
32411
+ return 0;
32412
+ default: {
32413
+ return block.kind === "paragraph" ? DEFAULT_PARAGRAPH_LINE_HEIGHT_PX : 0;
32414
+ }
32415
+ }
32416
+ }
32312
32417
  const DEFAULT_PAGE_SIZE$2 = { w: 612, h: 792 };
32313
32418
  const DEFAULT_MARGINS$2 = { top: 72, right: 72, bottom: 72, left: 72 };
32314
32419
  const COLUMN_EPSILON = 1e-4;
@@ -33023,6 +33128,36 @@ function layoutDocument(blocks, measures, options = {}) {
33023
33128
  placedAnchoredTableIds.add(tableBlock.id);
33024
33129
  }
33025
33130
  }
33131
+ if (paraBlock.attrs?.keepNext === true) {
33132
+ const nextBlock = blocks[index2 + 1];
33133
+ const nextMeasure = measures[index2 + 1];
33134
+ if (nextBlock && nextMeasure && nextBlock.kind !== "sectionBreak" && nextBlock.kind !== "pageBreak" && nextBlock.kind !== "columnBreak") {
33135
+ const shouldSkipAnchoredTable = nextBlock.kind === "table" && nextBlock.anchor?.isAnchored === true;
33136
+ if (!shouldSkipAnchoredTable) {
33137
+ let state = paginator.ensurePage();
33138
+ const availableHeight = state.contentBottom - state.cursorY;
33139
+ const spacingAfter = getParagraphSpacingAfter(paraBlock);
33140
+ const currentHeight = getMeasureHeight(paraBlock, measure);
33141
+ const nextHeight = getMeasureHeight(nextBlock, nextMeasure);
33142
+ const nextIsParagraph = nextBlock.kind === "paragraph" && nextMeasure.kind === "paragraph";
33143
+ const nextSpacingBefore = nextIsParagraph ? getParagraphSpacingBefore(nextBlock) : 0;
33144
+ const nextFirstLineHeight = (() => {
33145
+ if (!nextIsParagraph) {
33146
+ return nextHeight;
33147
+ }
33148
+ const firstLineHeight = nextMeasure.lines[0]?.lineHeight;
33149
+ if (typeof firstLineHeight === "number" && Number.isFinite(firstLineHeight) && firstLineHeight > 0) {
33150
+ return firstLineHeight;
33151
+ }
33152
+ return nextHeight;
33153
+ })();
33154
+ const combinedHeight = nextIsParagraph ? currentHeight + Math.max(spacingAfter, nextSpacingBefore) + nextFirstLineHeight : currentHeight + spacingAfter + nextHeight;
33155
+ if (combinedHeight > availableHeight && state.page.fragments.length > 0) {
33156
+ state = paginator.advanceColumn(state);
33157
+ }
33158
+ }
33159
+ }
33160
+ }
33026
33161
  layoutParagraphBlock(
33027
33162
  {
33028
33163
  block,
@@ -40131,6 +40266,23 @@ const applyThemeShade = (baseHex, ratio) => {
40131
40266
  };
40132
40267
  return rgbToHex(shaded);
40133
40268
  };
40269
+ const getLuminance = (hexColor) => {
40270
+ const rgb = hexToRgb(hexColor);
40271
+ if (!rgb) return 1;
40272
+ const toLinear = (channel) => {
40273
+ const c2 = channel / 255;
40274
+ return c2 <= 0.03928 ? c2 / 12.92 : Math.pow((c2 + 0.055) / 1.055, 2.4);
40275
+ };
40276
+ const R = toLinear(rgb.r);
40277
+ const G = toLinear(rgb.g);
40278
+ const B = toLinear(rgb.b);
40279
+ return 0.2126 * R + 0.7152 * G + 0.0722 * B;
40280
+ };
40281
+ const WCAG_AA_LUMINANCE_THRESHOLD = 0.18;
40282
+ const resolveAutoColor = (backgroundColor) => {
40283
+ const luminance = getLuminance(backgroundColor);
40284
+ return luminance < WCAG_AA_LUMINANCE_THRESHOLD ? "#FFFFFF" : "#000000";
40285
+ };
40134
40286
  const resolveThemeColor = (attrs, themeColors) => {
40135
40287
  if (!attrs || !themeColors) return void 0;
40136
40288
  const rawKey = attrs.themeColor;
@@ -40456,8 +40608,9 @@ const applyTextStyleMark = (run, attrs, themeColors) => {
40456
40608
  const DEFAULT_HYPERLINK_CONFIG = {
40457
40609
  enableRichHyperlinks: false
40458
40610
  };
40459
- const applyMarksToRun = (run, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG, themeColors) => {
40611
+ const applyMarksToRun = (run, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG, themeColors, backgroundColor) => {
40460
40612
  const isTabRun2 = run.kind === "tab";
40613
+ let markSetColor = false;
40461
40614
  marks.forEach((mark) => {
40462
40615
  const forwardedDataAttrs = extractDataAttributes(mark.attrs);
40463
40616
  try {
@@ -40493,7 +40646,11 @@ const applyMarksToRun = (run, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG,
40493
40646
  }
40494
40647
  case "textStyle":
40495
40648
  if (!isTabRun2) {
40649
+ const colorBefore = run.color;
40496
40650
  applyTextStyleMark(run, mark.attrs ?? {}, themeColors);
40651
+ if (run.color !== colorBefore && run.color !== void 0) {
40652
+ markSetColor = true;
40653
+ }
40497
40654
  }
40498
40655
  break;
40499
40656
  case "commentMark":
@@ -40574,6 +40731,15 @@ const applyMarksToRun = (run, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG,
40574
40731
  run.dataAttrs = { ...run.dataAttrs ?? {}, ...forwardedDataAttrs };
40575
40732
  }
40576
40733
  });
40734
+ if (!isTabRun2 && !markSetColor && backgroundColor) {
40735
+ const normalizedExisting = normalizeColor$1(run.color);
40736
+ const normalizedUpper = normalizedExisting?.toUpperCase();
40737
+ const isDefaultBlack = normalizedUpper === "#000000" || normalizedUpper === "#000";
40738
+ const isAutoColorValue = typeof run.color === "string" && ["auto", "none"].includes(run.color.trim().replace(/^#/, "").toLowerCase());
40739
+ if (!normalizedExisting || isAutoColorValue || isDefaultBlack) {
40740
+ run.color = resolveAutoColor(backgroundColor);
40741
+ }
40742
+ }
40577
40743
  };
40578
40744
  function textNodeToRun(textNode, positions, defaultFont, defaultSize, inheritedMarks = [], sdtMetadata, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors) {
40579
40745
  const run = {
@@ -44396,7 +44562,13 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
44396
44562
  const inlineStyleId = getInlineStyleId(inheritedMarks);
44397
44563
  applyRunStyles2(run, inlineStyleId, activeRunStyleId);
44398
44564
  applyBaseRunDefaults(run, baseRunDefaults, defaultFont, defaultSize);
44399
- applyMarksToRun(run, [...node.marks ?? [], ...inheritedMarks ?? []], hyperlinkConfig, themeColors);
44565
+ applyMarksToRun(
44566
+ run,
44567
+ [...node.marks ?? [], ...inheritedMarks ?? []],
44568
+ hyperlinkConfig,
44569
+ themeColors,
44570
+ converterContext?.backgroundColor
44571
+ );
44400
44572
  currentRuns.push(run);
44401
44573
  return;
44402
44574
  }
@@ -45115,9 +45287,21 @@ const parseTableCell = (args) => {
45115
45287
  return null;
45116
45288
  }
45117
45289
  const blocks = [];
45118
- const cellConverterContext = tableStyleParagraphProps ? {
45290
+ const cellBackground = cellNode.attrs?.background;
45291
+ let cellBackgroundColor;
45292
+ if (cellBackground && typeof cellBackground.color === "string") {
45293
+ const rawColor = cellBackground.color.trim();
45294
+ if (rawColor) {
45295
+ const normalized = rawColor.startsWith("#") ? rawColor : `#${rawColor}`;
45296
+ if (/^#[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$/.test(normalized)) {
45297
+ cellBackgroundColor = normalized;
45298
+ }
45299
+ }
45300
+ }
45301
+ const cellConverterContext = tableStyleParagraphProps || cellBackgroundColor ? {
45119
45302
  ...context.converterContext,
45120
- tableStyleParagraphProps
45303
+ ...tableStyleParagraphProps && { tableStyleParagraphProps },
45304
+ ...cellBackgroundColor && { backgroundColor: cellBackgroundColor }
45121
45305
  } : context.converterContext;
45122
45306
  const paragraphToFlowBlocks2 = context.converters?.paragraphToFlowBlocks ?? context.paragraphToFlowBlocks;
45123
45307
  const listCounterContext = context.listCounterContext;
@@ -48497,8 +48681,33 @@ async function measureParagraphBlock(block, maxWidth) {
48497
48681
  ...dropCapMeasure ? { dropCap: dropCapMeasure } : {}
48498
48682
  };
48499
48683
  }
48684
+ function validateTableWidthValue(attr) {
48685
+ const value = attr.width ?? attr.value;
48686
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
48687
+ return value;
48688
+ }
48689
+ return void 0;
48690
+ }
48691
+ function resolveTableWidth(attrs, maxWidth) {
48692
+ const tableWidthAttr = attrs?.tableWidth;
48693
+ if (!tableWidthAttr || typeof tableWidthAttr !== "object") {
48694
+ return void 0;
48695
+ }
48696
+ const typedAttr = tableWidthAttr;
48697
+ const validValue = validateTableWidthValue(typedAttr);
48698
+ if (validValue === void 0) {
48699
+ return void 0;
48700
+ }
48701
+ if (typedAttr.type === "pct") {
48702
+ return Math.round(maxWidth * (validValue / OOXML_PCT_DIVISOR));
48703
+ } else if (typedAttr.type === "px" || typedAttr.type === "pixel") {
48704
+ return validValue;
48705
+ }
48706
+ return void 0;
48707
+ }
48500
48708
  async function measureTableBlock(block, constraints) {
48501
48709
  const maxWidth = typeof constraints === "number" ? constraints : constraints.maxWidth;
48710
+ const resolvedTableWidth = resolveTableWidth(block.attrs, maxWidth);
48502
48711
  let columnWidths;
48503
48712
  const scaleColumnWidths = (widths, targetWidth) => {
48504
48713
  const totalWidth2 = widths.reduce((a, b) => a + b, 0);
@@ -48529,19 +48738,26 @@ async function measureTableBlock(block, constraints) {
48529
48738
  return scaled;
48530
48739
  };
48531
48740
  const maxCellCount = Math.max(1, Math.max(...block.rows.map((r2) => r2.cells.length)));
48741
+ const effectiveTargetWidth = resolvedTableWidth != null ? Math.min(resolvedTableWidth, maxWidth) : maxWidth;
48532
48742
  if (block.columnWidths && block.columnWidths.length > 0) {
48533
48743
  columnWidths = [...block.columnWidths];
48534
- const hasExplicitWidth = block.attrs?.tableWidth != null;
48744
+ const hasExplicitWidth = resolvedTableWidth != null;
48535
48745
  const hasFixedLayout = block.attrs?.tableLayout === "fixed";
48536
48746
  if (hasExplicitWidth || hasFixedLayout) {
48537
48747
  const totalWidth2 = columnWidths.reduce((a, b) => a + b, 0);
48538
- if (totalWidth2 > maxWidth) {
48539
- columnWidths = scaleColumnWidths(columnWidths, maxWidth);
48748
+ if (totalWidth2 !== effectiveTargetWidth && effectiveTargetWidth > 0) {
48749
+ const scale = effectiveTargetWidth / totalWidth2;
48750
+ columnWidths = columnWidths.map((w) => Math.max(1, Math.round(w * scale)));
48751
+ const scaledSum = columnWidths.reduce((a, b) => a + b, 0);
48752
+ if (scaledSum !== effectiveTargetWidth && columnWidths.length > 0) {
48753
+ const diff = effectiveTargetWidth - scaledSum;
48754
+ columnWidths[columnWidths.length - 1] = Math.max(1, columnWidths[columnWidths.length - 1] + diff);
48755
+ }
48540
48756
  }
48541
48757
  } else {
48542
48758
  if (columnWidths.length < maxCellCount) {
48543
48759
  const usedWidth = columnWidths.reduce((a, b) => a + b, 0);
48544
- const remainingWidth = Math.max(0, maxWidth - usedWidth);
48760
+ const remainingWidth = Math.max(0, effectiveTargetWidth - usedWidth);
48545
48761
  const missingColumns = maxCellCount - columnWidths.length;
48546
48762
  const paddingWidth = Math.max(1, Math.floor(remainingWidth / missingColumns));
48547
48763
  columnWidths.push(...Array.from({ length: missingColumns }, () => paddingWidth));
@@ -48549,12 +48765,12 @@ async function measureTableBlock(block, constraints) {
48549
48765
  columnWidths = columnWidths.slice(0, maxCellCount);
48550
48766
  }
48551
48767
  const totalWidth2 = columnWidths.reduce((a, b) => a + b, 0);
48552
- if (totalWidth2 > maxWidth) {
48553
- columnWidths = scaleColumnWidths(columnWidths, maxWidth);
48768
+ if (totalWidth2 > effectiveTargetWidth) {
48769
+ columnWidths = scaleColumnWidths(columnWidths, effectiveTargetWidth);
48554
48770
  }
48555
48771
  }
48556
48772
  } else {
48557
- const columnWidth = Math.max(1, Math.floor(maxWidth / maxCellCount));
48773
+ const columnWidth = Math.max(1, Math.floor(effectiveTargetWidth / maxCellCount));
48558
48774
  columnWidths = Array.from({ length: maxCellCount }, () => columnWidth);
48559
48775
  }
48560
48776
  const gridColumnCount = columnWidths.length;
@@ -49086,6 +49302,7 @@ const CommentMarkName = "commentMark";
49086
49302
  const TrackInsertMarkName = "trackInsert";
49087
49303
  const TrackDeleteMarkName = "trackDelete";
49088
49304
  const TrackFormatMarkName = "trackFormat";
49305
+ const SUBSCRIPT_SUPERSCRIPT_SCALE = 0.65;
49089
49306
  const DEFAULT_PAGE_SIZE = { w: 612, h: 792 };
49090
49307
  const DEFAULT_MARGINS = { top: 72, right: 72, bottom: 72, left: 72 };
49091
49308
  const DEFAULT_VIRTUALIZED_PAGE_GAP = 72;
@@ -52330,6 +52547,7 @@ class PresentationEditor extends EventEmitter {
52330
52547
  );
52331
52548
  this.#domIndexObserverManager?.pause();
52332
52549
  painter.paint(layout, this.#painterHost);
52550
+ this.#applyVertAlignToLayout();
52333
52551
  this.#rebuildDomPositionIndex();
52334
52552
  this.#domIndexObserverManager?.resume();
52335
52553
  this.#layoutEpoch = layoutEpoch;
@@ -54092,6 +54310,90 @@ class PresentationEditor extends EventEmitter {
54092
54310
  this.#errorBanner = null;
54093
54311
  this.#errorBannerMessage = null;
54094
54312
  }
54313
+ /**
54314
+ * Applies vertical alignment and font scaling to layout DOM elements for subscript/superscript rendering.
54315
+ *
54316
+ * This method post-processes the painted DOM layout to apply vertical alignment styles
54317
+ * (super, sub, baseline, or custom position) based on run properties and text style marks.
54318
+ * It handles both DOCX-style vertAlign ('superscript', 'subscript', 'baseline') and
54319
+ * custom position offsets (in half-points).
54320
+ *
54321
+ * Processing logic:
54322
+ * 1. Queries all text spans with ProseMirror position markers
54323
+ * 2. For each span, resolves the ProseMirror position to find the containing run node
54324
+ * 3. Extracts vertAlign and position from run properties and/or text style marks
54325
+ * 4. Applies CSS vertical-align and font-size styles based on the extracted properties
54326
+ * 5. Position takes precedence over vertAlign when both are present
54327
+ *
54328
+ * @throws Does not throw - DOM manipulation errors are silently caught to prevent layout corruption
54329
+ * @private
54330
+ */
54331
+ #applyVertAlignToLayout() {
54332
+ const doc2 = this.#editor?.state?.doc;
54333
+ if (!doc2 || !this.#painterHost) return;
54334
+ try {
54335
+ const spans = this.#painterHost.querySelectorAll(".superdoc-line span[data-pm-start]");
54336
+ spans.forEach((span) => {
54337
+ try {
54338
+ if (span.closest(".superdoc-page-header, .superdoc-page-footer")) return;
54339
+ const pmStart = Number(span.dataset.pmStart ?? "NaN");
54340
+ if (!Number.isFinite(pmStart)) return;
54341
+ const pos = Math.max(0, Math.min(pmStart, doc2.content.size));
54342
+ const $pos = doc2.resolve(pos);
54343
+ let runNode = null;
54344
+ for (let depth = $pos.depth; depth >= 0; depth--) {
54345
+ const node = $pos.node(depth);
54346
+ if (node.type.name === "run") {
54347
+ runNode = node;
54348
+ break;
54349
+ }
54350
+ }
54351
+ let vertAlign = runNode?.attrs?.runProperties?.vertAlign ?? null;
54352
+ let position = runNode?.attrs?.runProperties?.position ?? null;
54353
+ let fontSizeHalfPts = runNode?.attrs?.runProperties?.fontSize ?? null;
54354
+ if (!vertAlign && position == null && runNode) {
54355
+ runNode.forEach((child) => {
54356
+ if (!child.isText || !child.marks?.length) return;
54357
+ const rpr = decodeRPrFromMarks(child.marks);
54358
+ if (rpr.vertAlign && !vertAlign) vertAlign = rpr.vertAlign;
54359
+ if (rpr.position != null && position == null) position = rpr.position;
54360
+ if (rpr.fontSize != null && fontSizeHalfPts == null) fontSizeHalfPts = rpr.fontSize;
54361
+ });
54362
+ }
54363
+ if (vertAlign == null && position == null) return;
54364
+ const styleEntries = [];
54365
+ if (position != null && Number.isFinite(position)) {
54366
+ const pts = halfPointToPoints(position);
54367
+ if (Number.isFinite(pts)) {
54368
+ styleEntries.push(`vertical-align: ${pts}pt`);
54369
+ }
54370
+ } else if (vertAlign === "superscript" || vertAlign === "subscript") {
54371
+ styleEntries.push(`vertical-align: ${vertAlign === "superscript" ? "super" : "sub"}`);
54372
+ if (fontSizeHalfPts != null && Number.isFinite(fontSizeHalfPts)) {
54373
+ const scaledPts = halfPointToPoints(fontSizeHalfPts * SUBSCRIPT_SUPERSCRIPT_SCALE);
54374
+ if (Number.isFinite(scaledPts)) {
54375
+ styleEntries.push(`font-size: ${scaledPts}pt`);
54376
+ } else {
54377
+ styleEntries.push(`font-size: ${SUBSCRIPT_SUPERSCRIPT_SCALE * 100}%`);
54378
+ }
54379
+ } else {
54380
+ styleEntries.push(`font-size: ${SUBSCRIPT_SUPERSCRIPT_SCALE * 100}%`);
54381
+ }
54382
+ } else if (vertAlign === "baseline") {
54383
+ styleEntries.push("vertical-align: baseline");
54384
+ }
54385
+ if (!styleEntries.length) return;
54386
+ const existing = span.getAttribute("style");
54387
+ const merged = existing ? `${existing}; ${styleEntries.join("; ")}` : styleEntries.join("; ");
54388
+ span.setAttribute("style", merged);
54389
+ } catch (error) {
54390
+ console.error("Failed to apply vertical alignment to span:", error);
54391
+ }
54392
+ });
54393
+ } catch (error) {
54394
+ console.error("Failed to apply vertical alignment to layout:", error);
54395
+ }
54396
+ }
54095
54397
  }
54096
54398
  const Color = Extension.create({
54097
54399
  name: "color",
@@ -65633,7 +65935,63 @@ const TextStyle = Mark.create({
65633
65935
  * @category Attribute
65634
65936
  * @param {string} [styleId] - Style identifier for referencing predefined styles
65635
65937
  */
65636
- styleId: {}
65938
+ styleId: {},
65939
+ /**
65940
+ * Vertical alignment for subscript/superscript text (DOCX w:vertAlign).
65941
+ * Standard values: 'superscript', 'subscript', 'baseline'.
65942
+ * When both vertAlign and position are present, position takes precedence.
65943
+ * Renders as CSS vertical-align with 65% font-size scaling for super/subscript.
65944
+ * @category Attribute
65945
+ * @param {string} [vertAlign] - Vertical alignment mode ('superscript' | 'subscript' | 'baseline')
65946
+ */
65947
+ vertAlign: {
65948
+ default: null,
65949
+ renderDOM: (attrs) => {
65950
+ if (!attrs.vertAlign || attrs.position) return {};
65951
+ if (attrs.vertAlign === "superscript") {
65952
+ return { style: "vertical-align: super; font-size: 65%;" };
65953
+ }
65954
+ if (attrs.vertAlign === "subscript") {
65955
+ return { style: "vertical-align: sub; font-size: 65%;" };
65956
+ }
65957
+ if (attrs.vertAlign === "baseline") {
65958
+ return { style: "vertical-align: baseline;" };
65959
+ }
65960
+ return {};
65961
+ },
65962
+ parseDOM: (el) => {
65963
+ const va = el.style?.verticalAlign;
65964
+ if (va === "super") return "superscript";
65965
+ if (va === "sub") return "subscript";
65966
+ if (va === "baseline") return "baseline";
65967
+ return null;
65968
+ }
65969
+ },
65970
+ /**
65971
+ * Custom vertical position offset in points (DOCX w:position).
65972
+ * Numeric value specifying vertical offset (positive raises, negative lowers).
65973
+ * Format: '{number}pt' (e.g., '2pt', '-1.5pt').
65974
+ * Takes precedence over vertAlign when both are present.
65975
+ * Renders as CSS vertical-align with the exact offset value.
65976
+ * @category Attribute
65977
+ * @param {string} [position] - Vertical position offset (e.g., '2pt', '-1pt')
65978
+ */
65979
+ position: {
65980
+ default: null,
65981
+ renderDOM: (attrs) => {
65982
+ if (!attrs.position) return {};
65983
+ return { style: `vertical-align: ${attrs.position};` };
65984
+ },
65985
+ parseDOM: (el) => {
65986
+ const va = el.style?.verticalAlign;
65987
+ if (!va) return null;
65988
+ const numeric = parseFloat(va);
65989
+ if (!Number.isNaN(numeric)) {
65990
+ return `${numeric}pt`;
65991
+ }
65992
+ return null;
65993
+ }
65994
+ }
65637
65995
  };
65638
65996
  },
65639
65997
  addCommands() {
@@ -2,6 +2,6 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  require("../chunks/jszip-C8_CqJxM.cjs");
4
4
  require("../chunks/helpers-nOdwpmwb.cjs");
5
- const superEditor_converter = require("../chunks/SuperConverter-D7wt-eeZ.cjs");
5
+ const superEditor_converter = require("../chunks/SuperConverter-Dy0-KTCc.cjs");
6
6
  require("../chunks/uuid-R7L08bOx.cjs");
7
7
  exports.SuperConverter = superEditor_converter.SuperConverter;