@harbour-enterprises/superdoc 1.4.1-next.3 → 1.5.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,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-Cc0b8QgF.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-Qu0fAMVM.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";
@@ -15499,7 +15499,7 @@ const canUseDOM = () => {
15499
15499
  return false;
15500
15500
  }
15501
15501
  };
15502
- const summaryVersion = "1.4.1-next.3";
15502
+ const summaryVersion = "1.5.0-next.1";
15503
15503
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
15504
15504
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
15505
15505
  function mapAttributes(attrs) {
@@ -16809,6 +16809,31 @@ class Editor extends EventEmitter {
16809
16809
  }
16810
16810
  return null;
16811
16811
  }
16812
+ /**
16813
+ * Get the DOM element for a document position.
16814
+ * In presentation mode, returns the painted element.
16815
+ */
16816
+ getElementAtPos(pos, options = {}) {
16817
+ if (this.presentationEditor) {
16818
+ return this.presentationEditor.getElementAtPos(pos, options);
16819
+ }
16820
+ if (!this.view) return null;
16821
+ if (!Number.isFinite(pos)) return null;
16822
+ const maxPos = this.view.state.doc.content.size;
16823
+ const clampedPos = Math.max(0, Math.min(pos, maxPos));
16824
+ try {
16825
+ const { node } = this.view.domAtPos(clampedPos);
16826
+ if (node && node.nodeType === 1) {
16827
+ return node;
16828
+ }
16829
+ if (node && node.nodeType === 3) {
16830
+ return node.parentElement;
16831
+ }
16832
+ return node?.parentElement ?? null;
16833
+ } catch {
16834
+ return null;
16835
+ }
16836
+ }
16812
16837
  /**
16813
16838
  * Get position from client-space coordinates.
16814
16839
  * In layout/presentation mode, uses PresentationEditor hit testing for accurate coordinate mapping.
@@ -18131,7 +18156,7 @@ class Editor extends EventEmitter {
18131
18156
  * Process collaboration migrations
18132
18157
  */
18133
18158
  processCollaborationMigrations() {
18134
- console.debug("[checkVersionMigrations] Current editor version", "1.4.1-next.3");
18159
+ console.debug("[checkVersionMigrations] Current editor version", "1.5.0-next.1");
18135
18160
  if (!this.options.ydoc) return;
18136
18161
  const metaMap = this.options.ydoc.getMap("meta");
18137
18162
  let docVersion = metaMap.get("version");
@@ -23155,27 +23180,33 @@ const SDT_CONTAINER_STYLES = `
23155
23180
  align-items: center;
23156
23181
  }
23157
23182
 
23158
- /* Continuation styling: first fragment has top corners, last has bottom corners */
23159
- .superdoc-document-section[data-sdt-container-start="true"] {
23160
- border-radius: 4px 4px 0 0;
23183
+ /* Continuation styling: SDT container boundary handling for multi-fragment document sections */
23184
+ /* Single fragment (both start and end): full border radius */
23185
+ .superdoc-document-section[data-sdt-container-start="true"][data-sdt-container-end="true"] {
23186
+ border-radius: 4px;
23161
23187
  }
23162
23188
 
23163
- .superdoc-document-section[data-sdt-container-end="true"] {
23164
- border-radius: 0 0 4px 4px;
23189
+ /* First fragment of a multi-fragment SDT: top corners, no bottom border */
23190
+ .superdoc-document-section[data-sdt-container-start="true"]:not([data-sdt-container-end="true"]) {
23191
+ border-radius: 4px 4px 0 0;
23192
+ border-bottom: none;
23165
23193
  }
23166
23194
 
23167
- .superdoc-document-section[data-sdt-container-start="true"][data-sdt-container-end="true"] {
23168
- border-radius: 4px;
23195
+ /* Last fragment of a multi-fragment SDT: bottom corners, no top border */
23196
+ .superdoc-document-section[data-sdt-container-end="true"]:not([data-sdt-container-start="true"]) {
23197
+ border-radius: 0 0 4px 4px;
23198
+ border-top: none;
23169
23199
  }
23170
23200
 
23171
23201
  .superdoc-document-section[data-sdt-container-start="true"]:hover {
23172
23202
  border-radius: 0 4px 0 0;
23173
23203
  }
23174
23204
 
23175
- /* Middle fragments have no border radius */
23205
+ /* Middle fragments (neither start nor end): no corners, no top/bottom borders */
23176
23206
  .superdoc-document-section:not([data-sdt-container-start="true"]):not([data-sdt-container-end="true"]) {
23177
23207
  border-radius: 0;
23178
23208
  border-top: none;
23209
+ border-bottom: none;
23179
23210
  }
23180
23211
 
23181
23212
  /* Structured Content Block - Blue border container */
@@ -23222,21 +23253,28 @@ const SDT_CONTAINER_STYLES = `
23222
23253
  }
23223
23254
 
23224
23255
  /* Continuation styling for structured content blocks */
