superdoc 1.0.0-beta.2 → 1.0.0-beta.4

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.
Files changed (34) hide show
  1. package/dist/chunks/{PdfViewer-saAhozRR.es.js → PdfViewer-DUns3s8O.es.js} +2 -2
  2. package/dist/chunks/{PdfViewer-CeuX3gOe.cjs → PdfViewer-ZtwLhE_8.cjs} +1 -1
  3. package/dist/chunks/{eventemitter3-BZXKb7j7.es.js → eventemitter3-ByBH0NYV.es.js} +1 -1
  4. package/dist/chunks/{index-Sn-JVHIg-BCItIT88.es.js → index-BNGaD3Up-CQuoo1EF.es.js} +1 -1
  5. package/dist/chunks/{index-Sn-JVHIg-BxOp3gSx.cjs → index-BNGaD3Up-D2cRHMMk.cjs} +1 -1
  6. package/dist/chunks/{index-Dh5oVJua.cjs → index-BW38mdZF.cjs} +3 -3
  7. package/dist/chunks/{index-C0OeGje6.es.js → index-DIccWgYh.es.js} +6 -6
  8. package/dist/chunks/{jszip-Duxs2YMV.es.js → jszip-BwsONqK5.es.js} +1 -1
  9. package/dist/chunks/{super-editor.es-BKljkYUU.cjs → super-editor.es-C06-V-Iy.cjs} +736 -215
  10. package/dist/chunks/{super-editor.es-Dcz39nKY.es.js → super-editor.es-CtCHBIPE.es.js} +737 -216
  11. package/dist/chunks/{vue-B5QAf5pA.es.js → vue-CztqUvm1.es.js} +17 -17
  12. package/dist/chunks/xml-js-BZPSMmVo.es.js +2 -0
  13. package/dist/packages/superdoc/src/core/SuperDoc.d.ts +35 -2
  14. package/dist/packages/superdoc/src/core/SuperDoc.d.ts.map +1 -1
  15. package/dist/super-editor/ai-writer.es.js +2 -2
  16. package/dist/super-editor/chunks/{converter-BFGB7hqj.js → converter-ZJiSHoiq.js} +1 -1
  17. package/dist/super-editor/chunks/{docx-zipper-OPbzIk16.js → docx-zipper-B7FStorN.js} +1 -1
  18. package/dist/super-editor/chunks/{editor-CtI4XnMw.js → editor-DvepAjbe.js} +553 -181
  19. package/dist/super-editor/chunks/{index-Sn-JVHIg.js → index-BNGaD3Up.js} +1 -1
  20. package/dist/super-editor/chunks/{toolbar-BydALv4o.js → toolbar-CKXXbIQO.js} +2 -2
  21. package/dist/super-editor/converter.es.js +1 -1
  22. package/dist/super-editor/docx-zipper.es.js +2 -2
  23. package/dist/super-editor/editor.es.js +3 -3
  24. package/dist/super-editor/file-zipper.es.js +1 -1
  25. package/dist/super-editor/super-editor.es.js +217 -41
  26. package/dist/super-editor/toolbar.es.js +2 -2
  27. package/dist/super-editor.cjs +1 -1
  28. package/dist/super-editor.es.js +2 -2
  29. package/dist/superdoc.cjs +2 -2
  30. package/dist/superdoc.es.js +2 -2
  31. package/dist/superdoc.umd.js +738 -217
  32. package/dist/superdoc.umd.js.map +1 -1
  33. package/package.json +1 -1
  34. package/dist/chunks/xml-js-CVyfrKaV.es.js +0 -2
@@ -35581,7 +35581,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
35581
35581
  static getStoredSuperdocVersion(docx) {
35582
35582
  return _SuperConverter2.getStoredCustomProperty(docx, "SuperdocVersion");
35583
35583
  }
35584
- static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.2") {
35584
+ static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.4") {
35585
35585
  return _SuperConverter2.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
35586
35586
  }
35587
35587
  /**
@@ -46562,7 +46562,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
46562
46562
  var __privateAdd$1 = (obj, member, value) => member.has(obj) ? __typeError$1("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
46563
46563
  var __privateSet = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
46564
46564
  var __privateMethod$1 = (obj, member, method) => (__accessCheck$1(obj, member, "access private method"), method);
46565
- var _Attribute_static, getGlobalAttributes_fn, getNodeAndMarksAttributes_fn, _Schema_static, createNodesSchema_fn, createMarksSchema_fn, _events, _ExtensionService_instances, setupExtensions_fn, attachEditorEvents_fn, _editor, _stateValidators, _xmlValidators, _requiredNodeTypes, _requiredMarkTypes, _SuperValidator_instances, initializeValidators_fn, collectValidatorRequirements_fn, analyzeDocument_fn, dispatchWithFallback_fn, _commandService, _Editor_instances, initContainerElement_fn, init_fn, initRichText_fn, onFocus_fn, checkHeadless_fn, registerCopyHandler_fn, insertNewFileData_fn, getPluginKeyName_fn, createExtensionService_fn, createCommandService_fn, createConverter_fn, initMedia_fn, initFonts_fn, checkFonts_fn, determineUnsupportedFonts_fn, createSchema_fn, generatePmData_fn, createView_fn, onCollaborationReady_fn, initComments_fn, dispatchTransaction_fn, handleNodeSelection_fn, prepareDocumentForImport_fn, prepareDocumentForExport_fn, endCollaboration_fn, validateDocumentInit_fn, validateDocumentExport_fn, initDevTools_fn, _map, _editor2, _descriptors, _collections, _editorEntries, _maxCachedEditors, _editorAccessOrder, _pendingCreations, _cacheHits, _cacheMisses, _evictions, _HeaderFooterEditorManager_instances, hasConverter_fn, extractCollections_fn, collectDescriptors_fn, teardownMissingEditors_fn, teardownEditors_fn, createEditor_fn, createEditorContainer_fn, registerConverterEditor_fn, unregisterConverterEditor_fn, updateAccessOrder_fn, enforceCacheSizeLimit_fn, _manager, _mediaFiles, _blockCache, _HeaderFooterLayoutAdapter_instances, getBlocks_fn, getConverterContext_fn, _instances, _options, _editor3, _visibleHost, _viewportHost, _painterHost, _selectionOverlay, _hiddenHost, _layoutOptions, _layoutState, _domPainter, _layoutError, _layoutErrorState, _errorBanner, _errorBannerMessage, _telemetryEmitter, _renderScheduled, _pendingDocChange, _isRerendering, _selectionUpdateScheduled, _remoteCursorUpdateScheduled, _rafHandle, _editorListeners, _sectionMetadata, _documentMode, _inputBridge, _trackedChangesMode, _trackedChangesEnabled, _trackedChangesOverrides, _headerFooterManager, _headerFooterAdapter, _headerFooterIdentifier, _headerLayoutResults, _footerLayoutResults, _headerDecorationProvider, _footerDecorationProvider, _headerFooterManagerCleanups, _headerRegions, _footerRegions, _session, _activeHeaderFooterEditor, _hoverOverlay, _hoverTooltip, _modeBanner, _ariaLiveRegion, _hoverRegion, _clickCount, _lastClickTime, _lastClickPosition, _remoteCursorState, _remoteCursorDirty, _remoteCursorOverlay, _localSelectionLayer, _awarenessCleanup, _scrollCleanup, _remoteCursorRafHandle, _scrollTimeout, _PresentationEditor_instances, aggregateLayoutBounds_fn, safeCleanup_fn, setupEditorListeners_fn, setupCollaborationCursors_fn, normalizeAwarenessStates_fn, getFallbackColor_fn, getValidatedColor_fn, scheduleRemoteCursorUpdate_fn, scheduleRemoteCursorReRender_fn, updateRemoteCursors_fn, renderRemoteCursors_fn, renderRemoteCaret_fn, renderRemoteCursorLabel_fn, renderRemoteSelection_fn, setupPointerHandlers_fn, setupInputBridge_fn, initHeaderFooterRegistry_fn, _handlePointerDown, getFirstTextPosition_fn, registerPointerClick_fn, selectWordAt_fn, selectParagraphAt_fn, isWordCharacter_fn, _handlePointerMove, _handlePointerLeave, _handleDoubleClick, _handleKeyDown, focusHeaderFooterShortcut_fn, scheduleRerender_fn, flushRerenderQueue_fn, rerender_fn, ensurePainter_fn, scheduleSelectionUpdate_fn, updateSelection_fn, resolveLayoutOptions_fn, buildHeaderFooterInput_fn, computeHeaderFooterConstraints_fn, updateDecorationProviders_fn, createDecorationProvider_fn, computeDecorationBox_fn, rebuildHeaderFooterRegions_fn, hitTestHeaderFooterRegion_fn, pointInRegion_fn, activateHeaderFooterRegion_fn, enterHeaderFooterMode_fn, exitHeaderFooterMode_fn, getActiveDomTarget_fn, emitHeaderFooterModeChanged_fn, emitHeaderFooterEditingContext_fn, updateAwarenessSession_fn, updateModeBanner_fn, announce_fn, validateHeaderFooterEditPermission_fn, emitHeaderFooterEditBlocked_fn, resolveDescriptorForRegion_fn, getBodyPageHeight_fn, getHeaderFooterPageHeight_fn, renderSelectionRects_fn, renderHoverRegion_fn, clearHoverRegion_fn, renderCaretOverlay_fn, getHeaderFooterContext_fn, computeHeaderFooterSelectionRects_fn, computeHeaderFooterCaretRect_fn, syncTrackedChangesPreferences_fn, deriveTrackedChangesMode_fn, deriveTrackedChangesEnabled_fn, getTrackChangesPluginState_fn, computeDefaultLayoutDefaults_fn, parseColumns_fn, inchesToPx_fn, applyZoom_fn, createLayoutMetrics_fn, convertPageLocalToOverlayCoords_fn, normalizeClientPoint_fn, computeCaretLayoutRect_fn, findLineContainingPos_fn, lineHeightBeforeIndex_fn, getCurrentPageIndex_fn, findRegionForPage_fn, handleLayoutError_fn, decorateError_fn, showLayoutErrorBanner_fn, dismissErrorBanner_fn, createHiddenHost_fn, _windowRoot, _visibleHost2, _getTargetDom, _onTargetChanged, _listeners, _currentTarget, _PresentationInputBridge_instances, addListener_fn, dispatchToTarget_fn, forwardKeyboardEvent_fn, forwardTextEvent_fn, forwardCompositionEvent_fn, forwardContextMenu_fn, isEventOnActiveTarget_fn, _DocumentSectionView_instances, init_fn2, addToolTip_fn, _ParagraphNodeView_instances, updateHTMLAttributes_fn, updateDOMStyles_fn, updateListStyles_fn, initList_fn, checkIsList_fn, createMarker_fn, createSeparator_fn, calculateTabSeparatorStyle_fn, calculateMarkerStyle_fn, removeList_fn, getParagraphContext_fn, scheduleAnimation_fn, cancelScheduledAnimation_fn, _FieldAnnotationView_instances, createAnnotation_fn, _AutoPageNumberNodeView_instances, renderDom_fn, scheduleUpdateNodeStyle_fn;
46565
+ var _Attribute_static, getGlobalAttributes_fn, getNodeAndMarksAttributes_fn, _Schema_static, createNodesSchema_fn, createMarksSchema_fn, _events, _ExtensionService_instances, setupExtensions_fn, attachEditorEvents_fn, _editor, _stateValidators, _xmlValidators, _requiredNodeTypes, _requiredMarkTypes, _SuperValidator_instances, initializeValidators_fn, collectValidatorRequirements_fn, analyzeDocument_fn, dispatchWithFallback_fn, _commandService, _Editor_instances, initContainerElement_fn, init_fn, initRichText_fn, onFocus_fn, checkHeadless_fn, registerCopyHandler_fn, insertNewFileData_fn, getPluginKeyName_fn, createExtensionService_fn, createCommandService_fn, createConverter_fn, initMedia_fn, initFonts_fn, checkFonts_fn, determineUnsupportedFonts_fn, createSchema_fn, generatePmData_fn, createView_fn, onCollaborationReady_fn, initComments_fn, dispatchTransaction_fn, handleNodeSelection_fn, prepareDocumentForImport_fn, prepareDocumentForExport_fn, endCollaboration_fn, validateDocumentInit_fn, validateDocumentExport_fn, initDevTools_fn, _map, _editor2, _descriptors, _collections, _editorEntries, _maxCachedEditors, _editorAccessOrder, _pendingCreations, _cacheHits, _cacheMisses, _evictions, _HeaderFooterEditorManager_instances, hasConverter_fn, extractCollections_fn, collectDescriptors_fn, teardownMissingEditors_fn, teardownEditors_fn, createEditor_fn, createEditorContainer_fn, registerConverterEditor_fn, unregisterConverterEditor_fn, updateAccessOrder_fn, enforceCacheSizeLimit_fn, _manager, _mediaFiles, _blockCache, _HeaderFooterLayoutAdapter_instances, getBlocks_fn, getConverterContext_fn, _instances, _options, _editor3, _visibleHost, _viewportHost, _painterHost, _selectionOverlay, _hiddenHost, _layoutOptions, _layoutState, _domPainter, _layoutError, _layoutErrorState, _errorBanner, _errorBannerMessage, _telemetryEmitter, _renderScheduled, _pendingDocChange, _isRerendering, _selectionUpdateScheduled, _remoteCursorUpdateScheduled, _rafHandle, _editorListeners, _sectionMetadata, _documentMode, _inputBridge, _trackedChangesMode, _trackedChangesEnabled, _trackedChangesOverrides, _headerFooterManager, _headerFooterAdapter, _headerFooterIdentifier, _headerLayoutResults, _footerLayoutResults, _headerDecorationProvider, _footerDecorationProvider, _headerFooterManagerCleanups, _headerRegions, _footerRegions, _session, _activeHeaderFooterEditor, _hoverOverlay, _hoverTooltip, _modeBanner, _ariaLiveRegion, _hoverRegion, _clickCount, _lastClickTime, _lastClickPosition, _remoteCursorState, _remoteCursorDirty, _remoteCursorOverlay, _localSelectionLayer, _awarenessCleanup, _scrollCleanup, _remoteCursorRafHandle, _scrollTimeout, _PresentationEditor_instances, aggregateLayoutBounds_fn, safeCleanup_fn, setupEditorListeners_fn, setupCollaborationCursors_fn, normalizeAwarenessStates_fn, getFallbackColor_fn, getValidatedColor_fn, scheduleRemoteCursorUpdate_fn, scheduleRemoteCursorReRender_fn, updateRemoteCursors_fn, renderRemoteCursors_fn, renderRemoteCaret_fn, renderRemoteCursorLabel_fn, renderRemoteSelection_fn, setupPointerHandlers_fn, setupInputBridge_fn, initHeaderFooterRegistry_fn, _handlePointerDown, getFirstTextPosition_fn, registerPointerClick_fn, selectWordAt_fn, selectParagraphAt_fn, isWordCharacter_fn, _handlePointerMove, _handlePointerLeave, _handleDoubleClick, _handleKeyDown, focusHeaderFooterShortcut_fn, scheduleRerender_fn, flushRerenderQueue_fn, rerender_fn, ensurePainter_fn, scheduleSelectionUpdate_fn, updateSelection_fn, resolveLayoutOptions_fn, buildHeaderFooterInput_fn, computeHeaderFooterConstraints_fn, updateDecorationProviders_fn, createDecorationProvider_fn, computeDecorationBox_fn, rebuildHeaderFooterRegions_fn, hitTestHeaderFooterRegion_fn, pointInRegion_fn, activateHeaderFooterRegion_fn, enterHeaderFooterMode_fn, exitHeaderFooterMode_fn, getActiveDomTarget_fn, emitHeaderFooterModeChanged_fn, emitHeaderFooterEditingContext_fn, updateAwarenessSession_fn, updateModeBanner_fn, announce_fn, validateHeaderFooterEditPermission_fn, emitHeaderFooterEditBlocked_fn, resolveDescriptorForRegion_fn, getBodyPageHeight_fn, getHeaderFooterPageHeight_fn, renderSelectionRects_fn, renderHoverRegion_fn, clearHoverRegion_fn, renderCaretOverlay_fn, getHeaderFooterContext_fn, computeHeaderFooterSelectionRects_fn, computeHeaderFooterCaretRect_fn, syncTrackedChangesPreferences_fn, deriveTrackedChangesMode_fn, deriveTrackedChangesEnabled_fn, getTrackChangesPluginState_fn, computeDefaultLayoutDefaults_fn, parseColumns_fn, inchesToPx_fn, applyZoom_fn, createLayoutMetrics_fn, convertPageLocalToOverlayCoords_fn, normalizeClientPoint_fn, computeCaretLayoutRect_fn, findLineContainingPos_fn, lineHeightBeforeIndex_fn, getCurrentPageIndex_fn, findRegionForPage_fn, handleLayoutError_fn, decorateError_fn, showLayoutErrorBanner_fn, dismissErrorBanner_fn, createHiddenHost_fn, _windowRoot, _visibleHost2, _getTargetDom, _onTargetChanged, _listeners, _currentTarget, _destroyed, _PresentationInputBridge_instances, addListener_fn, dispatchToTarget_fn, forwardKeyboardEvent_fn, forwardTextEvent_fn, forwardCompositionEvent_fn, forwardContextMenu_fn, isEventOnActiveTarget_fn, _DocumentSectionView_instances, init_fn2, addToolTip_fn, _ParagraphNodeView_instances, updateHTMLAttributes_fn, updateDOMStyles_fn, updateListStyles_fn, initList_fn, checkIsList_fn, createMarker_fn, createSeparator_fn, calculateTabSeparatorStyle_fn, calculateMarkerStyle_fn, removeList_fn, getParagraphContext_fn, scheduleAnimation_fn, cancelScheduledAnimation_fn, _FieldAnnotationView_instances, createAnnotation_fn, _AutoPageNumberNodeView_instances, renderDom_fn, scheduleUpdateNodeStyle_fn;
46566
46566
  var GOOD_LEAF_SIZE = 200;
46567
46567
  var RopeSequence = function RopeSequence2() {
46568
46568
  };
@@ -60069,7 +60069,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
60069
60069
  const shouldSkipNodeView = (editor) => {
60070
60070
  return isHeadless(editor);
60071
60071
  };
60072
- const summaryVersion = "1.0.0-beta.2";
60072
+ const summaryVersion = "1.0.0-beta.4";
60073
60073
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
60074
60074
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
60075
60075
  function mapAttributes(attrs) {
@@ -60848,7 +60848,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
60848
60848
  { default: remarkStringify2 },
60849
60849
  { default: remarkGfm2 }
60850
60850
  ] = await Promise.all([
60851
- Promise.resolve().then(() => indexSnJVHIg),
60851
+ Promise.resolve().then(() => indexBNGaD3Up),
60852
60852
  Promise.resolve().then(() => indexDRCvimau),
60853
60853
  Promise.resolve().then(() => indexC_x_N6Uh),
60854
60854
  Promise.resolve().then(() => indexD_sWOSiG),
@@ -61053,7 +61053,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
61053
61053
  * Process collaboration migrations
61054
61054
  */
