superdoc 1.2.2-next.1 → 1.3.0-next.2

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
- 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-C4sb9GH7.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-ClzyObj7.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.2-next.1";
14901
+ const summaryVersion = "1.3.0-next.2";
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.2-next.1");
17534
+ console.debug("[checkVersionMigrations] Current editor version", "1.3.0-next.2");
17535
17535
  if (!this.options.ydoc) return;
17536
17536
  const metaMap = this.options.ydoc.getMap("meta");
17537
17537
  let docVersion = metaMap.get("version");
@@ -19951,18 +19951,18 @@ function formatNumber(num, format) {
19951
19951
  case "decimal":
19952
19952
  return num.toString();
19953
19953
  case "lowerLetter":
19954
- return toLetter$1(num, false);
19954
+ return toLetter(num, false);
19955
19955
  case "upperLetter":
19956
- return toLetter$1(num, true);
19956
+ return toLetter(num, true);
19957
19957
  case "lowerRoman":
19958
- return toRoman$2(num).toLowerCase();
19958
+ return toRoman$1(num).toLowerCase();
19959
19959
  case "upperRoman":
19960
- return toRoman$2(num);
19960
+ return toRoman$1(num);
19961
19961
  default:
19962
19962
  return num.toString();
19963
19963
  }
19964
19964
  }