23225
- .superdoc-structured-content-block[data-sdt-container-start="true"] {
23226
- border-radius: 4px 4px 0 0;
23256
+ /* Single fragment (both start and end): full border radius */
23257
+ .superdoc-structured-content-block[data-sdt-container-start="true"][data-sdt-container-end="true"] {
23258
+ border-radius: 4px;
23227
23259
  }
23228
23260
 
23229
- .superdoc-structured-content-block[data-sdt-container-end="true"] {
23230
- border-radius: 0 0 4px 4px;
23261
+ /* First fragment of a multi-fragment SDT: top corners, no bottom border */
23262
+ .superdoc-structured-content-block[data-sdt-container-start="true"]:not([data-sdt-container-end="true"]) {
23263
+ border-radius: 4px 4px 0 0;
23264
+ border-bottom: none;
23231
23265
  }
23232
23266
 
23233
- .superdoc-structured-content-block[data-sdt-container-start="true"][data-sdt-container-end="true"] {
23234
- border-radius: 4px;
23267
+ /* Last fragment of a multi-fragment SDT: bottom corners, no top border */
23268
+ .superdoc-structured-content-block[data-sdt-container-end="true"]:not([data-sdt-container-start="true"]) {
23269
+ border-radius: 0 0 4px 4px;
23270
+ border-top: none;
23235
23271
  }
23236
23272
 
23273
+ /* Middle fragment (neither start nor end): no corners, no top/bottom borders */
23237
23274
  .superdoc-structured-content-block:not([data-sdt-container-start="true"]):not([data-sdt-container-end="true"]) {
23238
23275
  border-radius: 0;
23239
23276
  border-top: none;
23277
+ border-bottom: none;
23240
23278
  }
23241
23279
 
23242
23280
  /* Structured Content Inline - Inline wrapper with blue border */
@@ -23705,6 +23743,78 @@ const resolveTableCellBorders = (tableBorders, rowIndex, colIndex, totalRows, to
23705
23743
  right: borderValueToSpec(isLastCol ? tableBorders?.right : null)
23706
23744
  };
23707
23745
  };
23746
+ function isStructuredContentMetadata(sdt) {
23747
+ return sdt !== null && sdt !== void 0 && typeof sdt === "object" && "type" in sdt && sdt.type === "structuredContent";
23748
+ }
23749
+ function isDocumentSectionMetadata(sdt) {
23750
+ return sdt !== null && sdt !== void 0 && typeof sdt === "object" && "type" in sdt && sdt.type === "documentSection";
23751
+ }
23752
+ function getSdtContainerConfig(sdt) {
23753
+ if (isDocumentSectionMetadata(sdt)) {
23754
+ return {
23755
+ className: "superdoc-document-section",
23756
+ labelText: sdt.title ?? "Document section",
23757
+ labelClassName: "superdoc-document-section__tooltip",
23758
+ isStart: true,
23759
+ isEnd: true
23760
+ };
23761
+ }
23762
+ if (isStructuredContentMetadata(sdt) && sdt.scope === "block") {
23763
+ return {
23764
+ className: "superdoc-structured-content-block",
23765
+ labelText: sdt.alias ?? "Structured content",
23766
+ labelClassName: "superdoc-structured-content__label",
23767
+ isStart: true,
23768
+ isEnd: true
23769
+ };
23770
+ }
23771
+ return null;
23772
+ }
23773
+ function getSdtContainerMetadata(sdt, containerSdt) {
23774
+ if (getSdtContainerConfig(sdt)) return sdt ?? null;
23775
+ if (getSdtContainerConfig(containerSdt)) return containerSdt ?? null;
23776
+ return null;
23777
+ }
23778
+ function getSdtContainerKey(sdt, containerSdt) {
23779
+ const metadata = getSdtContainerMetadata(sdt, containerSdt);
23780
+ if (!metadata) return null;
23781
+ if (metadata.type === "structuredContent") {
23782
+ if (metadata.scope !== "block") return null;
23783
+ if (!metadata.id) {
23784
+ return null;
23785
+ }
23786
+ return `structuredContent:${metadata.id}`;
23787
+ }
23788
+ if (metadata.type === "documentSection") {
23789
+ const sectionId = metadata.id ?? metadata.sdBlockId;
23790
+ if (!sectionId) {
23791
+ return null;
23792
+ }
23793
+ return `documentSection:${sectionId}`;
23794
+ }
23795
+ return null;
23796
+ }
23797
+ function applySdtContainerStyling(doc2, container, sdt, containerSdt, boundaryOptions) {
23798
+ let config = getSdtContainerConfig(sdt);
23799
+ if (!config && containerSdt) {
23800
+ config = getSdtContainerConfig(containerSdt);
23801
+ }
23802
+ if (!config) return;
23803
+ const isStart = boundaryOptions?.isStart ?? config.isStart;
23804
+ const isEnd = boundaryOptions?.isEnd ?? config.isEnd;
23805
+ container.classList.add(config.className);
23806
+ container.dataset.sdtContainerStart = String(isStart);
23807
+ container.dataset.sdtContainerEnd = String(isEnd);
23808
+ container.style.overflow = "visible";
23809
+ if (isStart) {
23810
+ const labelEl = doc2.createElement("div");
23811
+ labelEl.className = config.labelClassName;
23812
+ const labelText = doc2.createElement("span");
23813
+ labelText.textContent = config.labelText;
23814
+ labelEl.appendChild(labelText);
23815
+ container.appendChild(labelEl);
23816
+ }
23817
+ }
23708
23818
  const LIST_MARKER_GAP$3 = 8;
23709
23819
  function renderListMarker(params2) {
23710
23820
  const { doc: doc2, lineEl, markerLayout, markerMeasure, indentLeftPx } = params2;
@@ -23742,6 +23852,54 @@ function renderListMarker(params2) {
23742
23852
  lineContainer.appendChild(lineEl);
23743
23853
  return lineContainer;
23744
23854
  }
23855
+ const applyInlineStyles = (el, styles) => {
23856
+ Object.entries(styles).forEach(([key2, value]) => {
23857
+ if (value != null && value !== "" && key2 in el.style) {
23858
+ el.style[key2] = String(value);
23859
+ }
23860
+ });
23861
+ };
23862
+ const EMBEDDED_TABLE_VERSION = "embedded-table";
23863
+ const renderEmbeddedTable = (params2) => {
23864
+ const { doc: doc2, table, measure, context, renderLine, renderDrawingContent, applySdtDataset } = params2;
23865
+ const fragment = {
23866
+ kind: "table",
23867
+ blockId: table.id,
23868
+ fromRow: 0,
23869
+ toRow: table.rows.length,
23870
+ x: 0,
23871
+ y: 0,
23872
+ width: measure.totalWidth,
23873
+ height: measure.totalHeight
23874
+ };
23875
+ const blockLookup = /* @__PURE__ */ new Map([
23876
+ [
23877
+ table.id,
23878
+ {
23879
+ block: table,
23880
+ measure,
23881
+ version: EMBEDDED_TABLE_VERSION
23882
+ }
23883
+ ]
23884
+ ]);
23885
+ const applyFragmentFrame = (el, frag) => {
23886
+ el.style.left = `${frag.x}px`;
23887
+ el.style.top = `${frag.y}px`;
23888
+ el.style.width = `${frag.width}px`;
23889
+ el.dataset.blockId = frag.blockId;
23890
+ };
23891
+ return renderTableFragment({
23892
+ doc: doc2,
23893
+ fragment,
23894
+ context,
23895
+ blockLookup,
23896
+ renderLine,
23897
+ renderDrawingContent,
23898
+ applyFragmentFrame,
23899
+ applySdtDataset,
23900
+ applyStyles: applyInlineStyles
23901
+ });
23902
+ };
23745
23903
  function applyParagraphBordersAndShading(paraWrapper, block) {
23746
23904
  const borders = block.attrs?.borders;
23747
23905
  if (borders) {
@@ -23782,10 +23940,12 @@ const renderTableCell = (deps) => {
23782
23940
  cellMeasure,
23783
23941
  cell,
23784
23942
  borders,
23943
+ useDefaultBorder,
23785
23944
  renderLine,
23786
23945
  renderDrawingContent,
23787
23946
  context,
23788
23947
  applySdtDataset,
23948
+ tableSdt,
23789
23949
  fromLine,
23790
23950
  toLine
23791
23951
  } = deps;
@@ -23809,12 +23969,46 @@ const renderTableCell = (deps) => {
23809
23969
  cellEl.style.paddingBottom = `${paddingBottom}px`;
23810
23970
  if (borders) {
23811
23971
  applyCellBorders(cellEl, borders);
23972
+ } else if (useDefaultBorder) {
23973
+ cellEl.style.border = "1px solid rgba(0,0,0,0.6)";
23812
23974
  }
23813
23975
  if (cell?.attrs?.background) {
23814
23976
  cellEl.style.backgroundColor = cell.attrs.background;
23815
23977
  }
23816
23978
  const cellBlocks = cell?.blocks ?? (cell?.paragraph ? [cell.paragraph] : []);
23817
23979
  const blockMeasures = cellMeasure?.blocks ?? (cellMeasure?.paragraph ? [cellMeasure.paragraph] : []);
23980
+ const sdtContainerKeys = cellBlocks.map((block) => {
23981
+ if (block.kind !== "paragraph") {
23982
+ return null;
23983
+ }
23984
+ const attrs2 = block.attrs;
23985
+ return getSdtContainerKey(attrs2?.sdt, attrs2?.containerSdt);
23986
+ });
23987
+ const sdtBoundaries = sdtContainerKeys.map((key2, index2) => {
23988
+ if (!key2) return void 0;
23989
+ const prev = index2 > 0 ? sdtContainerKeys[index2 - 1] : null;
23990
+ const next = index2 < sdtContainerKeys.length - 1 ? sdtContainerKeys[index2 + 1] : null;
23991
+ return { isStart: key2 !== prev, isEnd: key2 !== next };
23992
+ });
23993
+ const tableSdtKey = tableSdt ? getSdtContainerKey(tableSdt, null) : null;
23994
+ const shouldApplySdtContainerStyling = (sdt, containerSdt, blockKey) => {
23995
+ const resolvedKey = blockKey ?? getSdtContainerKey(sdt, containerSdt);
23996
+ if (tableSdtKey && resolvedKey && tableSdtKey === resolvedKey) {
23997
+ return false;
23998
+ }
23999
+ if (tableSdt && (sdt === tableSdt || containerSdt === tableSdt)) {
24000
+ return false;
24001
+ }
24002
+ return Boolean(getSdtContainerConfig(sdt) || getSdtContainerConfig(containerSdt));
24003
+ };
24004
+ const hasSdtContainer = cellBlocks.some((block, index2) => {
24005
+ const attrs2 = block.attrs;
24006
+ const blockKey = sdtContainerKeys[index2] ?? null;
24007
+ return shouldApplySdtContainerStyling(attrs2?.sdt, attrs2?.containerSdt, blockKey);
24008
+ });
24009
+ if (hasSdtContainer) {
24010
+ cellEl.style.overflow = "visible";
24011
+ }
23818
24012
  if (cellBlocks.length > 0 && blockMeasures.length > 0) {
23819
24013
  const content = doc2.createElement("div");
23820
24014
  content.style.position = "relative";
@@ -23846,6 +24040,26 @@ const renderTableCell = (deps) => {
23846
24040
  for (let i = 0; i < Math.min(blockMeasures.length, cellBlocks.length); i++) {
23847
24041
  const blockMeasure = blockMeasures[i];
23848
24042
  const block = cellBlocks[i];
24043
+ if (blockMeasure.kind === "table" && block?.kind === "table") {
24044
+ const tableMeasure = blockMeasure;
24045
+ const tableWrapper = doc2.createElement("div");
24046
+ tableWrapper.style.position = "relative";
24047
+ tableWrapper.style.width = "100%";
24048
+ tableWrapper.style.height = `${tableMeasure.totalHeight}px`;
24049
+ tableWrapper.style.boxSizing = "border-box";
24050
+ const tableEl = renderEmbeddedTable({
24051
+ doc: doc2,
24052
+ table: block,
24053
+ measure: tableMeasure,
24054
+ context: { ...context, section: "body" },
24055
+ renderLine,
24056
+ renderDrawingContent,
24057
+ applySdtDataset
24058
+ });
24059
+ tableWrapper.appendChild(tableEl);
24060
+ content.appendChild(tableWrapper);
24061
+ continue;
24062
+ }
23849
24063
  if (blockMeasure.kind === "image" && block?.kind === "image") {
23850
24064
  const imageWrapper = doc2.createElement("div");
23851
24065
  imageWrapper.style.position = "relative";
@@ -23941,6 +24155,11 @@ const renderTableCell = (deps) => {
23941
24155
  paraWrapper.style.left = "0";
23942
24156
  paraWrapper.style.width = "100%";
23943
24157
  applySdtDataset(paraWrapper, block.attrs?.sdt);
24158
+ const sdtBoundary = sdtBoundaries[i];
24159
+ const blockKey = sdtContainerKeys[i] ?? null;
24160
+ if (shouldApplySdtContainerStyling(block.attrs?.sdt, block.attrs?.containerSdt, blockKey)) {
24161
+ applySdtContainerStyling(doc2, paraWrapper, block.attrs?.sdt, block.attrs?.containerSdt, sdtBoundary);
24162
+ }
23944
24163
  applyParagraphBordersAndShading(paraWrapper, block);
23945
24164
  applyParagraphBorderStyles(paraWrapper, block.attrs?.borders);
23946
24165
  applyParagraphShadingStyles(paraWrapper, block.attrs?.shading);
@@ -24015,8 +24234,6 @@ const renderTableCell = (deps) => {
24015
24234
  }
24016
24235
  }
24017
24236
  cumulativeLineCount += blockLineCount;
24018
- } else {
24019
- cumulativeLineCount += 0;
24020
24237
  }
24021
24238
  }
24022
24239
  }
@@ -24038,6 +24255,7 @@ const renderTableRow = (deps) => {
24038
24255
  renderLine,
24039
24256
  renderDrawingContent,
24040
24257
  applySdtDataset,
24258
+ tableSdt,
24041
24259
  continuesFromPrev,
24042
24260
  continuesOnNext,
24043
24261
  partialRow
@@ -24132,60 +24350,18 @@ const renderTableRow = (deps) => {
24132
24350
  cellMeasure,
24133
24351
  cell,
24134
24352
  borders: resolvedBorders,
24353
+ useDefaultBorder: false,
24135
24354
  renderLine,
24136
24355
  renderDrawingContent,
24137
24356
  context,
24138
24357
  applySdtDataset,
24358
+ tableSdt,
24139
24359
  fromLine,
24140
24360
  toLine
24141
24361
  });
24142
24362
  container.appendChild(cellElement);
24143
24363
  }
24144
24364
  };
24145
- function isStructuredContentMetadata(sdt) {
24146
- return sdt !== null && sdt !== void 0 && typeof sdt === "object" && "type" in sdt && sdt.type === "structuredContent";
24147
- }
24148
- function isDocumentSectionMetadata(sdt) {
24149
- return sdt !== null && sdt !== void 0 && typeof sdt === "object" && "type" in sdt && sdt.type === "documentSection";
24150
- }
24151
- function getSdtContainerConfig(sdt) {
24152
- if (isDocumentSectionMetadata(sdt)) {
24153
- return {
24154
- className: "superdoc-document-section",
24155
- labelText: sdt.title ?? "Document section",
24156
- labelClassName: "superdoc-document-section__tooltip",
24157
- isStart: true,
24158
- isEnd: true
24159
- };
24160
- }
24161
- if (isStructuredContentMetadata(sdt) && sdt.scope === "block") {
24162
- return {
24163
- className: "superdoc-structured-content-block",
24164
- labelText: sdt.alias ?? "Structured content",
24165
- labelClassName: "superdoc-structured-content__label",
24166
- isStart: true,
24167
- isEnd: true
24168
- };
24169
- }
24170
- return null;
24171
- }
24172
- function applySdtContainerStyling(doc2, container, sdt, containerSdt) {
24173
- let config = getSdtContainerConfig(sdt);
24174
- if (!config && containerSdt) {
24175
- config = getSdtContainerConfig(containerSdt);
24176
- }
24177
- if (!config) return;
24178
- container.classList.add(config.className);
24179
- container.dataset.sdtContainerStart = String(config.isStart);
24180
- container.dataset.sdtContainerEnd = String(config.isEnd);
24181
- container.style.overflow = "visible";
24182
- const labelEl = doc2.createElement("div");
24183
- labelEl.className = config.labelClassName;
24184
- const labelText = doc2.createElement("span");
24185
- labelText.textContent = config.labelText;
24186
- labelEl.appendChild(labelText);
24187
- container.appendChild(labelEl);
24188
- }
24189
24365
  const renderTableFragment = (deps) => {
24190
24366
  const {
24191
24367
  doc: doc2,
@@ -24329,6 +24505,7 @@ const renderTableFragment = (deps) => {
24329
24505
  renderLine,
24330
24506
  renderDrawingContent,
24331
24507
  applySdtDataset,
24508
+ tableSdt: block.attrs?.sdt ?? null,
24332
24509
  // Headers are always rendered as-is (no border suppression)
24333
24510
  continuesFromPrev: false,
24334
24511
  continuesOnNext: false
@@ -24359,6 +24536,7 @@ const renderTableFragment = (deps) => {
24359
24536
  renderLine,
24360
24537
  renderDrawingContent,
24361
24538
  applySdtDataset,
24539
+ tableSdt: block.attrs?.sdt ?? null,
24362
24540
  // Draw top border if table continues from previous fragment (MS Word behavior)
24363
24541
  continuesFromPrev: isFirstRenderedBodyRow && fragment.continuesFromPrev === true,
24364
24542
  // Draw bottom border if table continues on next fragment (MS Word behavior)
@@ -25610,8 +25788,10 @@ class DomPainter {
25610
25788
  section: "body",
25611
25789
  pageNumberText: page.numberText
25612
25790
  };
25613
- page.fragments.forEach((fragment) => {
25614
- el.appendChild(this.renderFragment(fragment, contextBase));
25791
+ const sdtBoundaries = computeSdtBoundaries(page.fragments, this.blockLookup);
25792
+ page.fragments.forEach((fragment, index2) => {
25793
+ const sdtBoundary = sdtBoundaries.get(index2);
25794
+ el.appendChild(this.renderFragment(fragment, contextBase, sdtBoundary));
25615
25795
  });
25616
25796
  this.renderDecorationsForPage(el, page);
25617
25797
  return el;
@@ -25842,6 +26022,7 @@ class DomPainter {
25842
26022
  pageEl.dataset.layoutEpoch = String(this.layoutEpoch);
25843
26023
  const existing = new Map(state.fragments.map((frag) => [frag.key, frag]));
25844
26024
  const nextFragments = [];
26025
+ const sdtBoundaries = computeSdtBoundaries(page.fragments, this.blockLookup);
25845
26026
  const contextBase = {
25846
26027
  pageNumber: page.number,
25847
26028
  totalPages: this.totalPages,
@@ -25851,11 +26032,13 @@ class DomPainter {
25851
26032
  page.fragments.forEach((fragment, index2) => {
25852
26033
  const key2 = fragmentKey(fragment);
25853
26034
  const current = existing.get(key2);
26035
+ const sdtBoundary = sdtBoundaries.get(index2);
25854
26036
  if (current) {
25855
26037
  existing.delete(key2);
25856
- const needsRebuild = this.changedBlocks.has(fragment.blockId) || current.signature !== fragmentSignature(fragment, this.blockLookup);
26038
+ const sdtBoundaryMismatch = shouldRebuildForSdtBoundary(current.element, sdtBoundary);
26039
+ const needsRebuild = this.changedBlocks.has(fragment.blockId) || current.signature !== fragmentSignature(fragment, this.blockLookup) || sdtBoundaryMismatch;
25857
26040
  if (needsRebuild) {
25858
- const replacement = this.renderFragment(fragment, contextBase);
26041
+ const replacement = this.renderFragment(fragment, contextBase, sdtBoundary);
25859
26042
  pageEl.replaceChild(replacement, current.element);
25860
26043
  current.element = replacement;
25861
26044
  current.signature = fragmentSignature(fragment, this.blockLookup);
@@ -25869,7 +26052,7 @@ class DomPainter {
25869
26052
  nextFragments.push(current);
25870
26053
  return;
25871
26054
  }
25872
- const fresh = this.renderFragment(fragment, contextBase);
26055
+ const fresh = this.renderFragment(fragment, contextBase, sdtBoundary);
25873
26056
  pageEl.insertBefore(fresh, pageEl.children[index2] ?? null);
25874
26057
  nextFragments.push({
25875
26058
  key: key2,
@@ -25941,8 +26124,10 @@ class DomPainter {
25941
26124
  totalPages: this.totalPages,
25942
26125
  section: "body"
25943
26126
  };
25944
- const fragments = page.fragments.map((fragment) => {
25945
- const fragmentEl = this.renderFragment(fragment, contextBase);
26127
+ const sdtBoundaries = computeSdtBoundaries(page.fragments, this.blockLookup);
26128
+ const fragments = page.fragments.map((fragment, index2) => {
26129
+ const sdtBoundary = sdtBoundaries.get(index2);
26130
+ const fragmentEl = this.renderFragment(fragment, contextBase, sdtBoundary);
25946
26131
  el.appendChild(fragmentEl);
25947
26132
  return {
25948
26133
  key: fragmentKey(fragment),
@@ -25962,12 +26147,12 @@ class DomPainter {
25962
26147
  }
25963
26148
  return this.options.pageStyles;
25964
26149
  }
25965
- renderFragment(fragment, context) {
26150
+ renderFragment(fragment, context, sdtBoundary) {
25966
26151
  if (fragment.kind === "para") {
25967
- return this.renderParagraphFragment(fragment, context);
26152
+ return this.renderParagraphFragment(fragment, context, sdtBoundary);
25968
26153
  }
25969
26154
  if (fragment.kind === "list-item") {
25970
- return this.renderListItemFragment(fragment, context);
26155
+ return this.renderListItemFragment(fragment, context, sdtBoundary);
25971
26156
  }
25972
26157
  if (fragment.kind === "image") {
25973
26158
  return this.renderImageFragment(fragment, context);
@@ -25986,9 +26171,10 @@ class DomPainter {
25986
26171
  *
25987
26172
  * @param fragment - The paragraph fragment to render
25988
26173
  * @param context - Rendering context with page and column information
26174
+ * @param sdtBoundary - Optional SDT boundary overrides for multi-fragment containers
25989
26175
  * @returns HTMLElement containing the rendered fragment or error placeholder
25990
26176
  */
25991
- renderParagraphFragment(fragment, context) {
26177
+ renderParagraphFragment(fragment, context, sdtBoundary) {
25992
26178
  try {
25993
26179
  const lookup = this.blockLookup.get(fragment.blockId);
25994
26180
  if (!lookup || lookup.block.kind !== "paragraph" || lookup.measure.kind !== "paragraph") {
@@ -26035,7 +26221,7 @@ class DomPainter {
26035
26221
  }
26036
26222
  this.applySdtDataset(fragmentEl, block.attrs?.sdt);
26037
26223
  this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
26038
- applySdtContainerStyling(this.doc, fragmentEl, block.attrs?.sdt, block.attrs?.containerSdt);
26224
+ applySdtContainerStyling(this.doc, fragmentEl, block.attrs?.sdt, block.attrs?.containerSdt, sdtBoundary);
26039
26225
  const dropCapDescriptor = block.attrs?.dropCapDescriptor;
26040
26226
  const dropCapMeasure = measure.dropCap;
26041
26227
  if (dropCapDescriptor && dropCapMeasure && !fragment.continuesFromPrev) {
@@ -26349,7 +26535,7 @@ class DomPainter {
26349
26535
  }
26350
26536
  return dropCapEl;
26351
26537
  }
26352
- renderListItemFragment(fragment, context) {
26538
+ renderListItemFragment(fragment, context, sdtBoundary) {
26353
26539
  try {
26354
26540
  const lookup = this.blockLookup.get(fragment.blockId);
26355
26541
  if (!lookup || lookup.block.kind !== "list" || lookup.measure.kind !== "list") {
@@ -26375,7 +26561,13 @@ class DomPainter {
26375
26561
  fragmentEl.dataset.itemId = fragment.itemId;
26376
26562
  const paragraphMetadata = item.paragraph.attrs?.sdt;
26377
26563
  this.applySdtDataset(fragmentEl, paragraphMetadata);
26378
- applySdtContainerStyling(this.doc, fragmentEl, paragraphMetadata, item.paragraph.attrs?.containerSdt);
26564
+ applySdtContainerStyling(
26565
+ this.doc,
26566
+ fragmentEl,
26567
+ paragraphMetadata,
26568
+ item.paragraph.attrs?.containerSdt,
26569
+ sdtBoundary
26570
+ );
26379
26571
  if (fragment.continuesFromPrev) {
26380
26572
  fragmentEl.dataset.continuesFromPrev = "true";
26381
26573
  }
@@ -28305,6 +28497,46 @@ class DomPainter {
28305
28497
  }
28306
28498
  }
28307
28499
  }
28500
+ const getFragmentSdtContainerKey = (fragment, blockLookup) => {
28501
+ const lookup = blockLookup.get(fragment.blockId);
28502
+ if (!lookup) return null;
28503
+ const block = lookup.block;
28504
+ if (fragment.kind === "para" && block.kind === "paragraph") {
28505
+ const attrs = block.attrs;
28506
+ return getSdtContainerKey(attrs?.sdt, attrs?.containerSdt);
28507
+ }
28508
+ if (fragment.kind === "list-item" && block.kind === "list") {
28509
+ const item = block.items.find((listItem) => listItem.id === fragment.itemId);
28510
+ const attrs = item?.paragraph.attrs;
28511
+ return getSdtContainerKey(attrs?.sdt, attrs?.containerSdt);
28512
+ }
28513
+ return null;
28514
+ };
28515
+ const computeSdtBoundaries = (fragments, blockLookup) => {
28516
+ const boundaries = /* @__PURE__ */ new Map();
28517
+ const containerKeys = fragments.map((fragment) => getFragmentSdtContainerKey(fragment, blockLookup));
28518
+ for (let i = 0; i < fragments.length; i += 1) {
28519
+ const currentKey = containerKeys[i];
28520
+ if (!currentKey) continue;
28521
+ const prev = i > 0 ? containerKeys[i - 1] : null;
28522
+ const next = i < fragments.length - 1 ? containerKeys[i + 1] : null;
28523
+ const isStart = currentKey !== prev;
28524
+ const isEnd = currentKey !== next;
28525
+ boundaries.set(i, { isStart, isEnd });
28526
+ }
28527
+ return boundaries;
28528
+ };
28529
+ const shouldRebuildForSdtBoundary = (element, boundary) => {
28530
+ if (!boundary) return false;
28531
+ const startAttr = element.dataset.sdtContainerStart;
28532
+ const endAttr = element.dataset.sdtContainerEnd;
28533
+ const expectedStart = String(boundary.isStart ?? true);
28534
+ const expectedEnd = String(boundary.isEnd ?? true);
28535
+ if (startAttr === void 0 || endAttr === void 0) {
28536
+ return true;
28537
+ }
28538
+ return startAttr !== expectedStart || endAttr !== expectedEnd;
28539
+ };
28308
28540
  const fragmentKey = (fragment) => {
28309
28541
  if (fragment.kind === "para") {
28310
28542
  return `para:${fragment.blockId}:${fragment.fromLine}:${fragment.toLine}`;
@@ -41716,16 +41948,6 @@ function tokenNodeToRun(node, positions, defaultFont, defaultSize, inheritedMark
41716
41948
  if (marksAsAttrs.length > 0) {
41717
41949
  run._explicitFont = true;
41718
41950
  }
41719
- console.debug("[token-debug] tokenNodeToRun", {
41720
- token,
41721
- fontFamily: run.fontFamily,
41722
- fontSize: run.fontSize,
41723
- defaultFont,
41724
- defaultSize,
41725
- nodeMarksCount: nodeMarks.length,
41726
- marksAsAttrsCount: marksAsAttrs.length,
41727
- inheritedMarksCount: inheritedMarks?.length ?? 0
41728
- });
41729
41951
  return run;
41730
41952
  }
41731
41953
  const EIGHTHS_PER_POINT = 8;
@@ -44121,6 +44343,16 @@ function applySdtMetadataToTableBlock(tableBlock, metadata) {
44121
44343
  table.attrs.sdt = metadata;
44122
44344
  table.rows?.forEach((row) => {
44123
44345
  row.cells?.forEach((cell) => {
44346
+ const cellBlocks = cell.blocks;
44347
+ if (cellBlocks && cellBlocks.length > 0) {
44348
+ applySdtMetadataToParagraphBlocks(cellBlocks, metadata);
44349
+ cellBlocks.forEach((block) => {
44350
+ if (block.kind === "table") {
44351
+ applySdtMetadataToTableBlock(block, metadata);
44352
+ }
44353
+ });
44354
+ return;
44355
+ }
44124
44356
  if (cell.paragraph) {
44125
44357
  applySdtMetadataToParagraphBlocks([cell.paragraph], metadata);
44126
44358
  }
@@ -45635,14 +45867,6 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
45635
45867
  enableComments
45636
45868
  );
45637
45869
  }
45638
- console.debug("[token-debug] paragraph-token-run", {
45639
- token: tokenRun.token,
45640
- fontFamily: tokenRun.fontFamily,
45641
- fontSize: tokenRun.fontSize,
45642
- inlineStyleId,
45643
- runStyleId: activeRunStyleId,
45644
- mergedMarksCount: mergedMarks.length
45645
- });
45646
45870
  applyInlineRunProperties(tokenRun, activeRunProperties);
45647
45871
  currentRuns.push(tokenRun);
45648
45872
  }
@@ -46298,7 +46522,19 @@ const parseTableCell = (args) => {
46298
46522
  ...cellBackgroundColor && { backgroundColor: cellBackgroundColor }
46299
46523
  } : context.converterContext;
46300
46524
  const paragraphToFlowBlocks2 = context.converters?.paragraphToFlowBlocks ?? context.paragraphToFlowBlocks;
46525
+ const tableNodeToBlock2 = context.converters?.tableNodeToBlock;
46301
46526
  const listCounterContext = context.listCounterContext;
46527
+ const appendParagraphBlocks = (paragraphBlocks, sdtMetadata) => {
46528
+ applySdtMetadataToParagraphBlocks(
46529
+ paragraphBlocks.filter((block) => block.kind === "paragraph"),
46530
+ sdtMetadata
46531
+ );
46532
+ paragraphBlocks.forEach((block) => {
46533
+ if (block.kind === "paragraph" || block.kind === "image" || block.kind === "drawing") {
46534
+ blocks.push(block);
46535
+ }
46536
+ });
46537
+ };
46302
46538
  for (const childNode of cellNode.content) {
46303
46539
  if (childNode.type === "paragraph") {
46304
46540
  if (!paragraphToFlowBlocks2) continue;
@@ -46316,11 +46552,75 @@ const parseTableCell = (args) => {
46316
46552
  context.themeColors,
46317
46553
  cellConverterContext
46318
46554
  );
46319
- paragraphBlocks.forEach((block) => {
46320
- if (block.kind === "paragraph" || block.kind === "image" || block.kind === "drawing") {
46321
- blocks.push(block);
46555
+ appendParagraphBlocks(paragraphBlocks);
46556
+ continue;
46557
+ }
46558
+ if (childNode.type === "structuredContentBlock" && Array.isArray(childNode.content)) {
46559
+ const structuredContentMetadata = resolveNodeSdtMetadata(childNode, "structuredContentBlock");
46560
+ for (const nestedNode of childNode.content) {
46561
+ if (nestedNode.type === "paragraph") {
46562
+ if (!paragraphToFlowBlocks2) continue;
46563
+ const paragraphBlocks = paragraphToFlowBlocks2(
46564
+ nestedNode,
46565
+ context.nextBlockId,
46566
+ context.positions,
46567
+ context.defaultFont,
46568
+ context.defaultSize,
46569
+ context.styleContext,
46570
+ listCounterContext,
46571
+ context.trackedChanges,
46572
+ context.bookmarks,
46573
+ context.hyperlinkConfig,
46574
+ context.themeColors,
46575
+ cellConverterContext
46576
+ );
46577
+ appendParagraphBlocks(paragraphBlocks, structuredContentMetadata);
46578
+ continue;
46322
46579
  }
46323
- });
46580
+ if (nestedNode.type === "table" && tableNodeToBlock2) {
46581
+ const tableBlock = tableNodeToBlock2(
46582
+ nestedNode,
46583
+ context.nextBlockId,
46584
+ context.positions,
46585
+ context.defaultFont,
46586
+ context.defaultSize,
46587
+ context.styleContext,
46588
+ context.trackedChanges,
46589
+ context.bookmarks,
46590
+ context.hyperlinkConfig,
46591
+ context.themeColors,
46592
+ paragraphToFlowBlocks2,
46593
+ context.converterContext,
46594
+ { listCounterContext, converters: context.converters }
46595
+ );
46596
+ if (tableBlock && tableBlock.kind === "table") {
46597
+ applySdtMetadataToTableBlock(tableBlock, structuredContentMetadata);
46598
+ blocks.push(tableBlock);
46599
+ }
46600
+ continue;
46601
+ }
46602
+ }
46603
+ continue;
46604
+ }
46605
+ if (childNode.type === "table" && tableNodeToBlock2) {
46606
+ const tableBlock = tableNodeToBlock2(
46607
+ childNode,
46608
+ context.nextBlockId,
46609
+ context.positions,
46610
+ context.defaultFont,
46611
+ context.defaultSize,
46612
+ context.styleContext,
46613
+ context.trackedChanges,
46614
+ context.bookmarks,
46615
+ context.hyperlinkConfig,
46616
+ context.themeColors,
46617
+ paragraphToFlowBlocks2,
46618
+ context.converterContext,
46619
+ { listCounterContext, converters: context.converters }
46620
+ );
46621
+ if (tableBlock && tableBlock.kind === "table") {
46622
+ blocks.push(tableBlock);
46623
+ }
46324
46624
  continue;
46325
46625
  }
46326
46626
  if (childNode.type === "image" && context.converters?.imageNodeToBlock) {
@@ -46384,6 +46684,7 @@ const parseTableCell = (args) => {
46384
46684
  if (drawingBlock && drawingBlock.kind === "drawing") {
46385
46685
  blocks.push(drawingBlock);
46386
46686
  }
46687
+ continue;
46387
46688
  }
46388
46689
  }
46389
46690
  if (blocks.length === 0) {
@@ -51927,6 +52228,39 @@ class PresentationEditor extends EventEmitter {
51927
52228
  height: rect.height
51928
52229
  };
51929
52230
  }
52231
+ /**
52232
+ * Get the painted DOM element that contains a document position (body only).
52233
+ *
52234
+ * Uses the DomPositionIndex which maps data-pm-start/end attributes to rendered
52235
+ * elements. Returns null when the position is not currently mounted (virtualization)
52236
+ * or when in header/footer mode.
52237
+ *
52238
+ * @param pos - Document position in the active editor
52239
+ * @param options.forceRebuild - Rebuild the index before lookup
52240
+ * @param options.fallbackToCoords - Use elementFromPoint with layout rects if index lookup fails
52241
+ * @returns The nearest painted DOM element for the position, or null if unavailable
52242
+ */
52243
+ getElementAtPos(pos, options = {}) {
52244
+ if (!Number.isFinite(pos)) return null;
52245
+ if (!this.#painterHost) return null;
52246
+ if (this.#session.mode !== "body") return null;
52247
+ if (options.forceRebuild || this.#domPositionIndex.size === 0) {
52248
+ this.#rebuildDomPositionIndex();
52249
+ }
52250
+ const indexed = this.#domPositionIndex.findElementAtPosition(pos);
52251
+ if (indexed) return indexed;
52252
+ if (!options.fallbackToCoords) return null;
52253
+ const rects = this.getRangeRects(pos, pos);
52254
+ if (!rects.length) return null;
52255
+ const doc2 = this.#visibleHost.ownerDocument ?? document;
52256
+ for (const rect of rects) {
52257
+ const el = doc2.elementFromPoint(rect.left + rect.width / 2, rect.top + rect.height / 2);
52258
+ if (el instanceof HTMLElement && this.#painterHost.contains(el)) {
52259
+ return el.closest("[data-pm-start][data-pm-end]") ?? el;
52260
+ }
52261
+ }
52262
+ return null;
52263
+ }
51930
52264
  /**
51931
52265
  * Scroll the visible host so a given document position is brought into view.
51932
52266
  *