61055
61055
  processCollaborationMigrations() {
61056
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.2");
61056
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.4");
61057
61057
  if (!this.options.ydoc) return;
61058
61058
  const metaMap = this.options.ydoc.getMap("meta");
61059
61059
  let docVersion = metaMap.get("version");
@@ -62672,6 +62672,50 @@ Please report this to https://github.com/markedjs/marked.`, e) {
62672
62672
  }
62673
62673
  return void 0;
62674
62674
  };
62675
+ const MAX_DATA_ATTR_COUNT = 50;
62676
+ const MAX_DATA_ATTR_VALUE_LENGTH = 1e3;
62677
+ const MAX_DATA_ATTR_NAME_LENGTH = 100;
62678
+ const extractDataAttributes = (attrs) => {
62679
+ if (!attrs) return void 0;
62680
+ const result = {};
62681
+ let attrCount = 0;
62682
+ for (const [key2, value] of Object.entries(attrs)) {
62683
+ if (typeof key2 !== "string" || !key2.toLowerCase().startsWith("data-")) {
62684
+ continue;
62685
+ }
62686
+ if (attrCount >= MAX_DATA_ATTR_COUNT) {
62687
+ if (process$1$1.env.NODE_ENV === "development") {
62688
+ console.warn(`[PM-Adapter] Rejecting data attributes exceeding ${MAX_DATA_ATTR_COUNT} limit`);
62689
+ }
62690
+ break;
62691
+ }
62692
+ if (key2.length > MAX_DATA_ATTR_NAME_LENGTH) {
62693
+ if (process$1$1.env.NODE_ENV === "development") {
62694
+ console.warn(
62695
+ `[PM-Adapter] Rejecting data attribute name exceeding ${MAX_DATA_ATTR_NAME_LENGTH} chars: ${key2.substring(0, 50)}...`
62696
+ );
62697
+ }
62698
+ continue;
62699
+ }
62700
+ if (value == null) {
62701
+ continue;
62702
+ }
62703
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
62704
+ const stringValue = String(value);
62705
+ if (stringValue.length > MAX_DATA_ATTR_VALUE_LENGTH) {
62706
+ if (process$1$1.env.NODE_ENV === "development") {
62707
+ console.warn(
62708
+ `[PM-Adapter] Rejecting data attribute value exceeding ${MAX_DATA_ATTR_VALUE_LENGTH} chars for key: ${key2}`
62709
+ );
62710
+ }
62711
+ continue;
62712
+ }
62713
+ result[key2] = stringValue;
62714
+ attrCount++;
62715
+ }
62716
+ }
62717
+ return Object.keys(result).length > 0 ? result : void 0;
62718
+ };
62675
62719
  const normalizeRunMarkList = (value) => {
62676
62720
  if (!value) return void 0;
62677
62721
  let entries = value;
@@ -62840,6 +62884,19 @@ Please report this to https://github.com/markedjs/marked.`, e) {
62840
62884
  }
62841
62885
  return sanitized;
62842
62886
  };
62887
+ const normalizeFontSizePx = (value) => {
62888
+ if (isFiniteNumber(value)) return value;
62889
+ if (typeof value !== "string") return void 0;
62890
+ const trimmed = value.trim();
62891
+ if (!trimmed) return void 0;
62892
+ const numeric = Number.parseFloat(trimmed);
62893
+ if (!Number.isFinite(numeric)) return void 0;
62894
+ const unit = trimmed.match(/[a-zA-Z%]+$/)?.[0]?.toLowerCase();
62895
+ if (unit === "pt") {
62896
+ return ptToPx(numeric);
62897
+ }
62898
+ return numeric;
62899
+ };
62843
62900
  const applyTextStyleMark = (run2, attrs, themeColors) => {
62844
62901
  const resolvedColor = resolveColorFromAttributes(attrs, themeColors);
62845
62902
  if (resolvedColor) {
@@ -62851,11 +62908,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
62851
62908
  run2.fontFamily = sanitized;
62852
62909
  }
62853
62910
  }