19965
- function toLetter$1(num, uppercase) {
19965
+ function toLetter(num, uppercase) {
19966
19966
  let result = "";
19967
19967
  let n = num;
19968
19968
  while (n > 0) {
@@ -19973,7 +19973,7 @@ function toLetter$1(num, uppercase) {
19973
19973
  }
19974
19974
  return result || (uppercase ? "A" : "a");
19975
19975
  }
19976
- function toRoman$2(num) {
19976
+ function toRoman$1(num) {
19977
19977
  const lookup = [
19978
19978
  [1e3, "M"],
19979
19979
  [900, "CM"],
@@ -25375,7 +25375,14 @@ class DomPainter {
25375
25375
  fragmentEl.dataset.continuesOnNext = "true";
25376
25376
  }
25377
25377
  const lines = fragment.lines ?? measure.lines.slice(fragment.fromLine, fragment.toLine);
25378
- applyParagraphBlockStyles(fragmentEl, block.attrs);
25378
+ applyParagraphBlockStyles(fragmentEl, block.attrs, { includeBorders: false, includeShading: false });
25379
+ const { shadingLayer, borderLayer } = createParagraphDecorationLayers(this.doc, fragment.width, block.attrs);
25380
+ if (shadingLayer) {
25381
+ fragmentEl.appendChild(shadingLayer);
25382
+ }
25383
+ if (borderLayer) {
25384
+ fragmentEl.appendChild(borderLayer);
25385
+ }
25379
25386
  if (block.attrs?.styleId) {
25380
25387
  fragmentEl.dataset.styleId = block.attrs.styleId;
25381
25388
  fragmentEl.setAttribute("styleid", block.attrs.styleId);
@@ -25759,10 +25766,18 @@ class DomPainter {
25759
25766
  contentEl.classList.add("superdoc-list-content");
25760
25767
  this.applySdtDataset(contentEl, paragraphMetadata);
25761
25768
  contentEl.style.display = "inline-block";
25769
+ contentEl.style.position = "relative";
25762
25770
  contentEl.style.width = `${fragment.width}px`;
25763
25771
  const lines = itemMeasure.paragraph.lines.slice(fragment.fromLine, fragment.toLine);
25764
25772
  const contentAttrs = wordLayout ? item.paragraph.attrs : stripListIndent(item.paragraph.attrs);
25765
- applyParagraphBlockStyles(contentEl, contentAttrs);
25773
+ applyParagraphBlockStyles(contentEl, contentAttrs, { includeBorders: false, includeShading: false });
25774
+ const { shadingLayer, borderLayer } = createParagraphDecorationLayers(this.doc, fragment.width, contentAttrs);
25775
+ if (shadingLayer) {
25776
+ contentEl.appendChild(shadingLayer);
25777
+ }
25778
+ if (borderLayer) {
25779
+ contentEl.appendChild(borderLayer);
25780
+ }
25766
25781
  contentEl.style.textAlign = "left";
25767
25782
  const paraForList = {
25768
25783
  ...item.paragraph,
@@ -27989,7 +28004,7 @@ const applyRunDataAttributes = (element, dataAttrs) => {
27989
28004
  }
27990
28005
  });
27991
28006
  };
27992
- const applyParagraphBlockStyles = (element, attrs) => {
28007
+ const applyParagraphBlockStyles = (element, attrs, options = {}) => {
27993
28008
  if (!attrs) return;
27994
28009
  if (attrs.styleId) {
27995
28010
  element.setAttribute("styleid", attrs.styleId);
@@ -28016,8 +28031,55 @@ const applyParagraphBlockStyles = (element, attrs) => {
28016
28031
  }
28017
28032
  }
28018
28033
  }
28019
- applyParagraphBorderStyles(element, attrs.borders);
28020
- applyParagraphShadingStyles(element, attrs.shading);
28034
+ if (options.includeBorders ?? true) {
28035
+ applyParagraphBorderStyles(element, attrs.borders);
28036
+ }
28037
+ if (options.includeShading ?? true) {
28038
+ applyParagraphShadingStyles(element, attrs.shading);
28039
+ }
28040
+ };
28041
+ const getParagraphBorderBox = (fragmentWidth, indent) => {
28042
+ const indentLeft = Number.isFinite(indent?.left) ? indent.left : 0;
28043
+ const indentRight = Number.isFinite(indent?.right) ? indent.right : 0;
28044
+ const firstLine = Number.isFinite(indent?.firstLine) ? indent.firstLine : 0;
28045
+ const hanging = Number.isFinite(indent?.hanging) ? indent.hanging : 0;
28046
+ const firstLineOffset = firstLine - hanging;
28047
+ const minLeftInset = Math.min(indentLeft, indentLeft + firstLineOffset);
28048
+ const leftInset = Math.max(0, minLeftInset);
28049
+ const rightInset = Math.max(0, indentRight);
28050
+ return {
28051
+ leftInset,
28052
+ width: Math.max(0, fragmentWidth - leftInset - rightInset)
28053
+ };
28054
+ };
28055
+ const createParagraphDecorationLayers = (doc2, fragmentWidth, attrs) => {
28056
+ if (!attrs?.borders && !attrs?.shading) return {};
28057
+ const borderBox = getParagraphBorderBox(fragmentWidth, attrs.indent);
28058
+ const baseStyles = {
28059
+ position: "absolute",
28060
+ top: "0px",
28061
+ bottom: "0px",
28062
+ left: `${borderBox.leftInset}px`,
28063
+ width: `${borderBox.width}px`,
28064
+ pointerEvents: "none",
28065
+ boxSizing: "border-box"
28066
+ };
28067
+ let shadingLayer;
28068
+ if (attrs.shading) {
28069
+ shadingLayer = doc2.createElement("div");
28070
+ shadingLayer.classList.add("superdoc-paragraph-shading");
28071
+ Object.assign(shadingLayer.style, baseStyles);
28072
+ applyParagraphShadingStyles(shadingLayer, attrs.shading);
28073
+ }
28074
+ let borderLayer;
28075
+ if (attrs.borders) {
28076
+ borderLayer = doc2.createElement("div");
28077
+ borderLayer.classList.add("superdoc-paragraph-border");
28078
+ Object.assign(borderLayer.style, baseStyles);
28079
+ borderLayer.style.zIndex = "1";
28080
+ applyParagraphBorderStyles(borderLayer, attrs.borders);
28081
+ }
28082
+ return { shadingLayer, borderLayer };
28021
28083
  };
28022
28084
  const BORDER_SIDES = ["top", "right", "bottom", "left"];
28023
28085
  const applyParagraphBorderStyles = (element, borders) => {
@@ -31667,33 +31729,13 @@ function computePartialRow(rowIndex, blockRow, measure, availableHeight, fromLin
31667
31729
  toLineByCell.push(cutLine);
31668
31730
  heightByCell.push(cumulativeHeight);
31669
31731
  }
31670
- const allCellsCompleteInFirstPass = toLineByCell.every((cutLine, idx) => {
31671
- const totalLines = getCellTotalLines(row.cells[idx]);
31672
- return cutLine >= totalLines;
31673
- });
31674
- const lineAdvancements = toLineByCell.map((cutLine, idx) => cutLine - (startLines[idx] || 0));
31675
- const positiveAdvancements = lineAdvancements.filter((adv) => adv > 0);
31676
- const minLineAdvancement = positiveAdvancements.length > 0 ? Math.min(...positiveAdvancements) : 0;
31677
31732
  let actualPartialHeight = 0;
31678
31733
  let maxPaddingTotal = 0;
31679
31734
  for (let cellIdx = 0; cellIdx < cellCount; cellIdx++) {
31680
- const cell = row.cells[cellIdx];
31681
- const startLine = startLines[cellIdx] || 0;
31682
- const lines = getCellLines(cell);
31683
31735
  const cellPadding = cellPaddings[cellIdx];
31684
31736
  const paddingTotal = cellPadding.top + cellPadding.bottom;
31685
31737
  maxPaddingTotal = Math.max(maxPaddingTotal, paddingTotal);
31686
- if (allCellsCompleteInFirstPass) {
31687
- actualPartialHeight = Math.max(actualPartialHeight, heightByCell[cellIdx] + paddingTotal);
31688
- } else {
31689
- const targetLine = Math.min(startLine + minLineAdvancement, lines.length);
31690
- let cumulativeHeight = 0;
31691
- for (let i = startLine; i < targetLine; i++) {
31692
- cumulativeHeight += lines[i].lineHeight || 0;
31693
- }
31694
- toLineByCell[cellIdx] = targetLine;
31695
- actualPartialHeight = Math.max(actualPartialHeight, cumulativeHeight + paddingTotal);
31696
- }
31738
+ actualPartialHeight = Math.max(actualPartialHeight, heightByCell[cellIdx] + paddingTotal);
31697
31739
  }
31698
31740
  const madeProgress = toLineByCell.some((cutLine, idx) => cutLine > (startLines[idx] || 0));
31699
31741
  const isFirstPart = startLines.every((l) => l === 0);
@@ -32246,7 +32288,7 @@ function toUpperLetter(num) {
32246
32288
  function toLowerLetter(num) {
32247
32289
  return toUpperLetter(num).toLowerCase();
32248
32290
  }
32249
- function formatPageNumber$1(pageNumber, format) {
32291
+ function formatPageNumber(pageNumber, format) {
32250
32292
  const num = Math.max(1, pageNumber);
32251
32293
  switch (format) {
32252
32294
  case "decimal":
@@ -32259,6 +32301,8 @@ function formatPageNumber$1(pageNumber, format) {
32259
32301
  return toUpperLetter(num);
32260
32302
  case "lowerLetter":
32261
32303
  return toLowerLetter(num);
32304
+ case "numberInDash":
32305
+ return `-${num}-`;
32262
32306
  default:
32263
32307
  return String(num);
32264
32308
  }
@@ -32287,7 +32331,7 @@ function computeDisplayPageNumber(pages, sections) {
32287
32331
  const sectionMetadata = sectionMap.get(pageSectionIndex);
32288
32332
  const format = sectionMetadata?.numbering?.format ?? "decimal";
32289
32333
  const displayNumber = runningCounter;
32290
- const displayText = formatPageNumber$1(displayNumber, format);
32334
+ const displayText = formatPageNumber(displayNumber, format);
32291
32335
  result.push({
32292
32336
  physicalPage: page.number,
32293
32337
  displayNumber,
@@ -32422,59 +32466,6 @@ const layoutLog = (...args) => {
32422
32466
  if (!layoutDebugEnabled$1) return;
32423
32467
  console.log(...args);
32424
32468
  };
32425
- function formatPageNumber(num, format) {
32426
- switch (format) {
32427
- case "decimal":
32428
- return String(num);
32429
- case "lowerLetter":
32430
- return toLetter(num, false);
32431
- case "upperLetter":
32432
- return toLetter(num, true);
32433
- case "lowerRoman":
32434
- return toRoman$1(num).toLowerCase();
32435
- case "upperRoman":
32436
- return toRoman$1(num);
32437
- default:
32438
- return String(num);
32439
- }
32440
- }
32441
- function toLetter(num, uppercase) {
32442
- let result = "";
32443
- let n = Math.max(1, Math.floor(num));
32444
- while (n > 0) {
32445
- const remainder = (n - 1) % 26;
32446
- const char = String.fromCharCode((uppercase ? 65 : 97) + remainder);
32447
- result = char + result;
32448
- n = Math.floor((n - 1) / 26);
32449
- }
32450
- return result;
32451
- }
32452
- function toRoman$1(num) {
32453
- const lookup = [
32454
- [1e3, "M"],
32455
- [900, "CM"],
32456
- [500, "D"],
32457
- [400, "CD"],
32458
- [100, "C"],
32459
- [90, "XC"],
32460
- [50, "L"],
32461
- [40, "XL"],
32462
- [10, "X"],
32463
- [9, "IX"],
32464
- [5, "V"],
32465
- [4, "IV"],
32466
- [1, "I"]
32467
- ];
32468
- let result = "";
32469
- let n = Math.max(1, Math.floor(num));
32470
- for (const [value, numeral] of lookup) {
32471
- while (n >= value) {
32472
- result += numeral;
32473
- n -= value;
32474
- }
32475
- }
32476
- return result;
32477
- }
32478
32469
  function layoutDocument(blocks, measures, options = {}) {
32479
32470
  if (blocks.length !== measures.length) {
32480
32471
  throw new Error(
@@ -33930,7 +33921,7 @@ class MeasureCache {
33930
33921
  return `${block.id}@${safeWidth}x${safeHeight}:${hash2}`;
33931
33922
  }
33932
33923
  }
33933
- function resolveHeaderFooterTokens(blocks, pageNumber, totalPages) {
33924
+ function resolveHeaderFooterTokens(blocks, pageNumber, totalPages, pageNumberText) {
33934
33925
  if (!blocks || blocks.length === 0) {
33935
33926
  return;
33936
33927
  }
@@ -33942,7 +33933,7 @@ function resolveHeaderFooterTokens(blocks, pageNumber, totalPages) {
33942
33933
  console.warn("[resolveHeaderFooterTokens] Invalid totalPages:", totalPages, "- using 1 as fallback");
33943
33934
  totalPages = 1;
33944
33935
  }
33945
- const pageNumberStr = String(pageNumber);
33936
+ const pageNumberStr = pageNumberText ?? String(pageNumber);
33946
33937
  const totalPagesStr = String(totalPages);
33947
33938
  for (const block of blocks) {
33948
33939
  if (block.kind !== "paragraph") continue;
@@ -34365,15 +34356,31 @@ async function layoutHeaderFooterWithCache(sections, constraints, measureBlock2,
34365
34356
  for (const pageNum of pagesToLayout) {
34366
34357
  const clonedBlocks = cloneHeaderFooterBlocks(blocks);
34367
34358
  const { displayText, totalPages: totalPagesForPage } = pageResolver(pageNum);
34368
- const resolvedPageNum = parseInt(displayText, 10) || pageNum;
34369
- resolveHeaderFooterTokens(clonedBlocks, resolvedPageNum, totalPagesForPage);
34359
+ resolveHeaderFooterTokens(clonedBlocks, pageNum, totalPagesForPage, displayText);
34370
34360
  const measures = await cache2.measureBlocks(clonedBlocks, constraints, measureBlock2);
34371
34361
  const pageLayout = layoutHeaderFooter(clonedBlocks, measures, constraints);
34362
+ const measuresById = /* @__PURE__ */ new Map();
34363
+ for (let i = 0; i < clonedBlocks.length; i += 1) {
34364
+ measuresById.set(clonedBlocks[i].id, measures[i]);
34365
+ }
34366
+ const fragmentsWithLines = pageLayout.pages[0]?.fragments.map((fragment) => {
34367
+ if (fragment.kind !== "para") {
34368
+ return fragment;
34369
+ }
34370
+ const measure = measuresById.get(fragment.blockId);
34371
+ if (!measure || measure.kind !== "paragraph") {
34372
+ return fragment;
34373
+ }
34374
+ return {
34375
+ ...fragment,
34376
+ lines: measure.lines.slice(fragment.fromLine, fragment.toLine)
34377
+ };
34378
+ }) ?? [];
34372
34379
  pages.push({
34373
34380
  number: pageNum,
34374
34381
  blocks: clonedBlocks,
34375
34382
  measures,
34376
- fragments: pageLayout.pages[0]?.fragments ?? []
34383
+ fragments: fragmentsWithLines
34377
34384
  });
34378
34385
  }
34379
34386
  const firstPageLayout = pages[0] ? layoutHeaderFooter(pages[0].blocks, pages[0].measures, constraints) : { height: 0 };
@@ -39260,7 +39267,14 @@ function extractPageNumbering(elements) {
39260
39267
  const pgNumType = elements.find((el) => el?.name === "w:pgNumType");
39261
39268
  if (!pgNumType?.attributes) return void 0;
39262
39269
  const fmtRaw = pgNumType.attributes["w:fmt"];
39263
- const validFormats = ["decimal", "lowerLetter", "upperLetter", "lowerRoman", "upperRoman"];
39270
+ const validFormats = [
39271
+ "decimal",
39272
+ "lowerLetter",
39273
+ "upperLetter",
39274
+ "lowerRoman",
39275
+ "upperRoman",
39276
+ "numberInDash"
39277
+ ];
39264
39278
  const fmt = validFormats.includes(fmtRaw) ? fmtRaw : void 0;
39265
39279
  const startRaw = pgNumType.attributes["w:start"];
39266
39280
  const startNum = startRaw != null ? Number(startRaw) : void 0;
@@ -49302,6 +49316,7 @@ const CommentMarkName = "commentMark";
49302
49316
  const TrackInsertMarkName = "trackInsert";
49303
49317
  const TrackDeleteMarkName = "trackDelete";
49304
49318
  const TrackFormatMarkName = "trackFormat";
49319
+ const SUBSCRIPT_SUPERSCRIPT_SCALE = 0.65;
49305
49320
  const DEFAULT_PAGE_SIZE = { w: 612, h: 792 };
49306
49321
  const DEFAULT_MARGINS = { top: 72, right: 72, bottom: 72, left: 72 };
49307
49322
  const DEFAULT_VIRTUALIZED_PAGE_GAP = 72;
@@ -52546,6 +52561,7 @@ class PresentationEditor extends EventEmitter {
52546
52561
  );
52547
52562
  this.#domIndexObserverManager?.pause();
52548
52563
  painter.paint(layout, this.#painterHost);
52564
+ this.#applyVertAlignToLayout();
52549
52565
  this.#rebuildDomPositionIndex();
52550
52566
  this.#domIndexObserverManager?.resume();
52551
52567
  this.#layoutEpoch = layoutEpoch;
@@ -54308,6 +54324,90 @@ class PresentationEditor extends EventEmitter {
54308
54324
  this.#errorBanner = null;
54309
54325
  this.#errorBannerMessage = null;
54310
54326
  }
54327
+ /**
54328
+ * Applies vertical alignment and font scaling to layout DOM elements for subscript/superscript rendering.
54329
+ *
54330
+ * This method post-processes the painted DOM layout to apply vertical alignment styles
54331
+ * (super, sub, baseline, or custom position) based on run properties and text style marks.
54332
+ * It handles both DOCX-style vertAlign ('superscript', 'subscript', 'baseline') and
54333
+ * custom position offsets (in half-points).
54334
+ *
54335
+ * Processing logic:
54336
+ * 1. Queries all text spans with ProseMirror position markers
54337
+ * 2. For each span, resolves the ProseMirror position to find the containing run node
54338
+ * 3. Extracts vertAlign and position from run properties and/or text style marks
54339
+ * 4. Applies CSS vertical-align and font-size styles based on the extracted properties
54340
+ * 5. Position takes precedence over vertAlign when both are present
54341
+ *
54342
+ * @throws Does not throw - DOM manipulation errors are silently caught to prevent layout corruption
54343
+ * @private
54344
+ */
54345
+ #applyVertAlignToLayout() {
54346
+ const doc2 = this.#editor?.state?.doc;
54347
+ if (!doc2 || !this.#painterHost) return;
54348
+ try {
54349
+ const spans = this.#painterHost.querySelectorAll(".superdoc-line span[data-pm-start]");
54350
+ spans.forEach((span) => {
54351
+ try {
54352
+ if (span.closest(".superdoc-page-header, .superdoc-page-footer")) return;
54353
+ const pmStart = Number(span.dataset.pmStart ?? "NaN");
54354
+ if (!Number.isFinite(pmStart)) return;
54355
+ const pos = Math.max(0, Math.min(pmStart, doc2.content.size));
54356
+ const $pos = doc2.resolve(pos);
54357
+ let runNode = null;
54358
+ for (let depth = $pos.depth; depth >= 0; depth--) {
54359
+ const node = $pos.node(depth);
54360
+ if (node.type.name === "run") {
54361
+ runNode = node;
54362
+ break;
54363
+ }
54364
+ }
54365
+ let vertAlign = runNode?.attrs?.runProperties?.vertAlign ?? null;
54366
+ let position = runNode?.attrs?.runProperties?.position ?? null;
54367
+ let fontSizeHalfPts = runNode?.attrs?.runProperties?.fontSize ?? null;
54368
+ if (!vertAlign && position == null && runNode) {
54369
+ runNode.forEach((child) => {
54370
+ if (!child.isText || !child.marks?.length) return;
54371
+ const rpr = decodeRPrFromMarks(child.marks);
54372
+ if (rpr.vertAlign && !vertAlign) vertAlign = rpr.vertAlign;
54373
+ if (rpr.position != null && position == null) position = rpr.position;
54374
+ if (rpr.fontSize != null && fontSizeHalfPts == null) fontSizeHalfPts = rpr.fontSize;
54375
+ });
54376
+ }
54377
+ if (vertAlign == null && position == null) return;
54378
+ const styleEntries = [];
54379
+ if (position != null && Number.isFinite(position)) {
54380
+ const pts = halfPointToPoints(position);
54381
+ if (Number.isFinite(pts)) {
54382
+ styleEntries.push(`vertical-align: ${pts}pt`);
54383
+ }
54384
+ } else if (vertAlign === "superscript" || vertAlign === "subscript") {
54385
+ styleEntries.push(`vertical-align: ${vertAlign === "superscript" ? "super" : "sub"}`);
54386
+ if (fontSizeHalfPts != null && Number.isFinite(fontSizeHalfPts)) {
54387
+ const scaledPts = halfPointToPoints(fontSizeHalfPts * SUBSCRIPT_SUPERSCRIPT_SCALE);
54388
+ if (Number.isFinite(scaledPts)) {
54389
+ styleEntries.push(`font-size: ${scaledPts}pt`);
54390
+ } else {
54391
+ styleEntries.push(`font-size: ${SUBSCRIPT_SUPERSCRIPT_SCALE * 100}%`);
54392
+ }
54393
+ } else {
54394
+ styleEntries.push(`font-size: ${SUBSCRIPT_SUPERSCRIPT_SCALE * 100}%`);
54395
+ }
54396
+ } else if (vertAlign === "baseline") {
54397
+ styleEntries.push("vertical-align: baseline");
54398
+ }
54399
+ if (!styleEntries.length) return;
54400
+ const existing = span.getAttribute("style");
54401
+ const merged = existing ? `${existing}; ${styleEntries.join("; ")}` : styleEntries.join("; ");
54402
+ span.setAttribute("style", merged);
54403
+ } catch (error) {
54404
+ console.error("Failed to apply vertical alignment to span:", error);
54405
+ }
54406
+ });
54407
+ } catch (error) {
54408
+ console.error("Failed to apply vertical alignment to layout:", error);
54409
+ }
54410
+ }
54311
54411
  }
54312
54412
  const Color = Extension.create({
54313
54413
  name: "color",
@@ -65849,7 +65949,63 @@ const TextStyle = Mark.create({
65849
65949
  * @category Attribute
65850
65950
  * @param {string} [styleId] - Style identifier for referencing predefined styles
65851
65951
  */
65852
- styleId: {}
65952
+ styleId: {},
65953
+ /**
65954
+ * Vertical alignment for subscript/superscript text (DOCX w:vertAlign).
65955
+ * Standard values: 'superscript', 'subscript', 'baseline'.
65956
+ * When both vertAlign and position are present, position takes precedence.
65957
+ * Renders as CSS vertical-align with 65% font-size scaling for super/subscript.
65958
+ * @category Attribute
65959
+ * @param {string} [vertAlign] - Vertical alignment mode ('superscript' | 'subscript' | 'baseline')
65960
+ */
65961
+ vertAlign: {
65962
+ default: null,
65963
+ renderDOM: (attrs) => {
65964
+ if (!attrs.vertAlign || attrs.position) return {};
65965
+ if (attrs.vertAlign === "superscript") {
65966
+ return { style: "vertical-align: super; font-size: 65%;" };
65967
+ }
65968
+ if (attrs.vertAlign === "subscript") {
65969
+ return { style: "vertical-align: sub; font-size: 65%;" };
65970
+ }
65971
+ if (attrs.vertAlign === "baseline") {
65972
+ return { style: "vertical-align: baseline;" };
65973
+ }
65974
+ return {};
65975
+ },
65976
+ parseDOM: (el) => {
65977
+ const va = el.style?.verticalAlign;
65978
+ if (va === "super") return "superscript";
65979
+ if (va === "sub") return "subscript";
65980
+ if (va === "baseline") return "baseline";
65981
+ return null;
65982
+ }
65983
+ },
65984
+ /**
65985
+ * Custom vertical position offset in points (DOCX w:position).
65986
+ * Numeric value specifying vertical offset (positive raises, negative lowers).
65987
+ * Format: '{number}pt' (e.g., '2pt', '-1.5pt').
65988
+ * Takes precedence over vertAlign when both are present.
65989
+ * Renders as CSS vertical-align with the exact offset value.
65990
+ * @category Attribute
65991
+ * @param {string} [position] - Vertical position offset (e.g., '2pt', '-1pt')
65992
+ */
65993
+ position: {
65994
+ default: null,
65995
+ renderDOM: (attrs) => {
65996
+ if (!attrs.position) return {};
65997
+ return { style: `vertical-align: ${attrs.position};` };
65998
+ },
65999
+ parseDOM: (el) => {
66000
+ const va = el.style?.verticalAlign;
66001
+ if (!va) return null;
66002
+ const numeric = parseFloat(va);
66003
+ if (!Number.isNaN(numeric)) {
66004
+ return `${numeric}pt`;
66005
+ }
66006
+ return null;
66007
+ }
66008
+ }
65853
66009
  };
65854
66010
  },
65855
66011
  addCommands() {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
- const index = require("./index-B2xKsF_F.cjs");
3
- require("./SuperConverter-C_fR_pax.cjs");
2
+ const index = require("./index-C2XLSjq0.cjs");
3
+ require("./SuperConverter-DOTz2R8L.cjs");
4
4
  const blankDocx = require("./blank-docx-DfW3Eeh2.cjs");
5
5
  const eventemitter3 = require("./eventemitter3-BQuRcMPI.cjs");
6
6
  const provider = require("@hocuspocus/provider");
@@ -7461,7 +7461,7 @@ const _sfc_main = {
7461
7461
  __name: "SuperDoc",
7462
7462
  emits: ["selection-update"],
7463
7463
  setup(__props, { emit: __emit }) {
7464
- const PdfViewer = vue.defineAsyncComponent(() => Promise.resolve().then(() => require("./PdfViewer-Cq1mqKR1.cjs")));
7464
+ const PdfViewer = vue.defineAsyncComponent(() => Promise.resolve().then(() => require("./PdfViewer-BEZc2jzN.cjs")));
7465
7465
  const superdocStore = useSuperdocStore();
7466
7466
  const commentsStore = useCommentsStore();
7467
7467
  const {
@@ -8367,7 +8367,7 @@ class SuperDoc extends eventemitter3.EventEmitter {
8367
8367
  this.config.colors = shuffleArray(this.config.colors);
8368
8368
  this.userColorMap = /* @__PURE__ */ new Map();
8369
8369
  this.colorIndex = 0;
8370
- this.version = "1.2.2-next.1";
8370
+ this.version = "1.3.0-next.2";
8371
8371
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
8372
8372
  this.superdocId = config.superdocId || uuid.v4();
8373
8373
  this.colors = this.config.colors;
@@ -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-C_fR_pax.cjs");
5
+ const superEditor_converter = require("../chunks/SuperConverter-DOTz2R8L.cjs");
6
6
  require("../chunks/uuid-R7L08bOx.cjs");
7
7
  exports.SuperConverter = superEditor_converter.SuperConverter;
@@ -1,6 +1,6 @@
1
1
  import "../chunks/jszip-B1fkPkPJ.es.js";
2
- import "../chunks/helpers-CAUq8coh.es.js";
3
- import { S } from "../chunks/SuperConverter-C4sb9GH7.es.js";
2
+ import "../chunks/helpers-C8e9wR5l.es.js";
3
+ import { S } from "../chunks/SuperConverter-ClzyObj7.es.js";
4
4
  import "../chunks/uuid-CjlX8hrF.es.js";
5
5
  export {
6
6
  S as SuperConverter
@@ -1,5 +1,5 @@
1
1
  import { B as Buffer } from "../chunks/jszip-B1fkPkPJ.es.js";
2
- import { g as getContentTypesFromXml, f as libExports } from "../chunks/helpers-CAUq8coh.es.js";
2
+ import { g as getContentTypesFromXml, f as libExports } from "../chunks/helpers-C8e9wR5l.es.js";
3
3
  import { J as JSZip } from "../chunks/jszip.min-DCl8qkFO.es.js";
4
4
  const isXmlLike = (name) => /\.xml$|\.rels$/i.test(name);
5
5
  function sniffEncoding(u8) {
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const index = require("./chunks/index-B2xKsF_F.cjs");
3
+ const index = require("./chunks/index-C2XLSjq0.cjs");
4
4
  const superEditor_docxZipper = require("./super-editor/docx-zipper.cjs");
5
5
  const superEditor_fileZipper = require("./super-editor/file-zipper.cjs");
6
6
  const vue = require("./chunks/vue-De9wkgLl.cjs");
7
- const superEditor_converter = require("./chunks/SuperConverter-C_fR_pax.cjs");
7
+ const superEditor_converter = require("./chunks/SuperConverter-DOTz2R8L.cjs");
8
8
  function isNodeType(node, name) {
9
9
  return node.type.name === name;
10
10
  }
@@ -1,9 +1,9 @@
1
- import { ax as Node, ay as Mark } from "./chunks/index-CcYK8nzG.es.js";
2
- import { ao, au, a9, ab, aw, am, av, aA, an, ak, aq, az, aa, as, aC, aE, aB, ac, aD, ar, at } from "./chunks/index-CcYK8nzG.es.js";
1
+ import { ax as Node, ay as Mark } from "./chunks/index-D5tN0eME.es.js";
2
+ import { ao, au, a9, ab, aw, am, av, aA, an, ak, aq, az, aa, as, aC, aE, aB, ac, aD, ar, at } from "./chunks/index-D5tN0eME.es.js";
3
3
  import { default as default2 } from "./super-editor/docx-zipper.es.js";
4
4
  import { createZip } from "./super-editor/file-zipper.es.js";
5
5
  import { d as defineComponent, E as createElementBlock, G as openBlock, K as createBaseVNode } from "./chunks/vue-BnBKJwCW.es.js";
6
- import { S, r } from "./chunks/SuperConverter-C4sb9GH7.es.js";
6
+ import { S, r } from "./chunks/SuperConverter-ClzyObj7.es.js";
7
7
  function isNodeType(node, name) {
8
8
  return node.type.name === name;
9
9
  }
package/dist/superdoc.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const index = require("./chunks/index-B2xKsF_F.cjs");
4
- const superdoc = require("./chunks/index-BS-AafWf.cjs");
5
- const superEditor_converter = require("./chunks/SuperConverter-C_fR_pax.cjs");
3
+ const index = require("./chunks/index-C2XLSjq0.cjs");
4
+ const superdoc = require("./chunks/index-sykfrKvQ.cjs");
5
+ const superEditor_converter = require("./chunks/SuperConverter-DOTz2R8L.cjs");
6
6
  const blankDocx = require("./chunks/blank-docx-DfW3Eeh2.cjs");
7
7
  require("./chunks/jszip-C8_CqJxM.cjs");
8
8
  require("./chunks/helpers-nOdwpmwb.cjs");
@@ -1,9 +1,9 @@
1
- import { au, ab, aw, av, as, a7, ac, ar, at } from "./chunks/index-CcYK8nzG.es.js";
2
- import { D, H, P, S, c } from "./chunks/index-Di1Kp3nz.es.js";
3
- import { S as S2, r } from "./chunks/SuperConverter-C4sb9GH7.es.js";
1
+ import { au, ab, aw, av, as, a7, ac, ar, at } from "./chunks/index-D5tN0eME.es.js";
2
+ import { D, H, P, S, c } from "./chunks/index-CMxyLpsU.es.js";
3
+ import { S as S2, r } from "./chunks/SuperConverter-ClzyObj7.es.js";
4
4
  import { B } from "./chunks/blank-docx-ABm6XYAA.es.js";
5
5
  import "./chunks/jszip-B1fkPkPJ.es.js";
6
- import "./chunks/helpers-CAUq8coh.es.js";
6
+ import "./chunks/helpers-C8e9wR5l.es.js";
7
7
  import "./chunks/jszip.min-DCl8qkFO.es.js";
8
8
  import { createZip } from "./super-editor/file-zipper.es.js";
9
9
  export {