62854
- if (isFiniteNumber(attrs.fontSize)) {
62855
- const size2 = Number(attrs.fontSize);
62856
- if (size2 >= 1 && size2 <= 1e3) {
62857
- run2.fontSize = size2;
62858
- }
62911
+ const fontSizePx = normalizeFontSizePx(attrs.fontSize);
62912
+ if (fontSizePx !== void 0 && fontSizePx >= 1 && fontSizePx <= 1e3) {
62913
+ run2.fontSize = fontSizePx;
62859
62914
  }
62860
62915
  if (isFiniteNumber(attrs.letterSpacing)) {
62861
62916
  const spacing = Number(attrs.letterSpacing);
@@ -62869,6 +62924,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
62869
62924
  };
62870
62925
  const applyMarksToRun = (run2, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG, themeColors) => {
62871
62926
  marks.forEach((mark2) => {
62927
+ const forwardedDataAttrs = extractDataAttributes(mark2.attrs);
62872
62928
  try {
62873
62929
  switch (mark2.type) {
62874
62930
  case TRACK_INSERT_MARK:
@@ -62963,6 +63019,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
62963
63019
  console.warn(`[PM-Adapter] Failed to apply mark ${mark2.type}:`, error);
62964
63020
  }
62965
63021
  }
63022
+ if (forwardedDataAttrs) {
63023
+ run2.dataAttrs = { ...run2.dataAttrs ?? {}, ...forwardedDataAttrs };
63024
+ }
62966
63025
  });
62967
63026
  };
62968
63027
  function textNodeToRun(textNode, positions, defaultFont, defaultSize, inheritedMarks = [], sdtMetadata, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors) {
@@ -62986,8 +63045,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
62986
63045
  const pos = positions.get(node2);
62987
63046
  if (!pos) return null;
62988
63047
  const paragraphAttrs = paragraph2.attrs ?? {};
62989
- const tabStops = Array.isArray(paragraphAttrs.tabStops) ? paragraphAttrs.tabStops : void 0;
62990
- const indent2 = paragraphAttrs.indent;
63048
+ const paragraphProps = typeof paragraphAttrs.paragraphProperties === "object" && paragraphAttrs.paragraphProperties !== null ? paragraphAttrs.paragraphProperties : {};
63049
+ const tabStops = Array.isArray(paragraphAttrs.tabStops) && paragraphAttrs.tabStops.length ? paragraphAttrs.tabStops : Array.isArray(paragraphProps.tabStops) ? paragraphProps.tabStops : void 0;
63050
+ const indent2 = paragraphAttrs.indent ?? paragraphProps.indent ?? void 0;
62991
63051
  return {
62992
63052
  kind: "tab",
62993
63053
  text: " ",
@@ -63301,6 +63361,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
63301
63361
  const afterRaw = pickNumber(source.after);
63302
63362
  const lineRaw = pickNumber(source.line);
63303
63363
  const lineRule = normalizeLineRule(source.lineRule);
63364
+ const beforeAutospacing = toBooleanFlag(source.beforeAutospacing ?? source.beforeAutoSpacing);
63365
+ const afterAutospacing = toBooleanFlag(source.afterAutospacing ?? source.afterAutoSpacing);
63366
+ const contextualSpacing = toBooleanFlag(source.contextualSpacing);
63304
63367
  const before = beforeRaw != null ? twipsToPx$1(beforeRaw) : pickNumber(source.lineSpaceBefore);
63305
63368
  const after = afterRaw != null ? twipsToPx$1(afterRaw) : pickNumber(source.lineSpaceAfter);
63306
63369
  const line = normalizeLineValue(lineRaw, lineRule);
@@ -63308,8 +63371,24 @@ Please report this to https://github.com/markedjs/marked.`, e) {
63308
63371
  if (after != null) spacing.after = after;
63309
63372
  if (line != null) spacing.line = line;
63310
63373
  if (lineRule) spacing.lineRule = lineRule;
63374
+ if (beforeAutospacing != null) spacing.beforeAutospacing = beforeAutospacing;
63375
+ if (afterAutospacing != null) spacing.afterAutospacing = afterAutospacing;
63376
+ if (contextualSpacing != null) spacing.contextualSpacing = contextualSpacing;
63311
63377
  return Object.keys(spacing).length > 0 ? spacing : void 0;
63312
63378
  };
63379
+ const toBooleanFlag = (value) => {
63380
+ if (value === true || value === false) return value;
63381
+ if (typeof value === "string") {
63382
+ const normalized = value.trim().toLowerCase();
63383
+ if (["true", "1", "on", "yes"].includes(normalized)) return true;
63384
+ if (["false", "0", "off", "no"].includes(normalized)) return false;
63385
+ }
63386
+ if (typeof value === "number") {
63387
+ if (value === 1) return true;
63388
+ if (value === 0) return false;
63389
+ }
63390
+ return void 0;
63391
+ };
63313
63392
  const normalizeLineValue = (value, lineRule) => {
63314
63393
  if (value == null) return void 0;
63315
63394
  if (lineRule === "auto") {
@@ -64682,15 +64761,17 @@ Please report this to https://github.com/markedjs/marked.`, e) {
64682
64761
  return null;
64683
64762
  }
64684
64763
  const attrs = para.attrs ?? {};
64685
- const styleId = typeof attrs.styleId === "string" && attrs.styleId.trim() ? attrs.styleId : null;
64764
+ const paragraphProps = typeof attrs.paragraphProperties === "object" && attrs.paragraphProperties !== null ? attrs.paragraphProperties : {};
64765
+ const styleIdSource = attrs.styleId ?? paragraphProps.styleId;
64766
+ const styleId = typeof styleIdSource === "string" && styleIdSource.trim() ? styleIdSource : null;
64686
64767
  if (!styleId) {
64687
64768
  return null;
64688
64769
  }
64689
64770
  const inlineProps = {
64690
64771
  styleId,
64691
- numberingProperties: cloneIfObject(attrs.numberingProperties),
64692
- indent: cloneIfObject(attrs.indent),
64693
- spacing: cloneIfObject(attrs.spacing)
64772
+ numberingProperties: cloneIfObject(attrs.numberingProperties ?? paragraphProps.numberingProperties),
64773
+ indent: cloneIfObject(attrs.indent ?? paragraphProps.indent),
64774
+ spacing: cloneIfObject(attrs.spacing ?? paragraphProps.spacing)
64694
64775
  };
64695
64776
  const resolverParams = {
64696
64777
  docx: context.docx,
@@ -64968,13 +65049,17 @@ Please report this to https://github.com/markedjs/marked.`, e) {
64968
65049
  };
64969
65050
  const computeParagraphAttrs = (para, styleContext, listCounterContext, converterContext, hydrationOverride) => {
64970
65051
  const attrs = para.attrs ?? {};
65052
+ const paragraphProps = typeof attrs.paragraphProperties === "object" && attrs.paragraphProperties !== null ? attrs.paragraphProperties : {};
64971
65053
  const hydrated = hydrationOverride ?? hydrateParagraphStyleAttrs(para, converterContext);
64972
- const spacingSource = attrs.spacing !== void 0 ? attrs.spacing : hydrated?.spacing;
65054
+ const spacingSource = attrs.spacing !== void 0 ? attrs.spacing : paragraphProps.spacing !== void 0 ? paragraphProps.spacing : hydrated?.spacing;
64973
65055
  const normalizedSpacing = normalizeParagraphSpacing(spacingSource);
64974
- const indentSource = attrs.indent ?? hydrated?.indent;
65056
+ const indentSource = attrs.indent ?? paragraphProps.indent ?? hydrated?.indent;
64975
65057
  const normalizedIndent = normalizePxIndent(indentSource) ?? normalizeParagraphIndent(indentSource ?? attrs.textIndent);
64976
- const styleNodeAttrs = hydrated?.tabStops && !attrs.tabStops && !attrs.tabs ? { ...attrs, tabStops: hydrated.tabStops } : attrs;
65058
+ const styleNodeAttrs = hydrated?.tabStops && !attrs.tabStops && !attrs.tabs ? { ...attrs, tabStops: hydrated.tabStops } : !attrs.tabStops && paragraphProps.tabStops ? { ...attrs, tabStops: paragraphProps.tabStops } : attrs;
64977
65059
  const styleNode = buildStyleNodeFromAttrs(styleNodeAttrs, normalizedSpacing, normalizedIndent);
65060
+ if (styleNodeAttrs.styleId == null && paragraphProps.styleId) {
65061
+ styleNode.styleId = paragraphProps.styleId;
65062
+ }
64978
65063
  const computed2 = resolveStyle(styleNode, styleContext);
64979
65064
  const { spacing, indent: indent2 } = resolveSpacingIndent(computed2.paragraph, computed2.numbering);
64980
65065
  const paragraphAttrs = {};
@@ -64999,6 +65084,18 @@ Please report this to https://github.com/markedjs/marked.`, e) {
64999
65084
  }
65000
65085
  const spacingPx = spacingPtToPx(spacing, normalizedSpacing);
65001
65086
  if (spacingPx) paragraphAttrs.spacing = spacingPx;
65087
+ if (normalizedSpacing?.beforeAutospacing != null || normalizedSpacing?.afterAutospacing != null) {
65088
+ paragraphAttrs.spacing = paragraphAttrs.spacing ?? {};
65089
+ if (normalizedSpacing?.beforeAutospacing != null) {
65090
+ paragraphAttrs.spacing.beforeAutospacing = normalizedSpacing.beforeAutospacing;
65091
+ }
65092
+ if (normalizedSpacing?.afterAutospacing != null) {
65093
+ paragraphAttrs.spacing.afterAutospacing = normalizedSpacing.afterAutospacing;
65094
+ }
65095
+ }
65096
+ if (normalizedSpacing?.contextualSpacing != null) {
65097
+ paragraphAttrs.contextualSpacing = normalizedSpacing.contextualSpacing;
65098
+ }
65002
65099
  const hasExplicitIndent = Boolean(normalizedIndent);
65003
65100
  const hasNumberingIndent = Boolean(computed2.numbering?.indent?.left || computed2.numbering?.indent?.hanging);
65004
65101
  if (hasExplicitIndent || hasNumberingIndent || bidi && adjustRightInd) {
@@ -65017,10 +65114,20 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65017
65114
  if (borders) paragraphAttrs.borders = borders;
65018
65115
  const shading = normalizeParagraphShading(attrs.shading ?? hydrated?.shading);
65019
65116
  if (shading) paragraphAttrs.shading = shading;
65117
+ const keepNext = paragraphProps.keepNext ?? hydrated?.keepNext ?? attrs.keepNext;
65118
+ if (keepNext === true) paragraphAttrs.keepNext = true;
65119
+ const keepLines = paragraphProps.keepLines ?? hydrated?.keepLines ?? attrs.keepLines;
65120
+ if (keepLines === true) paragraphAttrs.keepLines = true;
65020
65121
  const paragraphDecimalSeparator = styleContext.defaults?.decimalSeparator ?? DEFAULT_DECIMAL_SEPARATOR$2;
65021
65122
  if (paragraphDecimalSeparator !== DEFAULT_DECIMAL_SEPARATOR$2) {
65022
65123
  paragraphAttrs.decimalSeparator = paragraphDecimalSeparator;
65023
65124
  }
65125
+ const styleIdAttr = typeof attrs.styleId === "string" ? attrs.styleId : void 0;
65126
+ if (styleIdAttr) {
65127
+ paragraphAttrs.styleId = styleIdAttr;
65128
+ } else if (paragraphProps.styleId) {
65129
+ paragraphAttrs.styleId = paragraphProps.styleId;
65130
+ }
65024
65131
  const paraIntervalTwips = pickNumber(attrs.tabIntervalTwips) ?? (() => {
65025
65132
  const px = pickNumber(attrs.tabIntervalPx);
65026
65133
  return px != null ? Math.round(px * 15) : void 0;
@@ -65057,7 +65164,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65057
65164
  paragraphAttrs.floatAlignment = xAlign;
65058
65165
  }
65059
65166
  }
65060
- const numberingSource = attrs.numberingProperties ?? hydrated?.numberingProperties;
65167
+ const numberingSource = attrs.numberingProperties ?? paragraphProps.numberingProperties ?? hydrated?.numberingProperties;
65061
65168
  const rawNumberingProps = toAdapterNumberingProps(numberingSource);
65062
65169
  if (rawNumberingProps) {
65063
65170
  const numberingProps = rawNumberingProps;
@@ -65710,13 +65817,29 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65710
65817
  return null;
65711
65818
  };
65712
65819
  const isTextRun$1 = (run2) => run2.kind !== "tab";
65820
+ const dataAttrsCompatible = (a2, b2) => {
65821
+ const aAttrs = a2.dataAttrs;
65822
+ const bAttrs = b2.dataAttrs;
65823
+ if (!aAttrs && !bAttrs) return true;
65824
+ if (!aAttrs || !bAttrs) return false;
65825
+ const aKeys = Object.keys(aAttrs).sort();
65826
+ const bKeys = Object.keys(bAttrs).sort();
65827
+ if (aKeys.length !== bKeys.length) return false;
65828
+ for (let i2 = 0; i2 < aKeys.length; i2++) {
65829
+ const key2 = aKeys[i2];
65830
+ if (key2 !== bKeys[i2] || aAttrs[key2] !== bAttrs[key2]) {
65831
+ return false;
65832
+ }
65833
+ }
65834
+ return true;
65835
+ };
65713
65836
  function mergeAdjacentRuns(runs2) {
65714
65837
  if (runs2.length <= 1) return runs2;
65715
65838
  const merged = [];
65716
65839
  let current = runs2[0];
65717
65840
  for (let i2 = 1; i2 < runs2.length; i2++) {
65718
65841
  const next2 = runs2[i2];
65719
- const canMerge = isTextRun$1(current) && isTextRun$1(next2) && !current.token && !next2.token && current.pmStart != null && current.pmEnd != null && next2.pmStart != null && next2.pmEnd != null && current.pmEnd === next2.pmStart && current.fontFamily === next2.fontFamily && current.fontSize === next2.fontSize && current.bold === next2.bold && current.italic === next2.italic && current.underline === next2.underline && current.strike === next2.strike && current.color === next2.color && current.highlight === next2.highlight && (current.letterSpacing ?? 0) === (next2.letterSpacing ?? 0) && trackedChangesCompatible(current, next2);
65842
+ const canMerge = isTextRun$1(current) && isTextRun$1(next2) && !current.token && !next2.token && current.pmStart != null && current.pmEnd != null && next2.pmStart != null && next2.pmEnd != null && current.pmEnd === next2.pmStart && current.fontFamily === next2.fontFamily && current.fontSize === next2.fontSize && current.bold === next2.bold && current.italic === next2.italic && current.underline === next2.underline && current.strike === next2.strike && current.color === next2.color && current.highlight === next2.highlight && (current.letterSpacing ?? 0) === (next2.letterSpacing ?? 0) && trackedChangesCompatible(current, next2) && dataAttrsCompatible(current, next2);
65720
65843
  if (canMerge) {
65721
65844
  const currText = current.text ?? "";
65722
65845
  const nextText = next2.text ?? "";
@@ -65733,10 +65856,62 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65733
65856
  merged.push(current);
65734
65857
  return merged;
65735
65858
  }
65859
+ const applyBaseRunDefaults = (run2, defaults2, fallbackFont, fallbackSize) => {
65860
+ if (!run2) return;
65861
+ if (defaults2.fontFamily && run2.fontFamily === fallbackFont) {
65862
+ run2.fontFamily = defaults2.fontFamily;
65863
+ }
65864
+ if (defaults2.fontSizePx != null && run2.fontSize === fallbackSize) {
65865
+ run2.fontSize = defaults2.fontSizePx;
65866
+ }
65867
+ if (defaults2.color && !run2.color) {
65868
+ run2.color = defaults2.color;
65869
+ }
65870
+ if (defaults2.letterSpacing != null && run2.letterSpacing == null) {
65871
+ run2.letterSpacing = defaults2.letterSpacing;
65872
+ }
65873
+ if (defaults2.bold && run2.bold === void 0) {
65874
+ run2.bold = true;
65875
+ }
65876
+ if (defaults2.italic && run2.italic === void 0) {
65877
+ run2.italic = true;
65878
+ }
65879
+ if (defaults2.underline && !run2.underline) {
65880
+ run2.underline = defaults2.underline;
65881
+ }
65882
+ };
65736
65883
  function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defaultSize, styleContext, listCounterContext, trackedChanges, bookmarks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors, converters, converterContext) {
65737
65884
  const baseBlockId = nextBlockId("paragraph");
65738
- const paragraphStyleId = typeof para.attrs?.styleId === "string" ? para.attrs.styleId : null;
65885
+ const paragraphProps = typeof para.attrs?.paragraphProperties === "object" && para.attrs.paragraphProperties !== null ? para.attrs.paragraphProperties : {};
65886
+ const paragraphStyleId = typeof para.attrs?.styleId === "string" && para.attrs.styleId.trim() ? para.attrs.styleId : typeof paragraphProps.styleId === "string" && paragraphProps.styleId.trim() ? paragraphProps.styleId : null;
65739
65887
  const paragraphHydration = converterContext ? hydrateParagraphStyleAttrs(para, converterContext) : null;
65888
+ let baseRunDefaults = {};
65889
+ try {
65890
+ const spacingSource = para.attrs?.spacing !== void 0 ? para.attrs.spacing : paragraphProps.spacing !== void 0 ? paragraphProps.spacing : paragraphHydration?.spacing;
65891
+ const indentSource = para.attrs?.indent ?? paragraphProps.indent ?? paragraphHydration?.indent;
65892
+ const normalizedSpacing = normalizeParagraphSpacing(spacingSource);
65893
+ const normalizedIndent = normalizePxIndent(indentSource) ?? normalizeParagraphIndent(indentSource ?? para.attrs?.textIndent);
65894
+ const styleNodeAttrs = paragraphHydration?.tabStops && !para.attrs?.tabStops && !para.attrs?.tabs ? { ...para.attrs ?? {}, tabStops: paragraphHydration.tabStops } : para.attrs ?? {};
65895
+ const styleNode = buildStyleNodeFromAttrs(styleNodeAttrs, normalizedSpacing, normalizedIndent);
65896
+ if (styleNodeAttrs.styleId == null && paragraphProps.styleId) {
65897
+ styleNode.styleId = paragraphProps.styleId;
65898
+ }
65899
+ const resolved = resolveStyle(styleNode, styleContext);
65900
+ baseRunDefaults = {
65901
+ fontFamily: resolved.character.font?.family,
65902
+ fontSizePx: ptToPx(resolved.character.font?.size),
65903
+ color: resolved.character.color,
65904
+ bold: resolved.character.font?.weight != null ? resolved.character.font.weight >= 600 : void 0,
65905
+ italic: resolved.character.font?.italic,
65906
+ underline: resolved.character.underline ? {
65907
+ style: resolved.character.underline.style,
65908
+ color: resolved.character.underline.color
65909
+ } : void 0,
65910
+ letterSpacing: ptToPx(resolved.character.letterSpacing)
65911
+ };
65912
+ } catch {
65913
+ baseRunDefaults = {};
65914
+ }
65740
65915
  const paragraphAttrs = computeParagraphAttrs(
65741
65916
  para,
65742
65917
  styleContext,
@@ -65744,6 +65919,18 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65744
65919
  converterContext,
65745
65920
  paragraphHydration
65746
65921
  );
65922
+ if (paragraphAttrs?.spacing) {
65923
+ const spacing = { ...paragraphAttrs.spacing };
65924
+ const effectiveFontSize = baseRunDefaults.fontSizePx ?? defaultSize;
65925
+ const isList2 = Boolean(paragraphAttrs.numberingProperties);
65926
+ if (spacing.beforeAutospacing) {
65927
+ spacing.before = isList2 ? 0 : Math.max(0, Number(spacing.before ?? 0) + effectiveFontSize * 0.5);
65928
+ }
65929
+ if (spacing.afterAutospacing) {
65930
+ spacing.after = isList2 ? 0 : Math.max(0, Number(spacing.after ?? 0) + effectiveFontSize * 0.5);
65931
+ }
65932
+ paragraphAttrs.spacing = spacing;
65933
+ }
65747
65934
  const linkedStyleResolver = createLinkedStyleResolver(converterContext?.linkedStyles);
65748
65935
  const blocks2 = [];
65749
65936
  if (hasPageBreakBefore(para)) {
@@ -65821,6 +66008,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65821
66008
  );
65822
66009
  const inlineStyleId = getInlineStyleId(inheritedMarks);
65823
66010
  applyRunStyles2(run2, inlineStyleId, activeRunStyleId);
66011
+ applyBaseRunDefaults(run2, baseRunDefaults, defaultFont, defaultSize);
65824
66012
  currentRuns.push(run2);
65825
66013
  return;
65826
66014
  }
@@ -65856,6 +66044,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65856
66044
  );
65857
66045
  const inlineStyleId = getInlineStyleId(inheritedMarks);
65858
66046
  applyRunStyles2(run2, inlineStyleId, activeRunStyleId);
66047
+ applyBaseRunDefaults(run2, baseRunDefaults, defaultFont, defaultSize);
65859
66048
  currentRuns.push(run2);
65860
66049
  }
65861
66050
  }
@@ -65893,6 +66082,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65893
66082
  );
65894
66083
  const inlineStyleId = getInlineStyleId(mergedMarks);
65895
66084
  applyRunStyles2(tokenRun, inlineStyleId, activeRunStyleId);
66085
+ applyBaseRunDefaults(tokenRun, baseRunDefaults, defaultFont, defaultSize);
65896
66086
  if (pageRefPos) {
65897
66087
  tokenRun.pmStart = pageRefPos.start;
65898
66088
  tokenRun.pmEnd = pageRefPos.end;
@@ -65951,6 +66141,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65951
66141
  }
65952
66142
  const inlineStyleId = getInlineStyleId(inheritedMarks);
65953
66143
  applyRunStyles2(tokenRun, inlineStyleId, activeRunStyleId);
66144
+ applyBaseRunDefaults(tokenRun, baseRunDefaults, defaultFont, defaultSize);
65954
66145
  currentRuns.push(tokenRun);
65955
66146
  }
65956
66147
  return;
@@ -67979,7 +68170,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
67979
68170
  let lines = normalizeLines(measure);
67980
68171
  let fromLine = 0;
67981
68172
  const spacing = block.attrs?.spacing ?? {};
67982
- const spacingBefore = Math.max(0, Number(spacing.before ?? spacing.lineSpaceBefore ?? 0));
68173
+ const styleId = block.attrs?.styleId;
68174
+ const contextualSpacing = Boolean(block.attrs?.contextualSpacing);
68175
+ let spacingBefore = Math.max(0, Number(spacing.before ?? spacing.lineSpaceBefore ?? 0));
67983
68176
  const spacingAfter = Math.max(0, Number(spacing.after ?? spacing.lineSpaceAfter ?? 0));
67984
68177
  let appliedSpacingBefore = spacingBefore === 0;
67985
68178
  let lastState = null;
@@ -67995,6 +68188,15 @@ Please report this to https://github.com/markedjs/marked.`, e) {
67995
68188
  while (fromLine < lines.length) {
67996
68189
  let state2 = ensurePage();
67997
68190
  if (state2.trailingSpacing == null) state2.trailingSpacing = 0;
68191
+ if (contextualSpacing) {
68192
+ const prevStyle = state2.lastParagraphStyleId;
68193
+ if (styleId && prevStyle && prevStyle === styleId) {
68194
+ spacingBefore = 0;
68195
+ }
68196
+ }
68197
+ if (contextualSpacing && state2.lastParagraphStyleId && styleId && state2.lastParagraphStyleId === styleId) {
68198
+ spacingBefore = 0;
68199
+ }
67998
68200
  if (!appliedSpacingBefore && spacingBefore > 0) {
67999
68201
  while (!appliedSpacingBefore) {
68000
68202
  const prevTrailing = state2.trailingSpacing ?? 0;
@@ -68163,6 +68365,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68163
68365
  } else {
68164
68366
  lastState.trailingSpacing = 0;
68165
68367
  }
68368
+ lastState.lastParagraphStyleId = styleId;
68166
68369
  }
68167
68370
  }
68168
68371
  function layoutImageBlock({
@@ -68401,7 +68604,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68401
68604
  contentBottom,
68402
68605
  constraintBoundaries: [],
68403
68606
  activeConstraintIndex: -1,
68404
- trailingSpacing: 0
68607
+ trailingSpacing: 0,
68608
+ lastParagraphStyleId: void 0
68405
68609
  };
68406
68610
  states.push(state2);
68407
68611
  pages.push(state2.page);
@@ -68423,6 +68627,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68423
68627
  state2.cursorY = state2.topMargin;
68424
68628
  }
68425
68629
  state2.trailingSpacing = 0;
68630
+ state2.lastParagraphStyleId = void 0;
68426
68631
  return state2;
68427
68632
  }
68428
68633
  return startNewPage();
@@ -72965,8 +73170,59 @@ ${l}
72965
73170
  this.headerProvider = header;
72966
73171
  this.footerProvider = footer;
72967
73172
  }
72968
- setData(blocks2, measures) {
73173
+ /**
73174
+ * Updates the painter's block and measure data.
73175
+ *
73176
+ * @param blocks - Main document blocks
73177
+ * @param measures - Measures corresponding to main document blocks
73178
+ * @param headerBlocks - Optional header blocks from header/footer layout results
73179
+ * @param headerMeasures - Optional measures corresponding to header blocks
73180
+ * @param footerBlocks - Optional footer blocks from header/footer layout results
73181
+ * @param footerMeasures - Optional measures corresponding to footer blocks
73182
+ */
73183
+ setData(blocks2, measures, headerBlocks, headerMeasures, footerBlocks, footerMeasures) {
73184
+ if (blocks2.length !== measures.length) {
73185
+ throw new Error(
73186
+ `setData: blocks and measures arrays must have the same length. Got blocks.length=${blocks2.length}, measures.length=${measures.length}`
73187
+ );
73188
+ }
73189
+ const hasHeaderBlocks = headerBlocks !== void 0;
73190
+ const hasHeaderMeasures = headerMeasures !== void 0;
73191
+ if (hasHeaderBlocks !== hasHeaderMeasures) {
73192
+ throw new Error(
73193
+ `setData: headerBlocks and headerMeasures must both be provided or both be omitted. Got headerBlocks=${hasHeaderBlocks ? "provided" : "omitted"}, headerMeasures=${hasHeaderMeasures ? "provided" : "omitted"}`
73194
+ );
73195
+ }
73196
+ if (hasHeaderBlocks && hasHeaderMeasures && headerBlocks.length !== headerMeasures.length) {
73197
+ throw new Error(
73198
+ `setData: headerBlocks and headerMeasures arrays must have the same length. Got headerBlocks.length=${headerBlocks.length}, headerMeasures.length=${headerMeasures.length}`
73199
+ );
73200
+ }
73201
+ const hasFooterBlocks = footerBlocks !== void 0;
73202
+ const hasFooterMeasures = footerMeasures !== void 0;
73203
+ if (hasFooterBlocks !== hasFooterMeasures) {
73204
+ throw new Error(
73205
+ `setData: footerBlocks and footerMeasures must both be provided or both be omitted. Got footerBlocks=${hasFooterBlocks ? "provided" : "omitted"}, footerMeasures=${hasFooterMeasures ? "provided" : "omitted"}`
73206
+ );
73207
+ }
73208
+ if (hasFooterBlocks && hasFooterMeasures && footerBlocks.length !== footerMeasures.length) {
73209
+ throw new Error(
73210
+ `setData: footerBlocks and footerMeasures arrays must have the same length. Got footerBlocks.length=${footerBlocks.length}, footerMeasures.length=${footerMeasures.length}`
73211
+ );
73212
+ }
72969
73213
  const nextLookup = this.buildBlockLookup(blocks2, measures);
73214
+ if (headerBlocks && headerMeasures) {
73215
+ const headerLookup = this.buildBlockLookup(headerBlocks, headerMeasures);
73216
+ headerLookup.forEach((entry, id) => {
73217
+ nextLookup.set(id, entry);
73218
+ });
73219
+ }
73220
+ if (footerBlocks && footerMeasures) {
73221
+ const footerLookup = this.buildBlockLookup(footerBlocks, footerMeasures);
73222
+ footerLookup.forEach((entry, id) => {
73223
+ nextLookup.set(id, entry);
73224
+ });
73225
+ }
72970
73226
  const changed = /* @__PURE__ */ new Set();
72971
73227
  nextLookup.forEach((entry, id) => {
72972
73228
  const previous2 = this.blockLookup.get(id);
@@ -73289,6 +73545,14 @@ ${l}
73289
73545
  container.style.height = `${data.height}px`;
73290
73546
  container.style.top = `${Math.max(0, offset2)}px`;
73291
73547
  container.style.zIndex = "1";
73548
+ let footerYOffset = 0;
73549
+ if (kind === "footer" && data.fragments.length > 0) {
73550
+ const contentHeight = typeof data.contentHeight === "number" ? data.contentHeight : data.fragments.reduce((max2, f2) => {
73551
+ const fragHeight = "height" in f2 && typeof f2.height === "number" ? f2.height : this.estimateFragmentHeight(f2);
73552
+ return Math.max(max2, f2.y + Math.max(0, fragHeight));
73553
+ }, 0);
73554
+ footerYOffset = Math.max(0, data.height - contentHeight);
73555
+ }
73292
73556
  const context = {
73293
73557
  pageNumber: page.number,
73294
73558
  totalPages: this.totalPages,
@@ -73297,6 +73561,10 @@ ${l}
73297
73561
  };
73298
73562
  data.fragments.forEach((fragment) => {
73299
73563
  const fragEl = this.renderFragment(fragment, context);
73564
+ if (footerYOffset > 0) {
73565
+ const currentTop = parseFloat(fragEl.style.top) || fragment.y;
73566
+ fragEl.style.top = `${currentTop + footerYOffset}px`;
73567
+ }
73300
73568
  container.appendChild(fragEl);
73301
73569
  });
73302
73570
  if (!existing) {
@@ -73574,147 +73842,162 @@ ${l}
73574
73842
  return el;
73575
73843
  }
73576
73844
  renderListItemFragment(fragment, context) {
73577
- const lookup2 = this.blockLookup.get(fragment.blockId);
73578
- if (!lookup2 || lookup2.block.kind !== "list" || lookup2.measure.kind !== "list") {
73579
- throw new Error(`DomPainter: missing list data for fragment ${fragment.blockId}`);
73580
- }
73581
- if (!this.doc) {
73582
- throw new Error("DomPainter: document is not available");
73845
+ try {
73846
+ const lookup2 = this.blockLookup.get(fragment.blockId);
73847
+ if (!lookup2 || lookup2.block.kind !== "list" || lookup2.measure.kind !== "list") {
73848
+ throw new Error(`DomPainter: missing list data for fragment ${fragment.blockId}`);
73849
+ }
73850
+ if (!this.doc) {
73851
+ throw new Error("DomPainter: document is not available");
73852
+ }
73853
+ const block = lookup2.block;
73854
+ const measure = lookup2.measure;
73855
+ const item = block.items.find((entry) => entry.id === fragment.itemId);
73856
+ const itemMeasure = measure.items.find((entry) => entry.itemId === fragment.itemId);
73857
+ if (!item || !itemMeasure) {
73858
+ throw new Error(`DomPainter: missing list item ${fragment.itemId}`);
73859
+ }
73860
+ const fragmentEl = this.doc.createElement("div");
73861
+ fragmentEl.classList.add(CLASS_NAMES.fragment, `${CLASS_NAMES.fragment}-list-item`);
73862
+ applyStyles$2(fragmentEl, fragmentStyles);
73863
+ fragmentEl.style.left = `${fragment.x - fragment.markerWidth}px`;
73864
+ fragmentEl.style.top = `${fragment.y}px`;
73865
+ fragmentEl.style.width = `${fragment.markerWidth + fragment.width}px`;
73866
+ fragmentEl.dataset.blockId = fragment.blockId;
73867
+ fragmentEl.dataset.itemId = fragment.itemId;
73868
+ const paragraphMetadata = item.paragraph.attrs?.sdt;
73869
+ this.applySdtDataset(fragmentEl, paragraphMetadata);
73870
+ if (fragment.continuesFromPrev) {
73871
+ fragmentEl.dataset.continuesFromPrev = "true";
73872
+ }
73873
+ if (fragment.continuesOnNext) {
73874
+ fragmentEl.dataset.continuesOnNext = "true";
73875
+ }
73876
+ const markerEl = this.doc.createElement("span");
73877
+ markerEl.classList.add("superdoc-list-marker");
73878
+ const wordLayout = item.paragraph.attrs?.wordLayout;
73879
+ const marker = wordLayout?.marker;
73880
+ if (marker) {
73881
+ markerEl.textContent = marker.markerText ?? null;
73882
+ markerEl.style.display = "inline-block";
73883
+ markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
73884
+ markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
73885
+ markerEl.style.textAlign = marker.justification ?? "";
73886
+ markerEl.style.fontFamily = marker.run.fontFamily;
73887
+ markerEl.style.fontSize = `${marker.run.fontSize}px`;
73888
+ if (marker.run.bold) markerEl.style.fontWeight = "bold";
73889
+ if (marker.run.italic) markerEl.style.fontStyle = "italic";
73890
+ if (marker.run.color) markerEl.style.color = marker.run.color;
73891
+ if (marker.run.letterSpacing) markerEl.style.letterSpacing = `${marker.run.letterSpacing}px`;
73892
+ } else {
73893
+ markerEl.textContent = item.marker.text;
73894
+ markerEl.style.display = "inline-block";
73895
+ markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
73896
+ markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
73897
+ if (item.marker.align) {
73898
+ markerEl.style.textAlign = item.marker.align;
73899
+ }
73900
+ }
73901
+ fragmentEl.appendChild(markerEl);
73902
+ const contentEl = this.doc.createElement("div");
73903
+ contentEl.classList.add("superdoc-list-content");
73904
+ this.applySdtDataset(contentEl, paragraphMetadata);
73905
+ contentEl.style.display = "inline-block";
73906
+ contentEl.style.width = `${fragment.width}px`;
73907
+ const lines = itemMeasure.paragraph.lines.slice(fragment.fromLine, fragment.toLine);
73908
+ const contentAttrs = wordLayout ? item.paragraph.attrs : stripListIndent(item.paragraph.attrs);
73909
+ applyParagraphBlockStyles(contentEl, contentAttrs);
73910
+ lines.forEach((line) => {
73911
+ const lineEl = this.renderLine(item.paragraph, line, context);
73912
+ contentEl.appendChild(lineEl);
73913
+ });
73914
+ fragmentEl.appendChild(contentEl);
73915
+ return fragmentEl;
73916
+ } catch (error) {
73917
+ console.error("[DomPainter] List item fragment rendering failed:", { fragment, error });
73918
+ return this.createErrorPlaceholder(fragment.blockId, error);
73583
73919
  }
73584
- const block = lookup2.block;
73585
- const measure = lookup2.measure;
73586
- const item = block.items.find((entry) => entry.id === fragment.itemId);
73587
- const itemMeasure = measure.items.find((entry) => entry.itemId === fragment.itemId);
73588
- if (!item || !itemMeasure) {
73589
- throw new Error(`DomPainter: missing list item ${fragment.itemId}`);
73590
- }
73591
- const fragmentEl = this.doc.createElement("div");
73592
- fragmentEl.classList.add(CLASS_NAMES.fragment, `${CLASS_NAMES.fragment}-list-item`);
73593
- applyStyles$2(fragmentEl, fragmentStyles);
73594
- fragmentEl.style.left = `${fragment.x - fragment.markerWidth}px`;
73595
- fragmentEl.style.top = `${fragment.y}px`;
73596
- fragmentEl.style.width = `${fragment.markerWidth + fragment.width}px`;
73597
- fragmentEl.dataset.blockId = fragment.blockId;
73598
- fragmentEl.dataset.itemId = fragment.itemId;
73599
- const paragraphMetadata = item.paragraph.attrs?.sdt;
73600
- this.applySdtDataset(fragmentEl, paragraphMetadata);
73601
- if (fragment.continuesFromPrev) {
73602
- fragmentEl.dataset.continuesFromPrev = "true";
73603
- }
73604
- if (fragment.continuesOnNext) {
73605
- fragmentEl.dataset.continuesOnNext = "true";
73606
- }
73607
- const markerEl = this.doc.createElement("span");
73608
- markerEl.classList.add("superdoc-list-marker");
73609
- const wordLayout = item.paragraph.attrs?.wordLayout;
73610
- if (wordLayout?.marker) {
73611
- const marker = wordLayout.marker;
73612
- markerEl.textContent = marker.markerText;
73613
- markerEl.style.display = "inline-block";
73614
- markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
73615
- markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
73616
- markerEl.style.textAlign = marker.justification;
73617
- markerEl.style.fontFamily = marker.run.fontFamily;
73618
- markerEl.style.fontSize = `${marker.run.fontSize}px`;
73619
- if (marker.run.bold) markerEl.style.fontWeight = "bold";
73620
- if (marker.run.italic) markerEl.style.fontStyle = "italic";
73621
- if (marker.run.color) markerEl.style.color = marker.run.color;
73622
- if (marker.run.letterSpacing) markerEl.style.letterSpacing = `${marker.run.letterSpacing}px`;
73623
- } else {
73624
- markerEl.textContent = item.marker.text;
73625
- markerEl.style.display = "inline-block";
73626
- markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
73627
- markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
73628
- if (item.marker.align) {
73629
- markerEl.style.textAlign = item.marker.align;
73630
- }
73631
- }
73632
- fragmentEl.appendChild(markerEl);
73633
- const contentEl = this.doc.createElement("div");
73634
- contentEl.classList.add("superdoc-list-content");
73635
- this.applySdtDataset(contentEl, paragraphMetadata);
73636
- contentEl.style.display = "inline-block";
73637
- contentEl.style.width = `${fragment.width}px`;
73638
- const lines = itemMeasure.paragraph.lines.slice(fragment.fromLine, fragment.toLine);
73639
- const contentAttrs = wordLayout ? item.paragraph.attrs : stripListIndent(item.paragraph.attrs);
73640
- applyParagraphBlockStyles(contentEl, contentAttrs);
73641
- lines.forEach((line) => {
73642
- const lineEl = this.renderLine(item.paragraph, line, context);
73643
- contentEl.appendChild(lineEl);
73644
- });
73645
- fragmentEl.appendChild(contentEl);
73646
- return fragmentEl;
73647
73920
  }
73648
73921
  renderImageFragment(fragment) {
73649
- const lookup2 = this.blockLookup.get(fragment.blockId);
73650
- if (!lookup2 || lookup2.block.kind !== "image" || lookup2.measure.kind !== "image") {
73651
- throw new Error(`DomPainter: missing image block for fragment ${fragment.blockId}`);
73652
- }
73653
- if (!this.doc) {
73654
- throw new Error("DomPainter: document is not available");
73655
- }
73656
- const block = lookup2.block;
73657
- const fragmentEl = this.doc.createElement("div");
73658
- fragmentEl.classList.add(CLASS_NAMES.fragment);
73659
- applyStyles$2(fragmentEl, fragmentStyles);
73660
- this.applyFragmentFrame(fragmentEl, fragment);
73661
- fragmentEl.style.height = `${fragment.height}px`;
73662
- this.applySdtDataset(fragmentEl, block.attrs?.sdt);
73663
- this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
73664
- if (fragment.isAnchored && fragment.zIndex != null) {
73665
- fragmentEl.style.zIndex = String(fragment.zIndex);
73666
- }
73667
- const img2 = this.doc.createElement("img");
73668
- if (block.src) {
73669
- img2.src = block.src;
73922
+ try {
73923
+ const lookup2 = this.blockLookup.get(fragment.blockId);
73924
+ if (!lookup2 || lookup2.block.kind !== "image" || lookup2.measure.kind !== "image") {
73925
+ throw new Error(`DomPainter: missing image block for fragment ${fragment.blockId}`);
73926
+ }
73927
+ if (!this.doc) {
73928
+ throw new Error("DomPainter: document is not available");
73929
+ }
73930
+ const block = lookup2.block;
73931
+ const fragmentEl = this.doc.createElement("div");
73932
+ fragmentEl.classList.add(CLASS_NAMES.fragment);
73933
+ applyStyles$2(fragmentEl, fragmentStyles);
73934
+ this.applyFragmentFrame(fragmentEl, fragment);
73935
+ fragmentEl.style.height = `${fragment.height}px`;
73936
+ this.applySdtDataset(fragmentEl, block.attrs?.sdt);
73937
+ this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
73938
+ if (fragment.isAnchored && fragment.zIndex != null) {
73939
+ fragmentEl.style.zIndex = String(fragment.zIndex);
73940
+ }
73941
+ const img2 = this.doc.createElement("img");
73942
+ if (block.src) {
73943
+ img2.src = block.src;
73944
+ }
73945
+ img2.alt = block.alt ?? "";
73946
+ img2.style.width = "100%";
73947
+ img2.style.height = "100%";
73948
+ img2.style.objectFit = block.objectFit ?? "contain";
73949
+ img2.style.display = block.display === "inline" ? "inline-block" : "block";
73950
+ fragmentEl.appendChild(img2);
73951
+ return fragmentEl;
73952
+ } catch (error) {
73953
+ console.error("[DomPainter] Image fragment rendering failed:", { fragment, error });
73954
+ return this.createErrorPlaceholder(fragment.blockId, error);
73670
73955
  }
73671
- img2.alt = block.alt ?? "";
73672
- img2.style.width = "100%";
73673
- img2.style.height = "100%";
73674
- img2.style.objectFit = block.objectFit ?? "contain";
73675
- img2.style.display = block.display === "inline" ? "inline-block" : "block";
73676
- fragmentEl.appendChild(img2);
73677
- return fragmentEl;
73678
73956
  }
73679
73957
  renderDrawingFragment(fragment) {
73680
- const lookup2 = this.blockLookup.get(fragment.blockId);
73681
- if (!lookup2 || lookup2.block.kind !== "drawing" || lookup2.measure.kind !== "drawing") {
73682
- throw new Error(`DomPainter: missing drawing block for fragment ${fragment.blockId}`);
73683
- }
73684
- if (!this.doc) {
73685
- throw new Error("DomPainter: document is not available");
73958
+ try {
73959
+ const lookup2 = this.blockLookup.get(fragment.blockId);
73960
+ if (!lookup2 || lookup2.block.kind !== "drawing" || lookup2.measure.kind !== "drawing") {
73961
+ throw new Error(`DomPainter: missing drawing block for fragment ${fragment.blockId}`);
73962
+ }
73963
+ if (!this.doc) {
73964
+ throw new Error("DomPainter: document is not available");
73965
+ }
73966
+ const block = lookup2.block;
73967
+ const isVectorShapeBlock = block.kind === "drawing" && block.drawingKind === "vectorShape";
73968
+ const fragmentEl = this.doc.createElement("div");
73969
+ fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-drawing-fragment");
73970
+ applyStyles$2(fragmentEl, fragmentStyles);
73971
+ this.applyFragmentFrame(fragmentEl, fragment);
73972
+ fragmentEl.style.height = `${fragment.height}px`;
73973
+ fragmentEl.style.position = "absolute";
73974
+ if (fragment.isAnchored && fragment.zIndex != null) {
73975
+ fragmentEl.style.zIndex = String(fragment.zIndex);
73976
+ }
73977
+ const innerWrapper = this.doc.createElement("div");
73978
+ innerWrapper.classList.add("superdoc-drawing-inner");
73979
+ innerWrapper.style.position = "absolute";
73980
+ innerWrapper.style.left = "50%";
73981
+ innerWrapper.style.top = "50%";
73982
+ innerWrapper.style.width = `${fragment.geometry.width}px`;
73983
+ innerWrapper.style.height = `${fragment.geometry.height}px`;
73984
+ innerWrapper.style.transformOrigin = "center";
73985
+ const scale = fragment.scale ?? 1;
73986
+ const transforms = ["translate(-50%, -50%)"];
73987
+ if (!isVectorShapeBlock) {
73988
+ transforms.push(`rotate(${fragment.geometry.rotation ?? 0}deg)`);
73989
+ transforms.push(`scaleX(${fragment.geometry.flipH ? -1 : 1})`);
73990
+ transforms.push(`scaleY(${fragment.geometry.flipV ? -1 : 1})`);
73991
+ }
73992
+ transforms.push(`scale(${scale})`);
73993
+ innerWrapper.style.transform = transforms.join(" ");
73994
+ innerWrapper.appendChild(this.renderDrawingContent(block, fragment));
73995
+ fragmentEl.appendChild(innerWrapper);
73996
+ return fragmentEl;
73997
+ } catch (error) {
73998
+ console.error("[DomPainter] Drawing fragment rendering failed:", { fragment, error });
73999
+ return this.createErrorPlaceholder(fragment.blockId, error);
73686
74000
  }
73687
- const block = lookup2.block;
73688
- const isVectorShapeBlock = block.kind === "drawing" && block.drawingKind === "vectorShape";
73689
- const fragmentEl = this.doc.createElement("div");
73690
- fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-drawing-fragment");
73691
- applyStyles$2(fragmentEl, fragmentStyles);
73692
- this.applyFragmentFrame(fragmentEl, fragment);
73693
- fragmentEl.style.height = `${fragment.height}px`;
73694
- fragmentEl.style.position = "absolute";
73695
- if (fragment.isAnchored && fragment.zIndex != null) {
73696
- fragmentEl.style.zIndex = String(fragment.zIndex);
73697
- }
73698
- const innerWrapper = this.doc.createElement("div");
73699
- innerWrapper.classList.add("superdoc-drawing-inner");
73700
- innerWrapper.style.position = "absolute";
73701
- innerWrapper.style.left = "50%";
73702
- innerWrapper.style.top = "50%";
73703
- innerWrapper.style.width = `${fragment.geometry.width}px`;
73704
- innerWrapper.style.height = `${fragment.geometry.height}px`;
73705
- innerWrapper.style.transformOrigin = "center";
73706
- const scale = fragment.scale ?? 1;
73707
- const transforms = ["translate(-50%, -50%)"];
73708
- if (!isVectorShapeBlock) {
73709
- transforms.push(`rotate(${fragment.geometry.rotation ?? 0}deg)`);
73710
- transforms.push(`scaleX(${fragment.geometry.flipH ? -1 : 1})`);
73711
- transforms.push(`scaleY(${fragment.geometry.flipV ? -1 : 1})`);
73712
- }
73713
- transforms.push(`scale(${scale})`);
73714
- innerWrapper.style.transform = transforms.join(" ");
73715
- innerWrapper.appendChild(this.renderDrawingContent(block, fragment));
73716
- fragmentEl.appendChild(innerWrapper);
73717
- return fragmentEl;
73718
74001
  }
73719
74002
  renderDrawingContent(block, fragment) {
73720
74003
  if (!this.doc) {
@@ -74149,6 +74432,7 @@ ${l}
74149
74432
  }
74150
74433
  applyRunStyles(elem, run2, isActiveLink);
74151
74434
  elem.style.zIndex = "1";
74435
+ applyRunDataAttributes(elem, run2.dataAttrs);
74152
74436
  if (run2.pmStart != null) elem.dataset.pmStart = String(run2.pmStart);
74153
74437
  if (run2.pmEnd != null) elem.dataset.pmEnd = String(run2.pmEnd);
74154
74438
  if (trackedConfig) {
@@ -74347,6 +74631,33 @@ ${l}
74347
74631
  }
74348
74632
  }
74349
74633
  }
74634
+ /**
74635
+ * Estimates the height of a fragment when explicit height is not available.
74636
+ *
74637
+ * This method provides fallback height calculations for footer bottom-alignment
74638
+ * by consulting measure data for paragraphs and list items, or using the
74639
+ * fragment's height property for tables, images, and drawings.
74640
+ *
74641
+ * @param fragment - The fragment to estimate height for
74642
+ * @returns Estimated height in pixels, or 0 if height cannot be determined
74643
+ */
74644
+ estimateFragmentHeight(fragment) {
74645
+ const lookup2 = this.blockLookup.get(fragment.blockId);
74646
+ const measure = lookup2?.measure;
74647
+ if (fragment.kind === "para" && measure?.kind === "paragraph") {
74648
+ return measure.totalHeight;
74649
+ }
74650
+ if (fragment.kind === "list-item" && measure?.kind === "list") {
74651
+ return measure.totalHeight;
74652
+ }
74653
+ if (fragment.kind === "table") {
74654
+ return fragment.height;
74655
+ }
74656
+ if (fragment.kind === "image" || fragment.kind === "drawing") {
74657
+ return fragment.height;
74658
+ }
74659
+ return 0;
74660
+ }
74350
74661
  buildBlockLookup(blocks2, measures) {
74351
74662
  if (blocks2.length !== measures.length) {
74352
74663
  throw new Error("DomPainter requires the same number of blocks and measures");
@@ -74529,6 +74840,12 @@ ${l}
74529
74840
  run2.kind !== "tab" && run2.bold ? 1 : 0,
74530
74841
  run2.kind !== "tab" && run2.italic ? 1 : 0,
74531
74842
  run2.kind !== "tab" ? run2.color ?? "" : "",
74843
+ // Text decorations - ensures DOM updates when decoration properties change.
74844
+ run2.kind !== "tab" ? run2.underline?.style ?? "" : "",
74845
+ run2.kind !== "tab" ? run2.underline?.color ?? "" : "",
74846
+ run2.kind !== "tab" && run2.strike ? 1 : 0,
74847
+ run2.kind !== "tab" ? run2.highlight ?? "" : "",
74848
+ run2.kind !== "tab" && run2.letterSpacing != null ? run2.letterSpacing : "",
74532
74849
  run2.pmStart ?? "",
74533
74850
  run2.pmEnd ?? "",
74534
74851
  run2.kind !== "tab" ? run2.token ?? "" : ""
@@ -74623,6 +74940,20 @@ ${l}
74623
74940
  element2.style.textDecorationLine = decorations.join(" ");
74624
74941
  }
74625
74942
  };
74943
+ const applyRunDataAttributes = (element2, dataAttrs) => {
74944
+ if (!dataAttrs) return;
74945
+ Object.entries(dataAttrs).forEach(([key2, value]) => {
74946
+ if (typeof key2 !== "string" || !key2.toLowerCase().startsWith("data-")) return;
74947
+ if (typeof value !== "string") return;
74948
+ try {
74949
+ element2.setAttribute(key2, value);
74950
+ } catch (error) {
74951
+ if (process$1$1.env.NODE_ENV === "development") {
74952
+ console.warn(`[DomPainter] Failed to set data attribute "${key2}":`, error);
74953
+ }
74954
+ }
74955
+ });
74956
+ };
74626
74957
  const applyParagraphBlockStyles = (element2, attrs) => {
74627
74958
  if (!attrs) return;
74628
74959
  if (attrs.alignment) {
@@ -74795,8 +75126,8 @@ ${l}
74795
75126
  paint(layout, mount2) {
74796
75127
  painter.paint(layout, mount2);
74797
75128
  },
74798
- setData(blocks2, measures) {
74799
- painter.setData(blocks2, measures);
75129
+ setData(blocks2, measures, headerBlocks, headerMeasures, footerBlocks, footerMeasures) {
75130
+ painter.setData(blocks2, measures, headerBlocks, headerMeasures, footerBlocks, footerMeasures);
74800
75131
  },
74801
75132
  // Non-standard extension for demo app to avoid re-instantiating on provider changes
74802
75133
  setProviders(header, footer) {
@@ -78185,7 +78516,30 @@ ${l}
78185
78516
  if (typeof painter.setProviders === "function") {
78186
78517
  painter.setProviders(__privateGet$1(this, _headerDecorationProvider), __privateGet$1(this, _footerDecorationProvider));
78187
78518
  }
78188
- painter.setData?.(blocks2, measures);
78519
+ const headerBlocks = [];
78520
+ const headerMeasures = [];
78521
+ if (headerLayouts) {
78522
+ for (const headerResult of headerLayouts) {
78523
+ headerBlocks.push(...headerResult.blocks);
78524
+ headerMeasures.push(...headerResult.measures);
78525
+ }
78526
+ }
78527
+ const footerBlocks = [];
78528
+ const footerMeasures = [];
78529
+ if (footerLayouts) {
78530
+ for (const footerResult of footerLayouts) {
78531
+ footerBlocks.push(...footerResult.blocks);
78532
+ footerMeasures.push(...footerResult.measures);
78533
+ }
78534
+ }
78535
+ painter.setData?.(
78536
+ blocks2,
78537
+ measures,
78538
+ headerBlocks.length > 0 ? headerBlocks : void 0,
78539
+ headerMeasures.length > 0 ? headerMeasures : void 0,
78540
+ footerBlocks.length > 0 ? footerBlocks : void 0,
78541
+ footerMeasures.length > 0 ? footerMeasures : void 0
78542
+ );
78189
78543
  painter.paint(layout, __privateGet$1(this, _painterHost));
78190
78544
  __privateSet(this, _layoutError, null);
78191
78545
  __privateSet(this, _layoutErrorState, "healthy");
@@ -78355,7 +78709,8 @@ ${l}
78355
78709
  const finalHeaderId = headerId ?? fallbackId ?? void 0;
78356
78710
  return {
78357
78711
  fragments: slotPage.fragments,
78358
- height: variant.layout.height ?? box.height,
78712
+ height: box.height,
78713
+ contentHeight: variant.layout.height ?? box.height,
78359
78714
  offset: box.offset,
78360
78715
  marginLeft: box.x,
78361
78716
  contentWidth: box.width,
@@ -78382,18 +78737,19 @@ ${l}
78382
78737
  const left2 = margins.left ?? DEFAULT_MARGINS.left;
78383
78738
  const right2 = margins.right ?? DEFAULT_MARGINS.right;
78384
78739
  const width = Math.max(pageSize.w - (left2 + right2), 1);
78385
- const defaultHeight = kind === "header" ? margins.top ?? DEFAULT_MARGINS.top : margins.bottom ?? DEFAULT_MARGINS.bottom;
78386
- const { headerSpace, footerSpace } = extractHeaderFooterSpace(margins);
78387
- const target = kind === "header" ? headerSpace : footerSpace;
78388
- const height = Math.max(target || defaultHeight || 1, 1);
78389
78740
  const totalHeight = pageHeight ?? pageSize.h;
78390
- const offset2 = kind === "header" ? 0 : Math.max(0, totalHeight - height);
78391
- return {
78392
- x: left2,
78393
- width,
78394
- height,
78395
- offset: offset2
78396
- };
78741
+ if (kind === "header") {
78742
+ const headerMargin = margins.header ?? 0;
78743
+ const topMargin = margins.top ?? DEFAULT_MARGINS.top ?? 0;
78744
+ const height = Math.max(topMargin - headerMargin, 1);
78745
+ return { x: left2, width, height, offset: headerMargin };
78746
+ } else {
78747
+ const footerMargin = margins.footer ?? 0;
78748
+ const bottomMargin = margins.bottom ?? DEFAULT_MARGINS.bottom ?? 0;
78749
+ const height = Math.max(bottomMargin - footerMargin, 1);
78750
+ const offset2 = Math.max(0, totalHeight - footerMargin - height);
78751
+ return { x: left2, width, height, offset: offset2 };
78752
+ }
78397
78753
  };
78398
78754
  rebuildHeaderFooterRegions_fn = function(layout) {
78399
78755
  __privateGet$1(this, _headerRegions).clear();
@@ -78610,7 +78966,8 @@ ${l}
78610
78966
  return context.layout.pageSize?.h ?? context.region.height ?? 1;
78611
78967
  };
78612
78968
  renderSelectionRects_fn = function(rects) {
78613
- if (!__privateGet$1(this, _selectionOverlay)) {
78969
+ const localSelectionLayer = __privateGet$1(this, _localSelectionLayer);
78970
+ if (!localSelectionLayer) {
78614
78971
  return;
78615
78972
  }
78616
78973
  const pageHeight = __privateMethod$1(this, _PresentationEditor_instances, getBodyPageHeight_fn).call(this);
@@ -78621,7 +78978,7 @@ ${l}
78621
78978
  if (!coords) {
78622
78979
  return;
78623
78980
  }
78624
- const highlight = __privateGet$1(this, _selectionOverlay).ownerDocument?.createElement("div");
78981
+ const highlight = localSelectionLayer.ownerDocument?.createElement("div");
78625
78982
  if (!highlight) {
78626
78983
  return;
78627
78984
  }
@@ -78634,7 +78991,7 @@ ${l}
78634
78991
  highlight.style.backgroundColor = "rgba(51, 132, 255, 0.35)";
78635
78992
  highlight.style.borderRadius = "2px";
78636
78993
  highlight.style.pointerEvents = "none";
78637
- __privateGet$1(this, _selectionOverlay).appendChild(highlight);
78994
+ localSelectionLayer.appendChild(highlight);
78638
78995
  });
78639
78996
  };
78640
78997
  renderHoverRegion_fn = function(region) {
@@ -79084,6 +79441,7 @@ ${l}
79084
79441
  __privateAdd$1(this, _onTargetChanged);
79085
79442
  __privateAdd$1(this, _listeners);
79086
79443
  __privateAdd$1(this, _currentTarget, null);
79444
+ __privateAdd$1(this, _destroyed, false);
79087
79445
  __privateSet(this, _windowRoot, windowRoot);
79088
79446
  __privateSet(this, _visibleHost2, visibleHost);
79089
79447
  __privateSet(this, _getTargetDom, getTargetDom);
@@ -79111,9 +79469,13 @@ ${l}
79111
79469
  });
79112
79470
  __privateSet(this, _listeners, []);
79113
79471
  __privateSet(this, _currentTarget, null);
79472
+ __privateSet(this, _destroyed, true);
79114
79473
  }
79115
79474
  notifyTargetChanged() {
79116
79475
  var _a2;
79476
+ if (__privateGet$1(this, _destroyed)) {
79477
+ return;
79478
+ }
79117
79479
  const nextTarget = __privateGet$1(this, _getTargetDom).call(this);
79118
79480
  if (nextTarget === __privateGet$1(this, _currentTarget)) {
79119
79481
  return;
@@ -79143,6 +79505,7 @@ ${l}
79143
79505
  _onTargetChanged = /* @__PURE__ */ new WeakMap();
79144
79506
  _listeners = /* @__PURE__ */ new WeakMap();
79145
79507
  _currentTarget = /* @__PURE__ */ new WeakMap();
79508
+ _destroyed = /* @__PURE__ */ new WeakMap();
79146
79509
  _PresentationInputBridge_instances = /* @__PURE__ */ new WeakSet();
79147
79510
  addListener_fn = function(type2, handler2, target) {
79148
79511
  const bound = handler2.bind(this);
@@ -79150,12 +79513,21 @@ ${l}
79150
79513
  target.addEventListener(type2, bound, true);
79151
79514
  };
79152
79515
  dispatchToTarget_fn = function(originalEvent, synthetic) {
79516
+ if (__privateGet$1(this, _destroyed)) return;
79153
79517
  const target = __privateGet$1(this, _getTargetDom).call(this);
79154
79518
  __privateSet(this, _currentTarget, target);
79155
79519
  if (!target) return;
79156
- const canceled = !target.dispatchEvent(synthetic) || synthetic.defaultPrevented;
79157
- if (canceled) {
79158
- originalEvent.preventDefault();
79520
+ const isConnected = target.isConnected;
79521
+ if (isConnected === false) return;
79522
+ try {
79523
+ const canceled = !target.dispatchEvent(synthetic) || synthetic.defaultPrevented;
79524
+ if (canceled) {
79525
+ originalEvent.preventDefault();
79526
+ }
79527
+ } catch (error) {
79528
+ if (process$1$1.env.NODE_ENV === "development") {
79529
+ console.warn("[PresentationEditor] Failed to dispatch event to target:", error);
79530
+ }
79159
79531
  }
79160
79532
  };
79161
79533
  forwardKeyboardEvent_fn = function(event) {
@@ -108045,7 +108417,7 @@ ${style2}
108045
108417
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
108046
108418
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
108047
108419
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
108048
- var _SuperToolbar_instances, initToolbarGroups_fn, _interceptedCommands, makeToolbarItems_fn, initDefaultFonts_fn, updateHighlightColors_fn, deactivateAll_fn, updateToolbarHistory_fn, enrichTrackedChanges_fn, runCommandWithArgumentOnly_fn;
108420
+ var _MARK_TOGGLE_NAMES, _SuperToolbar_instances, initToolbarGroups_fn, _interceptedCommands, makeToolbarItems_fn, initDefaultFonts_fn, updateHighlightColors_fn, deactivateAll_fn, updateToolbarHistory_fn, enrichTrackedChanges_fn, runCommandWithArgumentOnly_fn, syncStickyMarksFromState_fn, restoreStickyMarksIfNeeded_fn, ensureStoredMarksForMarkToggle_fn;
108049
108421
  var eventemitter3$1 = { exports: {} };
108050
108422
  var hasRequiredEventemitter3$1;
108051
108423
  function requireEventemitter3$1() {
@@ -108264,7 +108636,7 @@ ${style2}
108264
108636
  if (!Array.isArray(options.options)) throw new Error("Invalid toolbar item options - " + options.options);
108265
108637
  nestedOptions.value?.push(...options.options);
108266
108638
  }
108267
- const activate = (attrs, ...args) => {
108639
+ const activate = (attrs = {}, ...args) => {
108268
108640
  onActivate(attrs, ...args);
108269
108641
  if (suppressActiveHighlight.value) return;
108270
108642
  active.value = true;
@@ -110536,7 +110908,7 @@ ${style2}
110536
110908
  if (typeof checker !== "function") return false;
110537
110909
  return Boolean(checker(attrs));
110538
110910
  };
110539
- class SuperToolbar extends EventEmitter$1 {
110911
+ const _SuperToolbar = class _SuperToolbar2 extends EventEmitter$1 {
110540
110912
  /**
110541
110913
  * Creates a new SuperToolbar instance
110542
110914
  * @param {ToolbarConfig} config - The configuration for the toolbar
@@ -110580,11 +110952,11 @@ ${style2}
110580
110952
  const isSmallScreen = window.matchMedia("(max-width: 834px)").matches;
110581
110953
  if (isMobileDevice && isSmallScreen) {
110582
110954
  layers.style.transformOrigin = "0 0";
110583
- layers.style.transform = `scale(${parseInt(argument) / 100})`;
110955
+ layers.style.transform = `scale(${parseInt(argument, 10) / 100})`;
110584
110956
  } else {
110585
- layers.style.zoom = parseInt(argument) / 100;
110957
+ layers.style.zoom = parseInt(argument, 10) / 100;
110586
110958
  }
110587
- this.superdoc.superdocStore.activeZoom = parseInt(argument);
110959
+ this.superdoc.superdocStore.activeZoom = parseInt(argument, 10);
110588
110960
  },
110589
110961
  /**
110590
110962
  * Sets the document mode
@@ -110666,31 +111038,37 @@ ${style2}
110666
111038
  * @returns {Promise<void>}
110667
111039
  */
110668
111040
  startImageUpload: async () => {
110669
- let open = getFileOpener();
110670
- let result = await open();
110671
- if (!result?.file) {
110672
- return;
110673
- }
110674
- const { size: size2, file } = await checkAndProcessImage({
110675
- file: result.file,
110676
- getMaxContentSize: () => this.activeEditor.getMaxContentSize()
110677
- });
110678
- if (!file) {
110679
- return;
111041
+ try {
111042
+ let open = getFileOpener();
111043
+ let result = await open();
111044
+ if (!result?.file) {
111045
+ return;
111046
+ }
111047
+ const { size: size2, file } = await checkAndProcessImage({
111048
+ file: result.file,
111049
+ getMaxContentSize: () => this.activeEditor.getMaxContentSize()
111050
+ });
111051
+ if (!file) {
111052
+ return;
111053
+ }
111054
+ const id = {};
111055
+ replaceSelectionWithImagePlaceholder({
111056
+ view: this.activeEditor.view,
111057
+ editorOptions: this.activeEditor.options,
111058
+ id
111059
+ });
111060
+ await uploadAndInsertImage({
111061
+ editor: this.activeEditor,
111062
+ view: this.activeEditor.view,
111063
+ file,
111064
+ size: size2,
111065
+ id
111066
+ });
111067
+ } catch (error) {
111068
+ const err = new Error("[super-toolbar 🎨] Image upload failed");
111069
+ this.emit("exception", { error: err, editor: this.activeEditor, originalError: error });
111070
+ console.error(err, error);
110680
111071
  }
110681
- const id = {};
110682
- replaceSelectionWithImagePlaceholder({
110683
- view: this.activeEditor.view,
110684
- editorOptions: this.activeEditor.options,
110685
- id
110686
- });
110687
- await uploadAndInsertImage({
110688
- editor: this.activeEditor,
110689
- view: this.activeEditor.view,
110690
- file,
110691
- size: size2,
110692
- id
110693
- });
110694
111072
  },
110695
111073
  /**
110696
111074
  * Increases text indentation or list level
@@ -110859,6 +111237,13 @@ ${style2}
110859
111237
  };
110860
111238
  this.config.hideButtons = config2.hideButtons ?? true;
110861
111239
  this.config.responsiveToContainer = config2.responsiveToContainer ?? false;
111240
+ this.pendingMarkCommands = [];
111241
+ this.stickyStoredMarks = null;
111242
+ this._boundEditorHandlers = {
111243
+ transaction: null,
111244
+ selectionUpdate: null,
111245
+ focus: null
111246
+ };
110862
111247
  if (!this.config.selector && this.config.element) {
110863
111248
  this.config.selector = this.config.element;
110864
111249
  }
@@ -110918,12 +111303,28 @@ ${style2}
110918
111303
  }
110919
111304
  /**
110920
111305
  * The toolbar expects an active Super Editor instance.
110921
- * @param {Object} editor - The editor instance to attach to the toolbar
111306
+ * Removes listeners from the previous editor (if any) before attaching to the new one.
111307
+ * @param {Object|null} editor - The editor instance to attach to the toolbar, or null to detach
110922
111308
  * @returns {void}
110923
111309
  */
110924
111310
  setActiveEditor(editor) {
111311
+ if (this.activeEditor && this._boundEditorHandlers.transaction) {
111312
+ this.activeEditor.off("transaction", this._boundEditorHandlers.transaction);
111313
+ this.activeEditor.off("selectionUpdate", this._boundEditorHandlers.selectionUpdate);
111314
+ this.activeEditor.off("focus", this._boundEditorHandlers.focus);
111315
+ this._boundEditorHandlers.transaction = null;
111316
+ this._boundEditorHandlers.selectionUpdate = null;
111317
+ this._boundEditorHandlers.focus = null;
111318
+ }
110925
111319
  this.activeEditor = editor;
110926
- this.activeEditor.on("transaction", this.onEditorTransaction.bind(this));
111320
+ if (editor) {
111321
+ this._boundEditorHandlers.transaction = this.onEditorTransaction.bind(this);
111322
+ this._boundEditorHandlers.selectionUpdate = this.onEditorSelectionUpdate.bind(this);
111323
+ this._boundEditorHandlers.focus = this.onEditorFocus.bind(this);
111324
+ this.activeEditor.on("transaction", this._boundEditorHandlers.transaction);
111325
+ this.activeEditor.on("selectionUpdate", this._boundEditorHandlers.selectionUpdate);
111326
+ this.activeEditor.on("focus", this._boundEditorHandlers.focus);
111327
+ }
110927
111328
  }
110928
111329
  /**
110929
111330
  * Get toolbar items by group name
@@ -111071,15 +111472,28 @@ ${style2}
111071
111472
  * @returns {*} The result of the executed command, undefined if no result is returned
111072
111473
  */
111073
111474
  emitCommand({ item, argument, option }) {
111475
+ const hasFocusFn = this.activeEditor?.view?.hasFocus;
111476
+ const wasFocused = Boolean(typeof hasFocusFn === "function" && hasFocusFn.call(this.activeEditor.view));
111477
+ const { command: command2 } = item;
111478
+ const isMarkToggle = this.isMarkToggle(item);
111479
+ if (!wasFocused && isMarkToggle) {
111480
+ this.pendingMarkCommands.push({ command: command2, argument, item });
111481
+ item?.activate?.();
111482
+ if (this.activeEditor && !this.activeEditor.options.isHeaderOrFooter) {
111483
+ this.activeEditor.focus();
111484
+ }
111485
+ return;
111486
+ }
111074
111487
  if (this.activeEditor && !this.activeEditor.options.isHeaderOrFooter) {
111075
111488
  this.activeEditor.focus();
111076
111489
  }
111077
- const { command: command2 } = item;
111078
111490
  if (!command2) {
111079
111491
  return;
111080
111492
  }
111081
111493
  if (command2 in __privateGet(this, _interceptedCommands)) {
111082
- return __privateGet(this, _interceptedCommands)[command2]({ item, argument });
111494
+ const result = __privateGet(this, _interceptedCommands)[command2]({ item, argument });
111495
+ if (isMarkToggle) __privateMethod(this, _SuperToolbar_instances, syncStickyMarksFromState_fn).call(this);
111496
+ return result;
111083
111497
  }
111084
111498
  if (this.activeEditor && this.activeEditor.commands && command2 in this.activeEditor.commands) {
111085
111499
  this.activeEditor.commands[command2](argument);
@@ -111090,9 +111504,67 @@ ${style2}
111090
111504
  this.emit("exception", { error, editor: this.activeEditor });
111091
111505
  throw error;
111092
111506
  }
111507
+ if (isMarkToggle) __privateMethod(this, _SuperToolbar_instances, syncStickyMarksFromState_fn).call(this);
111093
111508
  this.updateToolbarState();
111094
111509
  }
111095
- }
111510
+ /**
111511
+ * Processes and executes pending mark commands when editor selection updates.
111512
+ * This is triggered by the editor's 'selectionUpdate' event after focus is restored.
111513
+ * Clears the pending queue after execution.
111514
+ * @returns {void}
111515
+ */
111516
+ onEditorSelectionUpdate() {
111517
+ if (!this.activeEditor) return;
111518
+ if (this.pendingMarkCommands.length) {
111519
+ const pending = this.pendingMarkCommands;
111520
+ this.pendingMarkCommands = [];
111521
+ pending.forEach(({ command: command2, argument, item }) => {
111522
+ if (!command2) return;
111523
+ try {
111524
+ if (command2 in __privateGet(this, _interceptedCommands)) {
111525
+ __privateGet(this, _interceptedCommands)[command2]({ item, argument });
111526
+ } else if (this.activeEditor.commands && command2 in this.activeEditor.commands) {
111527
+ this.activeEditor.commands[command2](argument);
111528
+ }
111529
+ __privateMethod(this, _SuperToolbar_instances, ensureStoredMarksForMarkToggle_fn).call(this, { command: command2, argument });
111530
+ } catch (error) {
111531
+ const err = new Error(`[super-toolbar 🎨] Failed to execute pending command: ${command2}`);
111532
+ this.emit("exception", { error: err, editor: this.activeEditor, originalError: error });
111533
+ console.error(err, error);
111534
+ }
111535
+ });
111536
+ __privateMethod(this, _SuperToolbar_instances, syncStickyMarksFromState_fn).call(this);
111537
+ this.updateToolbarState();
111538
+ return;
111539
+ }
111540
+ const restored = __privateMethod(this, _SuperToolbar_instances, restoreStickyMarksIfNeeded_fn).call(this);
111541
+ if (restored) this.updateToolbarState();
111542
+ }
111543
+ /**
111544
+ * Handles editor focus events by flushing any pending mark commands.
111545
+ * This is triggered by the editor's 'focus' event.
111546
+ * @returns {void}
111547
+ */
111548
+ onEditorFocus() {
111549
+ if (this.pendingMarkCommands.length) {
111550
+ this.onEditorSelectionUpdate();
111551
+ return;
111552
+ }
111553
+ const restored = __privateMethod(this, _SuperToolbar_instances, restoreStickyMarksIfNeeded_fn).call(this);
111554
+ if (restored) this.updateToolbarState();
111555
+ }
111556
+ /**
111557
+ * Determines if a toolbar item represents a mark toggle command.
111558
+ * Mark toggles include text formatting commands like bold, italic, underline, etc.
111559
+ * @param {ToolbarItem} item - The toolbar item to check
111560
+ * @returns {boolean} True if the item is a mark toggle, false otherwise
111561
+ */
111562
+ isMarkToggle(item) {
111563
+ const name = item?.name?.value;
111564
+ return __privateGet(_SuperToolbar2, _MARK_TOGGLE_NAMES).has(name);
111565
+ }
111566
+ };
111567
+ _MARK_TOGGLE_NAMES = /* @__PURE__ */ new WeakMap();
111096
111568
  _SuperToolbar_instances = /* @__PURE__ */ new WeakSet();
111097
111569
  initToolbarGroups_fn = function() {
111098
111570
  if (this.config.groups && !Array.isArray(this.config.groups) && Object.keys(this.config.groups).length) {
@@ -111205,6 +111677,55 @@ ${style2}
111205
111677
  this.updateToolbarState();
111206
111678
  }
111207
111679
  };
111680
+ syncStickyMarksFromState_fn = function() {
111681
+ if (!this.activeEditor) return;
111682
+ const { selection, storedMarks } = this.activeEditor.state || {};
111683
+ if (!selection?.empty) return;
111684
+ this.stickyStoredMarks = storedMarks?.length ? [...storedMarks] : null;
111685
+ };
111686
+ restoreStickyMarksIfNeeded_fn = function() {
111687
+ if (!this.activeEditor) return false;
111688
+ if (!this.stickyStoredMarks?.length) return false;
111689
+ const { state: state2, view } = this.activeEditor;
111690
+ const { selection, storedMarks } = state2 || {};
111691
+ if (!selection?.empty) return false;
111692
+ if (storedMarks?.length) return false;
111693
+ if (!view?.dispatch || !state2?.tr) return false;
111694
+ const hasActiveMarkToggle = getActiveFormatting(this.activeEditor).some(
111695
+ (mark2) => __privateGet(_SuperToolbar, _MARK_TOGGLE_NAMES).has(mark2.name)
111696
+ );
111697
+ if (hasActiveMarkToggle) return false;
111698
+ const tr = state2.tr.setStoredMarks(this.stickyStoredMarks);
111699
+ view.dispatch(tr);
111700
+ return true;
111701
+ };
111702
+ ensureStoredMarksForMarkToggle_fn = function({ command: command2, argument }) {
111703
+ if (!this.activeEditor) return;
111704
+ if (!this.activeEditor.state?.selection?.empty) return;
111705
+ if (this.activeEditor.state?.storedMarks?.length) return;
111706
+ if (command2 !== "setFontSize") return;
111707
+ const { state: state2, view } = this.activeEditor;
111708
+ const textStyleMark = state2.schema?.marks?.textStyle;
111709
+ if (!textStyleMark || !view?.dispatch || !state2?.tr) return;
111710
+ const [value, unit] = parseSizeUnit(argument ?? "");
111711
+ if (Number.isNaN(value)) return;
111712
+ const clamped = Math.min(96, Math.max(8, Number(value)));
111713
+ const resolvedUnit = unit || "pt";
111714
+ const mark2 = textStyleMark.create({ fontSize: `${clamped}${resolvedUnit}` });
111715
+ const tr = state2.tr.setStoredMarks([mark2]);
111716
+ view.dispatch(tr);
111717
+ };
111718
+ __privateAdd(_SuperToolbar, _MARK_TOGGLE_NAMES, /* @__PURE__ */ new Set([
111719
+ "bold",
111720
+ "italic",
111721
+ "underline",
111722
+ "strike",
111723
+ "highlight",
111724
+ "color",
111725
+ "fontSize",
111726
+ "fontFamily"
111727
+ ]));
111728
+ let SuperToolbar = _SuperToolbar;
111208
111729
  const onMarginClickCursorChange = (event, editor) => {
111209
111730
  const y2 = event.clientY;
111210
111731
  const x2 = event.clientX;
@@ -130653,7 +131174,7 @@ ${style2}
130653
131174
  this.config.colors = shuffleArray(this.config.colors);
130654
131175
  this.userColorMap = /* @__PURE__ */ new Map();
130655
131176
  this.colorIndex = 0;
130656
- this.version = "1.0.0-beta.2";
131177
+ this.version = "1.0.0-beta.4";
130657
131178
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
130658
131179
  this.superdocId = config2.superdocId || v4();
130659
131180
  this.colors = this.config.colors;
@@ -133096,7 +133617,7 @@ ${style2}
133096
133617
  value && typeof value === "object" && "byteLength" in value && "byteOffset" in value
133097
133618
  );
133098
133619
  }
133099
- const indexSnJVHIg = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
133620
+ const indexBNGaD3Up = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
133100
133621
  __proto__: null,
133101
133622
  unified
133102
133623
  }, Symbol.toStringTag, { value: "Module" }));