@harbour-enterprises/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
@@ -35580,7 +35580,7 @@ const _SuperConverter = class _SuperConverter2 {
35580
35580
  static getStoredSuperdocVersion(docx) {
35581
35581
  return _SuperConverter2.getStoredCustomProperty(docx, "SuperdocVersion");
35582
35582
  }
35583
- static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.2") {
35583
+ static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.4") {
35584
35584
  return _SuperConverter2.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
35585
35585
  }
35586
35586
  /**
@@ -38780,7 +38780,7 @@ var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "rea
38780
38780
  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);
38781
38781
  var __privateSet = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
38782
38782
  var __privateMethod$1 = (obj, member, method) => (__accessCheck$1(obj, member, "access private method"), method);
38783
- 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;
38783
+ 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;
38784
38784
  var GOOD_LEAF_SIZE = 200;
38785
38785
  var RopeSequence = function RopeSequence2() {
38786
38786
  };
@@ -52287,7 +52287,7 @@ const isHeadless = (editor) => {
52287
52287
  const shouldSkipNodeView = (editor) => {
52288
52288
  return isHeadless(editor);
52289
52289
  };
52290
- const summaryVersion = "1.0.0-beta.2";
52290
+ const summaryVersion = "1.0.0-beta.4";
52291
52291
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
52292
52292
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
52293
52293
  function mapAttributes(attrs) {
@@ -53066,7 +53066,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
53066
53066
  { default: remarkStringify },
53067
53067
  { default: remarkGfm }
53068
53068
  ] = await Promise.all([
53069
- Promise.resolve().then(() => require("./index-Sn-JVHIg-BxOp3gSx.cjs")),
53069
+ Promise.resolve().then(() => require("./index-BNGaD3Up-D2cRHMMk.cjs")),
53070
53070
  Promise.resolve().then(() => require("./index-DRCvimau-H4Ck3S9a.cjs")),
53071
53071
  Promise.resolve().then(() => require("./index-C_x_N6Uh-Db3CUJMX.cjs")),
53072
53072
  Promise.resolve().then(() => require("./index-D_sWOSiG-BtDZzJ6I.cjs")),
@@ -53271,7 +53271,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
53271
53271
  * Process collaboration migrations
53272
53272
  */
53273
53273
  processCollaborationMigrations() {
53274
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.2");
53274
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.4");
53275
53275
  if (!this.options.ydoc) return;
53276
53276
  const metaMap = this.options.ydoc.getMap("meta");
53277
53277
  let docVersion = metaMap.get("version");
@@ -54890,6 +54890,50 @@ const resolveColorFromAttributes = (attrs, themeColors) => {
54890
54890
  }
54891
54891
  return void 0;
54892
54892
  };
54893
+ const MAX_DATA_ATTR_COUNT = 50;
54894
+ const MAX_DATA_ATTR_VALUE_LENGTH = 1e3;
54895
+ const MAX_DATA_ATTR_NAME_LENGTH = 100;
54896
+ const extractDataAttributes = (attrs) => {
54897
+ if (!attrs) return void 0;
54898
+ const result = {};
54899
+ let attrCount = 0;
54900
+ for (const [key2, value] of Object.entries(attrs)) {
54901
+ if (typeof key2 !== "string" || !key2.toLowerCase().startsWith("data-")) {
54902
+ continue;
54903
+ }
54904
+ if (attrCount >= MAX_DATA_ATTR_COUNT) {
54905
+ if (process$1$1.env.NODE_ENV === "development") {
54906
+ console.warn(`[PM-Adapter] Rejecting data attributes exceeding ${MAX_DATA_ATTR_COUNT} limit`);
54907
+ }
54908
+ break;
54909
+ }
54910
+ if (key2.length > MAX_DATA_ATTR_NAME_LENGTH) {
54911
+ if (process$1$1.env.NODE_ENV === "development") {
54912
+ console.warn(
54913
+ `[PM-Adapter] Rejecting data attribute name exceeding ${MAX_DATA_ATTR_NAME_LENGTH} chars: ${key2.substring(0, 50)}...`
54914
+ );
54915
+ }
54916
+ continue;
54917
+ }
54918
+ if (value == null) {
54919
+ continue;
54920
+ }
54921
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
54922
+ const stringValue = String(value);
54923
+ if (stringValue.length > MAX_DATA_ATTR_VALUE_LENGTH) {
54924
+ if (process$1$1.env.NODE_ENV === "development") {
54925
+ console.warn(
54926
+ `[PM-Adapter] Rejecting data attribute value exceeding ${MAX_DATA_ATTR_VALUE_LENGTH} chars for key: ${key2}`
54927
+ );
54928
+ }
54929
+ continue;
54930
+ }
54931
+ result[key2] = stringValue;
54932
+ attrCount++;
54933
+ }
54934
+ }
54935
+ return Object.keys(result).length > 0 ? result : void 0;
54936
+ };
54893
54937
  const normalizeRunMarkList = (value) => {
54894
54938
  if (!value) return void 0;
54895
54939
  let entries = value;
@@ -55058,6 +55102,19 @@ const sanitizeFontFamily = (fontFamily2) => {
55058
55102
  }
55059
55103
  return sanitized;
55060
55104
  };
55105
+ const normalizeFontSizePx = (value) => {
55106
+ if (isFiniteNumber(value)) return value;
55107
+ if (typeof value !== "string") return void 0;
55108
+ const trimmed = value.trim();
55109
+ if (!trimmed) return void 0;
55110
+ const numeric = Number.parseFloat(trimmed);
55111
+ if (!Number.isFinite(numeric)) return void 0;
55112
+ const unit = trimmed.match(/[a-zA-Z%]+$/)?.[0]?.toLowerCase();
55113
+ if (unit === "pt") {
55114
+ return ptToPx(numeric);
55115
+ }
55116
+ return numeric;
55117
+ };
55061
55118
  const applyTextStyleMark = (run2, attrs, themeColors) => {
55062
55119
  const resolvedColor = resolveColorFromAttributes(attrs, themeColors);
55063
55120
  if (resolvedColor) {
@@ -55069,11 +55126,9 @@ const applyTextStyleMark = (run2, attrs, themeColors) => {
55069
55126
  run2.fontFamily = sanitized;
55070
55127
  }
55071
55128
  }
55072
- if (isFiniteNumber(attrs.fontSize)) {
55073
- const size2 = Number(attrs.fontSize);
55074
- if (size2 >= 1 && size2 <= 1e3) {
55075
- run2.fontSize = size2;
55076
- }
55129
+ const fontSizePx = normalizeFontSizePx(attrs.fontSize);
55130
+ if (fontSizePx !== void 0 && fontSizePx >= 1 && fontSizePx <= 1e3) {
55131
+ run2.fontSize = fontSizePx;
55077
55132
  }
55078
55133
  if (isFiniteNumber(attrs.letterSpacing)) {
55079
55134
  const spacing = Number(attrs.letterSpacing);
@@ -55087,6 +55142,7 @@ const DEFAULT_HYPERLINK_CONFIG = {
55087
55142
  };
55088
55143
  const applyMarksToRun = (run2, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG, themeColors) => {
55089
55144
  marks.forEach((mark) => {
55145
+ const forwardedDataAttrs = extractDataAttributes(mark.attrs);
55090
55146
  try {
55091
55147
  switch (mark.type) {
55092
55148
  case TRACK_INSERT_MARK:
@@ -55181,6 +55237,9 @@ const applyMarksToRun = (run2, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG
55181
55237
  console.warn(`[PM-Adapter] Failed to apply mark ${mark.type}:`, error);
55182
55238
  }
55183
55239
  }
55240
+ if (forwardedDataAttrs) {
55241
+ run2.dataAttrs = { ...run2.dataAttrs ?? {}, ...forwardedDataAttrs };
55242
+ }
55184
55243
  });
55185
55244
  };
55186
55245
  function textNodeToRun(textNode, positions, defaultFont, defaultSize, inheritedMarks = [], sdtMetadata, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors) {
@@ -55204,8 +55263,9 @@ function tabNodeToRun(node, positions, tabIndex, paragraph) {
55204
55263
  const pos = positions.get(node);
55205
55264
  if (!pos) return null;
55206
55265
  const paragraphAttrs = paragraph.attrs ?? {};
55207
- const tabStops = Array.isArray(paragraphAttrs.tabStops) ? paragraphAttrs.tabStops : void 0;
55208
- const indent = paragraphAttrs.indent;
55266
+ const paragraphProps = typeof paragraphAttrs.paragraphProperties === "object" && paragraphAttrs.paragraphProperties !== null ? paragraphAttrs.paragraphProperties : {};
55267
+ const tabStops = Array.isArray(paragraphAttrs.tabStops) && paragraphAttrs.tabStops.length ? paragraphAttrs.tabStops : Array.isArray(paragraphProps.tabStops) ? paragraphProps.tabStops : void 0;
55268
+ const indent = paragraphAttrs.indent ?? paragraphProps.indent ?? void 0;
55209
55269
  return {
55210
55270
  kind: "tab",
55211
55271
  text: " ",
@@ -55519,6 +55579,9 @@ const normalizeParagraphSpacing = (value) => {
55519
55579
  const afterRaw = pickNumber(source.after);
55520
55580
  const lineRaw = pickNumber(source.line);
55521
55581
  const lineRule = normalizeLineRule(source.lineRule);
55582
+ const beforeAutospacing = toBooleanFlag(source.beforeAutospacing ?? source.beforeAutoSpacing);
55583
+ const afterAutospacing = toBooleanFlag(source.afterAutospacing ?? source.afterAutoSpacing);
55584
+ const contextualSpacing = toBooleanFlag(source.contextualSpacing);
55522
55585
  const before = beforeRaw != null ? twipsToPx$1(beforeRaw) : pickNumber(source.lineSpaceBefore);
55523
55586
  const after = afterRaw != null ? twipsToPx$1(afterRaw) : pickNumber(source.lineSpaceAfter);
55524
55587
  const line = normalizeLineValue(lineRaw, lineRule);
@@ -55526,8 +55589,24 @@ const normalizeParagraphSpacing = (value) => {
55526
55589
  if (after != null) spacing.after = after;
55527
55590
  if (line != null) spacing.line = line;
55528
55591
  if (lineRule) spacing.lineRule = lineRule;
55592
+ if (beforeAutospacing != null) spacing.beforeAutospacing = beforeAutospacing;
55593
+ if (afterAutospacing != null) spacing.afterAutospacing = afterAutospacing;
55594
+ if (contextualSpacing != null) spacing.contextualSpacing = contextualSpacing;
55529
55595
  return Object.keys(spacing).length > 0 ? spacing : void 0;
55530
55596
  };
55597
+ const toBooleanFlag = (value) => {
55598
+ if (value === true || value === false) return value;
55599
+ if (typeof value === "string") {
55600
+ const normalized = value.trim().toLowerCase();
55601
+ if (["true", "1", "on", "yes"].includes(normalized)) return true;
55602
+ if (["false", "0", "off", "no"].includes(normalized)) return false;
55603
+ }
55604
+ if (typeof value === "number") {
55605
+ if (value === 1) return true;
55606
+ if (value === 0) return false;
55607
+ }
55608
+ return void 0;
55609
+ };
55531
55610
  const normalizeLineValue = (value, lineRule) => {
55532
55611
  if (value == null) return void 0;
55533
55612
  if (lineRule === "auto") {
@@ -56900,15 +56979,17 @@ const hydrateParagraphStyleAttrs = (para, context, preResolved) => {
56900
56979
  return null;
56901
56980
  }
56902
56981
  const attrs = para.attrs ?? {};
56903
- const styleId = typeof attrs.styleId === "string" && attrs.styleId.trim() ? attrs.styleId : null;
56982
+ const paragraphProps = typeof attrs.paragraphProperties === "object" && attrs.paragraphProperties !== null ? attrs.paragraphProperties : {};
56983
+ const styleIdSource = attrs.styleId ?? paragraphProps.styleId;
56984
+ const styleId = typeof styleIdSource === "string" && styleIdSource.trim() ? styleIdSource : null;
56904
56985
  if (!styleId) {
56905
56986
  return null;
56906
56987
  }
56907
56988
  const inlineProps = {
56908
56989
  styleId,
56909
- numberingProperties: cloneIfObject(attrs.numberingProperties),
56910
- indent: cloneIfObject(attrs.indent),
56911
- spacing: cloneIfObject(attrs.spacing)
56990
+ numberingProperties: cloneIfObject(attrs.numberingProperties ?? paragraphProps.numberingProperties),
56991
+ indent: cloneIfObject(attrs.indent ?? paragraphProps.indent),
56992
+ spacing: cloneIfObject(attrs.spacing ?? paragraphProps.spacing)
56912
56993
  };
56913
56994
  const resolverParams = {
56914
56995
  docx: context.docx,
@@ -57186,13 +57267,17 @@ const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleCont
57186
57267
  };
57187
57268
  const computeParagraphAttrs = (para, styleContext, listCounterContext, converterContext, hydrationOverride) => {
57188
57269
  const attrs = para.attrs ?? {};
57270
+ const paragraphProps = typeof attrs.paragraphProperties === "object" && attrs.paragraphProperties !== null ? attrs.paragraphProperties : {};
57189
57271
  const hydrated = hydrationOverride ?? hydrateParagraphStyleAttrs(para, converterContext);
57190
- const spacingSource = attrs.spacing !== void 0 ? attrs.spacing : hydrated?.spacing;
57272
+ const spacingSource = attrs.spacing !== void 0 ? attrs.spacing : paragraphProps.spacing !== void 0 ? paragraphProps.spacing : hydrated?.spacing;
57191
57273
  const normalizedSpacing = normalizeParagraphSpacing(spacingSource);
57192
- const indentSource = attrs.indent ?? hydrated?.indent;
57274
+ const indentSource = attrs.indent ?? paragraphProps.indent ?? hydrated?.indent;
57193
57275
  const normalizedIndent = normalizePxIndent(indentSource) ?? normalizeParagraphIndent(indentSource ?? attrs.textIndent);
57194
- const styleNodeAttrs = hydrated?.tabStops && !attrs.tabStops && !attrs.tabs ? { ...attrs, tabStops: hydrated.tabStops } : attrs;
57276
+ const styleNodeAttrs = hydrated?.tabStops && !attrs.tabStops && !attrs.tabs ? { ...attrs, tabStops: hydrated.tabStops } : !attrs.tabStops && paragraphProps.tabStops ? { ...attrs, tabStops: paragraphProps.tabStops } : attrs;
57195
57277
  const styleNode = buildStyleNodeFromAttrs(styleNodeAttrs, normalizedSpacing, normalizedIndent);
57278
+ if (styleNodeAttrs.styleId == null && paragraphProps.styleId) {
57279
+ styleNode.styleId = paragraphProps.styleId;
57280
+ }
57196
57281
  const computed2 = resolveStyle(styleNode, styleContext);
57197
57282
  const { spacing, indent } = resolveSpacingIndent(computed2.paragraph, computed2.numbering);
57198
57283
  const paragraphAttrs = {};
@@ -57217,6 +57302,18 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
57217
57302
  }
57218
57303
  const spacingPx = spacingPtToPx(spacing, normalizedSpacing);
57219
57304
  if (spacingPx) paragraphAttrs.spacing = spacingPx;
57305
+ if (normalizedSpacing?.beforeAutospacing != null || normalizedSpacing?.afterAutospacing != null) {
57306
+ paragraphAttrs.spacing = paragraphAttrs.spacing ?? {};
57307
+ if (normalizedSpacing?.beforeAutospacing != null) {
57308
+ paragraphAttrs.spacing.beforeAutospacing = normalizedSpacing.beforeAutospacing;
57309
+ }
57310
+ if (normalizedSpacing?.afterAutospacing != null) {
57311
+ paragraphAttrs.spacing.afterAutospacing = normalizedSpacing.afterAutospacing;
57312
+ }
57313
+ }
57314
+ if (normalizedSpacing?.contextualSpacing != null) {
57315
+ paragraphAttrs.contextualSpacing = normalizedSpacing.contextualSpacing;
57316
+ }
57220
57317
  const hasExplicitIndent = Boolean(normalizedIndent);
57221
57318
  const hasNumberingIndent = Boolean(computed2.numbering?.indent?.left || computed2.numbering?.indent?.hanging);
57222
57319
  if (hasExplicitIndent || hasNumberingIndent || bidi && adjustRightInd) {
@@ -57235,10 +57332,20 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
57235
57332
  if (borders) paragraphAttrs.borders = borders;
57236
57333
  const shading = normalizeParagraphShading(attrs.shading ?? hydrated?.shading);
57237
57334
  if (shading) paragraphAttrs.shading = shading;
57335
+ const keepNext = paragraphProps.keepNext ?? hydrated?.keepNext ?? attrs.keepNext;
57336
+ if (keepNext === true) paragraphAttrs.keepNext = true;
57337
+ const keepLines = paragraphProps.keepLines ?? hydrated?.keepLines ?? attrs.keepLines;
57338
+ if (keepLines === true) paragraphAttrs.keepLines = true;
57238
57339
  const paragraphDecimalSeparator = styleContext.defaults?.decimalSeparator ?? DEFAULT_DECIMAL_SEPARATOR$2;
57239
57340
  if (paragraphDecimalSeparator !== DEFAULT_DECIMAL_SEPARATOR$2) {
57240
57341
  paragraphAttrs.decimalSeparator = paragraphDecimalSeparator;
57241
57342
  }
57343
+ const styleIdAttr = typeof attrs.styleId === "string" ? attrs.styleId : void 0;
57344
+ if (styleIdAttr) {
57345
+ paragraphAttrs.styleId = styleIdAttr;
57346
+ } else if (paragraphProps.styleId) {
57347
+ paragraphAttrs.styleId = paragraphProps.styleId;
57348
+ }
57242
57349
  const paraIntervalTwips = pickNumber(attrs.tabIntervalTwips) ?? (() => {
57243
57350
  const px = pickNumber(attrs.tabIntervalPx);
57244
57351
  return px != null ? Math.round(px * 15) : void 0;
@@ -57275,7 +57382,7 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
57275
57382
  paragraphAttrs.floatAlignment = xAlign;
57276
57383
  }
57277
57384
  }
57278
- const numberingSource = attrs.numberingProperties ?? hydrated?.numberingProperties;
57385
+ const numberingSource = attrs.numberingProperties ?? paragraphProps.numberingProperties ?? hydrated?.numberingProperties;
57279
57386
  const rawNumberingProps = toAdapterNumberingProps(numberingSource);
57280
57387
  if (rawNumberingProps) {
57281
57388
  const numberingProps = rawNumberingProps;
@@ -57928,13 +58035,29 @@ const extractRunStyleId = (runProperties) => {
57928
58035
  return null;
57929
58036
  };
57930
58037
  const isTextRun$1 = (run2) => run2.kind !== "tab";
58038
+ const dataAttrsCompatible = (a, b2) => {
58039
+ const aAttrs = a.dataAttrs;
58040
+ const bAttrs = b2.dataAttrs;
58041
+ if (!aAttrs && !bAttrs) return true;
58042
+ if (!aAttrs || !bAttrs) return false;
58043
+ const aKeys = Object.keys(aAttrs).sort();
58044
+ const bKeys = Object.keys(bAttrs).sort();
58045
+ if (aKeys.length !== bKeys.length) return false;
58046
+ for (let i = 0; i < aKeys.length; i++) {
58047
+ const key2 = aKeys[i];
58048
+ if (key2 !== bKeys[i] || aAttrs[key2] !== bAttrs[key2]) {
58049
+ return false;
58050
+ }
58051
+ }
58052
+ return true;
58053
+ };
57931
58054
  function mergeAdjacentRuns(runs) {
57932
58055
  if (runs.length <= 1) return runs;
57933
58056
  const merged = [];
57934
58057
  let current = runs[0];
57935
58058
  for (let i = 1; i < runs.length; i++) {
57936
58059
  const next = runs[i];
57937
- const canMerge = isTextRun$1(current) && isTextRun$1(next) && !current.token && !next.token && current.pmStart != null && current.pmEnd != null && next.pmStart != null && next.pmEnd != null && current.pmEnd === next.pmStart && current.fontFamily === next.fontFamily && current.fontSize === next.fontSize && current.bold === next.bold && current.italic === next.italic && current.underline === next.underline && current.strike === next.strike && current.color === next.color && current.highlight === next.highlight && (current.letterSpacing ?? 0) === (next.letterSpacing ?? 0) && trackedChangesCompatible(current, next);
58060
+ const canMerge = isTextRun$1(current) && isTextRun$1(next) && !current.token && !next.token && current.pmStart != null && current.pmEnd != null && next.pmStart != null && next.pmEnd != null && current.pmEnd === next.pmStart && current.fontFamily === next.fontFamily && current.fontSize === next.fontSize && current.bold === next.bold && current.italic === next.italic && current.underline === next.underline && current.strike === next.strike && current.color === next.color && current.highlight === next.highlight && (current.letterSpacing ?? 0) === (next.letterSpacing ?? 0) && trackedChangesCompatible(current, next) && dataAttrsCompatible(current, next);
57938
58061
  if (canMerge) {
57939
58062
  const currText = current.text ?? "";
57940
58063
  const nextText = next.text ?? "";
@@ -57951,10 +58074,62 @@ function mergeAdjacentRuns(runs) {
57951
58074
  merged.push(current);
57952
58075
  return merged;
57953
58076
  }
58077
+ const applyBaseRunDefaults = (run2, defaults, fallbackFont, fallbackSize) => {
58078
+ if (!run2) return;
58079
+ if (defaults.fontFamily && run2.fontFamily === fallbackFont) {
58080
+ run2.fontFamily = defaults.fontFamily;
58081
+ }
58082
+ if (defaults.fontSizePx != null && run2.fontSize === fallbackSize) {
58083
+ run2.fontSize = defaults.fontSizePx;
58084
+ }
58085
+ if (defaults.color && !run2.color) {
58086
+ run2.color = defaults.color;
58087
+ }
58088
+ if (defaults.letterSpacing != null && run2.letterSpacing == null) {
58089
+ run2.letterSpacing = defaults.letterSpacing;
58090
+ }
58091
+ if (defaults.bold && run2.bold === void 0) {
58092
+ run2.bold = true;
58093
+ }
58094
+ if (defaults.italic && run2.italic === void 0) {
58095
+ run2.italic = true;
58096
+ }
58097
+ if (defaults.underline && !run2.underline) {
58098
+ run2.underline = defaults.underline;
58099
+ }
58100
+ };
57954
58101
  function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defaultSize, styleContext, listCounterContext, trackedChanges, bookmarks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors, converters, converterContext) {
57955
58102
  const baseBlockId = nextBlockId("paragraph");
57956
- const paragraphStyleId = typeof para.attrs?.styleId === "string" ? para.attrs.styleId : null;
58103
+ const paragraphProps = typeof para.attrs?.paragraphProperties === "object" && para.attrs.paragraphProperties !== null ? para.attrs.paragraphProperties : {};
58104
+ const paragraphStyleId = typeof para.attrs?.styleId === "string" && para.attrs.styleId.trim() ? para.attrs.styleId : typeof paragraphProps.styleId === "string" && paragraphProps.styleId.trim() ? paragraphProps.styleId : null;
57957
58105
  const paragraphHydration = converterContext ? hydrateParagraphStyleAttrs(para, converterContext) : null;
58106
+ let baseRunDefaults = {};
58107
+ try {
58108
+ const spacingSource = para.attrs?.spacing !== void 0 ? para.attrs.spacing : paragraphProps.spacing !== void 0 ? paragraphProps.spacing : paragraphHydration?.spacing;
58109
+ const indentSource = para.attrs?.indent ?? paragraphProps.indent ?? paragraphHydration?.indent;
58110
+ const normalizedSpacing = normalizeParagraphSpacing(spacingSource);
58111
+ const normalizedIndent = normalizePxIndent(indentSource) ?? normalizeParagraphIndent(indentSource ?? para.attrs?.textIndent);
58112
+ const styleNodeAttrs = paragraphHydration?.tabStops && !para.attrs?.tabStops && !para.attrs?.tabs ? { ...para.attrs ?? {}, tabStops: paragraphHydration.tabStops } : para.attrs ?? {};
58113
+ const styleNode = buildStyleNodeFromAttrs(styleNodeAttrs, normalizedSpacing, normalizedIndent);
58114
+ if (styleNodeAttrs.styleId == null && paragraphProps.styleId) {
58115
+ styleNode.styleId = paragraphProps.styleId;
58116
+ }
58117
+ const resolved = resolveStyle(styleNode, styleContext);
58118
+ baseRunDefaults = {
58119
+ fontFamily: resolved.character.font?.family,
58120
+ fontSizePx: ptToPx(resolved.character.font?.size),
58121
+ color: resolved.character.color,
58122
+ bold: resolved.character.font?.weight != null ? resolved.character.font.weight >= 600 : void 0,
58123
+ italic: resolved.character.font?.italic,
58124
+ underline: resolved.character.underline ? {
58125
+ style: resolved.character.underline.style,
58126
+ color: resolved.character.underline.color
58127
+ } : void 0,
58128
+ letterSpacing: ptToPx(resolved.character.letterSpacing)
58129
+ };
58130
+ } catch {
58131
+ baseRunDefaults = {};
58132
+ }
57958
58133
  const paragraphAttrs = computeParagraphAttrs(
57959
58134
  para,
57960
58135
  styleContext,
@@ -57962,6 +58137,18 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
57962
58137
  converterContext,
57963
58138
  paragraphHydration
57964
58139
  );
58140
+ if (paragraphAttrs?.spacing) {
58141
+ const spacing = { ...paragraphAttrs.spacing };
58142
+ const effectiveFontSize = baseRunDefaults.fontSizePx ?? defaultSize;
58143
+ const isList2 = Boolean(paragraphAttrs.numberingProperties);
58144
+ if (spacing.beforeAutospacing) {
58145
+ spacing.before = isList2 ? 0 : Math.max(0, Number(spacing.before ?? 0) + effectiveFontSize * 0.5);
58146
+ }
58147
+ if (spacing.afterAutospacing) {
58148
+ spacing.after = isList2 ? 0 : Math.max(0, Number(spacing.after ?? 0) + effectiveFontSize * 0.5);
58149
+ }
58150
+ paragraphAttrs.spacing = spacing;
58151
+ }
57965
58152
  const linkedStyleResolver = createLinkedStyleResolver(converterContext?.linkedStyles);
57966
58153
  const blocks = [];
57967
58154
  if (hasPageBreakBefore(para)) {
@@ -58039,6 +58226,7 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
58039
58226
  );
58040
58227
  const inlineStyleId = getInlineStyleId(inheritedMarks);
58041
58228
  applyRunStyles2(run2, inlineStyleId, activeRunStyleId);
58229
+ applyBaseRunDefaults(run2, baseRunDefaults, defaultFont, defaultSize);
58042
58230
  currentRuns.push(run2);
58043
58231
  return;
58044
58232
  }
@@ -58074,6 +58262,7 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
58074
58262
  );
58075
58263
  const inlineStyleId = getInlineStyleId(inheritedMarks);
58076
58264
  applyRunStyles2(run2, inlineStyleId, activeRunStyleId);
58265
+ applyBaseRunDefaults(run2, baseRunDefaults, defaultFont, defaultSize);
58077
58266
  currentRuns.push(run2);
58078
58267
  }
58079
58268
  }
@@ -58111,6 +58300,7 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
58111
58300
  );
58112
58301
  const inlineStyleId = getInlineStyleId(mergedMarks);
58113
58302
  applyRunStyles2(tokenRun, inlineStyleId, activeRunStyleId);
58303
+ applyBaseRunDefaults(tokenRun, baseRunDefaults, defaultFont, defaultSize);
58114
58304
  if (pageRefPos) {
58115
58305
  tokenRun.pmStart = pageRefPos.start;
58116
58306
  tokenRun.pmEnd = pageRefPos.end;
@@ -58169,6 +58359,7 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
58169
58359
  }
58170
58360
  const inlineStyleId = getInlineStyleId(inheritedMarks);
58171
58361
  applyRunStyles2(tokenRun, inlineStyleId, activeRunStyleId);
58362
+ applyBaseRunDefaults(tokenRun, baseRunDefaults, defaultFont, defaultSize);
58172
58363
  currentRuns.push(tokenRun);
58173
58364
  }
58174
58365
  return;
@@ -60197,7 +60388,9 @@ function layoutParagraphBlock(ctx2, anchors) {
60197
60388
  let lines = normalizeLines(measure);
60198
60389
  let fromLine = 0;
60199
60390
  const spacing = block.attrs?.spacing ?? {};
60200
- const spacingBefore = Math.max(0, Number(spacing.before ?? spacing.lineSpaceBefore ?? 0));
60391
+ const styleId = block.attrs?.styleId;
60392
+ const contextualSpacing = Boolean(block.attrs?.contextualSpacing);
60393
+ let spacingBefore = Math.max(0, Number(spacing.before ?? spacing.lineSpaceBefore ?? 0));
60201
60394
  const spacingAfter = Math.max(0, Number(spacing.after ?? spacing.lineSpaceAfter ?? 0));
60202
60395
  let appliedSpacingBefore = spacingBefore === 0;
60203
60396
  let lastState = null;
@@ -60213,6 +60406,15 @@ function layoutParagraphBlock(ctx2, anchors) {
60213
60406
  while (fromLine < lines.length) {
60214
60407
  let state2 = ensurePage();
60215
60408
  if (state2.trailingSpacing == null) state2.trailingSpacing = 0;
60409
+ if (contextualSpacing) {
60410
+ const prevStyle = state2.lastParagraphStyleId;
60411
+ if (styleId && prevStyle && prevStyle === styleId) {
60412
+ spacingBefore = 0;
60413
+ }
60414
+ }
60415
+ if (contextualSpacing && state2.lastParagraphStyleId && styleId && state2.lastParagraphStyleId === styleId) {
60416
+ spacingBefore = 0;
60417
+ }
60216
60418
  if (!appliedSpacingBefore && spacingBefore > 0) {
60217
60419
  while (!appliedSpacingBefore) {
60218
60420
  const prevTrailing = state2.trailingSpacing ?? 0;
@@ -60381,6 +60583,7 @@ function layoutParagraphBlock(ctx2, anchors) {
60381
60583
  } else {
60382
60584
  lastState.trailingSpacing = 0;
60383
60585
  }
60586
+ lastState.lastParagraphStyleId = styleId;
60384
60587
  }
60385
60588
  }
60386
60589
  function layoutImageBlock({
@@ -60619,7 +60822,8 @@ function createPaginator(opts) {
60619
60822
  contentBottom,
60620
60823
  constraintBoundaries: [],
60621
60824
  activeConstraintIndex: -1,
60622
- trailingSpacing: 0
60825
+ trailingSpacing: 0,
60826
+ lastParagraphStyleId: void 0
60623
60827
  };
60624
60828
  states.push(state2);
60625
60829
  pages.push(state2.page);
@@ -60641,6 +60845,7 @@ function createPaginator(opts) {
60641
60845
  state2.cursorY = state2.topMargin;
60642
60846
  }
60643
60847
  state2.trailingSpacing = 0;
60848
+ state2.lastParagraphStyleId = void 0;
60644
60849
  return state2;
60645
60850
  }
60646
60851
  return startNewPage();
@@ -65183,8 +65388,59 @@ const _DomPainter = class _DomPainter2 {
65183
65388
  this.headerProvider = header;
65184
65389
  this.footerProvider = footer;
65185
65390
  }
65186
- setData(blocks, measures) {
65391
+ /**
65392
+ * Updates the painter's block and measure data.
65393
+ *
65394
+ * @param blocks - Main document blocks
65395
+ * @param measures - Measures corresponding to main document blocks
65396
+ * @param headerBlocks - Optional header blocks from header/footer layout results
65397
+ * @param headerMeasures - Optional measures corresponding to header blocks
65398
+ * @param footerBlocks - Optional footer blocks from header/footer layout results
65399
+ * @param footerMeasures - Optional measures corresponding to footer blocks
65400
+ */
65401
+ setData(blocks, measures, headerBlocks, headerMeasures, footerBlocks, footerMeasures) {
65402
+ if (blocks.length !== measures.length) {
65403
+ throw new Error(
65404
+ `setData: blocks and measures arrays must have the same length. Got blocks.length=${blocks.length}, measures.length=${measures.length}`
65405
+ );
65406
+ }
65407
+ const hasHeaderBlocks = headerBlocks !== void 0;
65408
+ const hasHeaderMeasures = headerMeasures !== void 0;
65409
+ if (hasHeaderBlocks !== hasHeaderMeasures) {
65410
+ throw new Error(
65411
+ `setData: headerBlocks and headerMeasures must both be provided or both be omitted. Got headerBlocks=${hasHeaderBlocks ? "provided" : "omitted"}, headerMeasures=${hasHeaderMeasures ? "provided" : "omitted"}`
65412
+ );
65413
+ }
65414
+ if (hasHeaderBlocks && hasHeaderMeasures && headerBlocks.length !== headerMeasures.length) {
65415
+ throw new Error(
65416
+ `setData: headerBlocks and headerMeasures arrays must have the same length. Got headerBlocks.length=${headerBlocks.length}, headerMeasures.length=${headerMeasures.length}`
65417
+ );
65418
+ }
65419
+ const hasFooterBlocks = footerBlocks !== void 0;
65420
+ const hasFooterMeasures = footerMeasures !== void 0;
65421
+ if (hasFooterBlocks !== hasFooterMeasures) {
65422
+ throw new Error(
65423
+ `setData: footerBlocks and footerMeasures must both be provided or both be omitted. Got footerBlocks=${hasFooterBlocks ? "provided" : "omitted"}, footerMeasures=${hasFooterMeasures ? "provided" : "omitted"}`
65424
+ );
65425
+ }
65426
+ if (hasFooterBlocks && hasFooterMeasures && footerBlocks.length !== footerMeasures.length) {
65427
+ throw new Error(
65428
+ `setData: footerBlocks and footerMeasures arrays must have the same length. Got footerBlocks.length=${footerBlocks.length}, footerMeasures.length=${footerMeasures.length}`
65429
+ );
65430
+ }
65187
65431
  const nextLookup = this.buildBlockLookup(blocks, measures);
65432
+ if (headerBlocks && headerMeasures) {
65433
+ const headerLookup = this.buildBlockLookup(headerBlocks, headerMeasures);
65434
+ headerLookup.forEach((entry, id) => {
65435
+ nextLookup.set(id, entry);
65436
+ });
65437
+ }
65438
+ if (footerBlocks && footerMeasures) {
65439
+ const footerLookup = this.buildBlockLookup(footerBlocks, footerMeasures);
65440
+ footerLookup.forEach((entry, id) => {
65441
+ nextLookup.set(id, entry);
65442
+ });
65443
+ }
65188
65444
  const changed = /* @__PURE__ */ new Set();
65189
65445
  nextLookup.forEach((entry, id) => {
65190
65446
  const previous = this.blockLookup.get(id);
@@ -65507,6 +65763,14 @@ const _DomPainter = class _DomPainter2 {
65507
65763
  container.style.height = `${data.height}px`;
65508
65764
  container.style.top = `${Math.max(0, offset2)}px`;
65509
65765
  container.style.zIndex = "1";
65766
+ let footerYOffset = 0;
65767
+ if (kind === "footer" && data.fragments.length > 0) {
65768
+ const contentHeight = typeof data.contentHeight === "number" ? data.contentHeight : data.fragments.reduce((max2, f2) => {
65769
+ const fragHeight = "height" in f2 && typeof f2.height === "number" ? f2.height : this.estimateFragmentHeight(f2);
65770
+ return Math.max(max2, f2.y + Math.max(0, fragHeight));
65771
+ }, 0);
65772
+ footerYOffset = Math.max(0, data.height - contentHeight);
65773
+ }
65510
65774
  const context = {
65511
65775
  pageNumber: page.number,
65512
65776
  totalPages: this.totalPages,
@@ -65515,6 +65779,10 @@ const _DomPainter = class _DomPainter2 {
65515
65779
  };
65516
65780
  data.fragments.forEach((fragment) => {
65517
65781
  const fragEl = this.renderFragment(fragment, context);
65782
+ if (footerYOffset > 0) {
65783
+ const currentTop = parseFloat(fragEl.style.top) || fragment.y;
65784
+ fragEl.style.top = `${currentTop + footerYOffset}px`;
65785
+ }
65518
65786
  container.appendChild(fragEl);
65519
65787
  });
65520
65788
  if (!existing) {
@@ -65792,147 +66060,162 @@ const _DomPainter = class _DomPainter2 {
65792
66060
  return el;
65793
66061
  }
65794
66062
  renderListItemFragment(fragment, context) {
65795
- const lookup2 = this.blockLookup.get(fragment.blockId);
65796
- if (!lookup2 || lookup2.block.kind !== "list" || lookup2.measure.kind !== "list") {
65797
- throw new Error(`DomPainter: missing list data for fragment ${fragment.blockId}`);
65798
- }
65799
- if (!this.doc) {
65800
- throw new Error("DomPainter: document is not available");
66063
+ try {
66064
+ const lookup2 = this.blockLookup.get(fragment.blockId);
66065
+ if (!lookup2 || lookup2.block.kind !== "list" || lookup2.measure.kind !== "list") {
66066
+ throw new Error(`DomPainter: missing list data for fragment ${fragment.blockId}`);
66067
+ }
66068
+ if (!this.doc) {
66069
+ throw new Error("DomPainter: document is not available");
66070
+ }
66071
+ const block = lookup2.block;
66072
+ const measure = lookup2.measure;
66073
+ const item = block.items.find((entry) => entry.id === fragment.itemId);
66074
+ const itemMeasure = measure.items.find((entry) => entry.itemId === fragment.itemId);
66075
+ if (!item || !itemMeasure) {
66076
+ throw new Error(`DomPainter: missing list item ${fragment.itemId}`);
66077
+ }
66078
+ const fragmentEl = this.doc.createElement("div");
66079
+ fragmentEl.classList.add(CLASS_NAMES.fragment, `${CLASS_NAMES.fragment}-list-item`);
66080
+ applyStyles$2(fragmentEl, fragmentStyles);
66081
+ fragmentEl.style.left = `${fragment.x - fragment.markerWidth}px`;
66082
+ fragmentEl.style.top = `${fragment.y}px`;
66083
+ fragmentEl.style.width = `${fragment.markerWidth + fragment.width}px`;
66084
+ fragmentEl.dataset.blockId = fragment.blockId;
66085
+ fragmentEl.dataset.itemId = fragment.itemId;
66086
+ const paragraphMetadata = item.paragraph.attrs?.sdt;
66087
+ this.applySdtDataset(fragmentEl, paragraphMetadata);
66088
+ if (fragment.continuesFromPrev) {
66089
+ fragmentEl.dataset.continuesFromPrev = "true";
66090
+ }
66091
+ if (fragment.continuesOnNext) {
66092
+ fragmentEl.dataset.continuesOnNext = "true";
66093
+ }
66094
+ const markerEl = this.doc.createElement("span");
66095
+ markerEl.classList.add("superdoc-list-marker");
66096
+ const wordLayout = item.paragraph.attrs?.wordLayout;
66097
+ const marker = wordLayout?.marker;
66098
+ if (marker) {
66099
+ markerEl.textContent = marker.markerText ?? null;
66100
+ markerEl.style.display = "inline-block";
66101
+ markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
66102
+ markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
66103
+ markerEl.style.textAlign = marker.justification ?? "";
66104
+ markerEl.style.fontFamily = marker.run.fontFamily;
66105
+ markerEl.style.fontSize = `${marker.run.fontSize}px`;
66106
+ if (marker.run.bold) markerEl.style.fontWeight = "bold";
66107
+ if (marker.run.italic) markerEl.style.fontStyle = "italic";
66108
+ if (marker.run.color) markerEl.style.color = marker.run.color;
66109
+ if (marker.run.letterSpacing) markerEl.style.letterSpacing = `${marker.run.letterSpacing}px`;
66110
+ } else {
66111
+ markerEl.textContent = item.marker.text;
66112
+ markerEl.style.display = "inline-block";
66113
+ markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
66114
+ markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
66115
+ if (item.marker.align) {
66116
+ markerEl.style.textAlign = item.marker.align;
66117
+ }
66118
+ }
66119
+ fragmentEl.appendChild(markerEl);
66120
+ const contentEl = this.doc.createElement("div");
66121
+ contentEl.classList.add("superdoc-list-content");
66122
+ this.applySdtDataset(contentEl, paragraphMetadata);
66123
+ contentEl.style.display = "inline-block";
66124
+ contentEl.style.width = `${fragment.width}px`;
66125
+ const lines = itemMeasure.paragraph.lines.slice(fragment.fromLine, fragment.toLine);
66126
+ const contentAttrs = wordLayout ? item.paragraph.attrs : stripListIndent(item.paragraph.attrs);
66127
+ applyParagraphBlockStyles(contentEl, contentAttrs);
66128
+ lines.forEach((line) => {
66129
+ const lineEl = this.renderLine(item.paragraph, line, context);
66130
+ contentEl.appendChild(lineEl);
66131
+ });
66132
+ fragmentEl.appendChild(contentEl);
66133
+ return fragmentEl;
66134
+ } catch (error) {
66135
+ console.error("[DomPainter] List item fragment rendering failed:", { fragment, error });
66136
+ return this.createErrorPlaceholder(fragment.blockId, error);
65801
66137
  }
65802
- const block = lookup2.block;
65803
- const measure = lookup2.measure;
65804
- const item = block.items.find((entry) => entry.id === fragment.itemId);
65805
- const itemMeasure = measure.items.find((entry) => entry.itemId === fragment.itemId);
65806
- if (!item || !itemMeasure) {
65807
- throw new Error(`DomPainter: missing list item ${fragment.itemId}`);
65808
- }
65809
- const fragmentEl = this.doc.createElement("div");
65810
- fragmentEl.classList.add(CLASS_NAMES.fragment, `${CLASS_NAMES.fragment}-list-item`);
65811
- applyStyles$2(fragmentEl, fragmentStyles);
65812
- fragmentEl.style.left = `${fragment.x - fragment.markerWidth}px`;
65813
- fragmentEl.style.top = `${fragment.y}px`;
65814
- fragmentEl.style.width = `${fragment.markerWidth + fragment.width}px`;
65815
- fragmentEl.dataset.blockId = fragment.blockId;
65816
- fragmentEl.dataset.itemId = fragment.itemId;
65817
- const paragraphMetadata = item.paragraph.attrs?.sdt;
65818
- this.applySdtDataset(fragmentEl, paragraphMetadata);
65819
- if (fragment.continuesFromPrev) {
65820
- fragmentEl.dataset.continuesFromPrev = "true";
65821
- }
65822
- if (fragment.continuesOnNext) {
65823
- fragmentEl.dataset.continuesOnNext = "true";
65824
- }
65825
- const markerEl = this.doc.createElement("span");
65826
- markerEl.classList.add("superdoc-list-marker");
65827
- const wordLayout = item.paragraph.attrs?.wordLayout;
65828
- if (wordLayout?.marker) {
65829
- const marker = wordLayout.marker;
65830
- markerEl.textContent = marker.markerText;
65831
- markerEl.style.display = "inline-block";
65832
- markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
65833
- markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
65834
- markerEl.style.textAlign = marker.justification;
65835
- markerEl.style.fontFamily = marker.run.fontFamily;
65836
- markerEl.style.fontSize = `${marker.run.fontSize}px`;
65837
- if (marker.run.bold) markerEl.style.fontWeight = "bold";
65838
- if (marker.run.italic) markerEl.style.fontStyle = "italic";
65839
- if (marker.run.color) markerEl.style.color = marker.run.color;
65840
- if (marker.run.letterSpacing) markerEl.style.letterSpacing = `${marker.run.letterSpacing}px`;
65841
- } else {
65842
- markerEl.textContent = item.marker.text;
65843
- markerEl.style.display = "inline-block";
65844
- markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
65845
- markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
65846
- if (item.marker.align) {
65847
- markerEl.style.textAlign = item.marker.align;
65848
- }
65849
- }
65850
- fragmentEl.appendChild(markerEl);
65851
- const contentEl = this.doc.createElement("div");
65852
- contentEl.classList.add("superdoc-list-content");
65853
- this.applySdtDataset(contentEl, paragraphMetadata);
65854
- contentEl.style.display = "inline-block";
65855
- contentEl.style.width = `${fragment.width}px`;
65856
- const lines = itemMeasure.paragraph.lines.slice(fragment.fromLine, fragment.toLine);
65857
- const contentAttrs = wordLayout ? item.paragraph.attrs : stripListIndent(item.paragraph.attrs);
65858
- applyParagraphBlockStyles(contentEl, contentAttrs);
65859
- lines.forEach((line) => {
65860
- const lineEl = this.renderLine(item.paragraph, line, context);
65861
- contentEl.appendChild(lineEl);
65862
- });
65863
- fragmentEl.appendChild(contentEl);
65864
- return fragmentEl;
65865
66138
  }
65866
66139
  renderImageFragment(fragment) {
65867
- const lookup2 = this.blockLookup.get(fragment.blockId);
65868
- if (!lookup2 || lookup2.block.kind !== "image" || lookup2.measure.kind !== "image") {
65869
- throw new Error(`DomPainter: missing image block for fragment ${fragment.blockId}`);
65870
- }
65871
- if (!this.doc) {
65872
- throw new Error("DomPainter: document is not available");
65873
- }
65874
- const block = lookup2.block;
65875
- const fragmentEl = this.doc.createElement("div");
65876
- fragmentEl.classList.add(CLASS_NAMES.fragment);
65877
- applyStyles$2(fragmentEl, fragmentStyles);
65878
- this.applyFragmentFrame(fragmentEl, fragment);
65879
- fragmentEl.style.height = `${fragment.height}px`;
65880
- this.applySdtDataset(fragmentEl, block.attrs?.sdt);
65881
- this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
65882
- if (fragment.isAnchored && fragment.zIndex != null) {
65883
- fragmentEl.style.zIndex = String(fragment.zIndex);
65884
- }
65885
- const img = this.doc.createElement("img");
65886
- if (block.src) {
65887
- img.src = block.src;
66140
+ try {
66141
+ const lookup2 = this.blockLookup.get(fragment.blockId);
66142
+ if (!lookup2 || lookup2.block.kind !== "image" || lookup2.measure.kind !== "image") {
66143
+ throw new Error(`DomPainter: missing image block for fragment ${fragment.blockId}`);
66144
+ }
66145
+ if (!this.doc) {
66146
+ throw new Error("DomPainter: document is not available");
66147
+ }
66148
+ const block = lookup2.block;
66149
+ const fragmentEl = this.doc.createElement("div");
66150
+ fragmentEl.classList.add(CLASS_NAMES.fragment);
66151
+ applyStyles$2(fragmentEl, fragmentStyles);
66152
+ this.applyFragmentFrame(fragmentEl, fragment);
66153
+ fragmentEl.style.height = `${fragment.height}px`;
66154
+ this.applySdtDataset(fragmentEl, block.attrs?.sdt);
66155
+ this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
66156
+ if (fragment.isAnchored && fragment.zIndex != null) {
66157
+ fragmentEl.style.zIndex = String(fragment.zIndex);
66158
+ }
66159
+ const img = this.doc.createElement("img");
66160
+ if (block.src) {
66161
+ img.src = block.src;
66162
+ }
66163
+ img.alt = block.alt ?? "";
66164
+ img.style.width = "100%";
66165
+ img.style.height = "100%";
66166
+ img.style.objectFit = block.objectFit ?? "contain";
66167
+ img.style.display = block.display === "inline" ? "inline-block" : "block";
66168
+ fragmentEl.appendChild(img);
66169
+ return fragmentEl;
66170
+ } catch (error) {
66171
+ console.error("[DomPainter] Image fragment rendering failed:", { fragment, error });
66172
+ return this.createErrorPlaceholder(fragment.blockId, error);
65888
66173
  }
65889
- img.alt = block.alt ?? "";
65890
- img.style.width = "100%";
65891
- img.style.height = "100%";
65892
- img.style.objectFit = block.objectFit ?? "contain";
65893
- img.style.display = block.display === "inline" ? "inline-block" : "block";
65894
- fragmentEl.appendChild(img);
65895
- return fragmentEl;
65896
66174
  }
65897
66175
  renderDrawingFragment(fragment) {
65898
- const lookup2 = this.blockLookup.get(fragment.blockId);
65899
- if (!lookup2 || lookup2.block.kind !== "drawing" || lookup2.measure.kind !== "drawing") {
65900
- throw new Error(`DomPainter: missing drawing block for fragment ${fragment.blockId}`);
65901
- }
65902
- if (!this.doc) {
65903
- throw new Error("DomPainter: document is not available");
66176
+ try {
66177
+ const lookup2 = this.blockLookup.get(fragment.blockId);
66178
+ if (!lookup2 || lookup2.block.kind !== "drawing" || lookup2.measure.kind !== "drawing") {
66179
+ throw new Error(`DomPainter: missing drawing block for fragment ${fragment.blockId}`);
66180
+ }
66181
+ if (!this.doc) {
66182
+ throw new Error("DomPainter: document is not available");
66183
+ }
66184
+ const block = lookup2.block;
66185
+ const isVectorShapeBlock = block.kind === "drawing" && block.drawingKind === "vectorShape";
66186
+ const fragmentEl = this.doc.createElement("div");
66187
+ fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-drawing-fragment");
66188
+ applyStyles$2(fragmentEl, fragmentStyles);
66189
+ this.applyFragmentFrame(fragmentEl, fragment);
66190
+ fragmentEl.style.height = `${fragment.height}px`;
66191
+ fragmentEl.style.position = "absolute";
66192
+ if (fragment.isAnchored && fragment.zIndex != null) {
66193
+ fragmentEl.style.zIndex = String(fragment.zIndex);
66194
+ }
66195
+ const innerWrapper = this.doc.createElement("div");
66196
+ innerWrapper.classList.add("superdoc-drawing-inner");
66197
+ innerWrapper.style.position = "absolute";
66198
+ innerWrapper.style.left = "50%";
66199
+ innerWrapper.style.top = "50%";
66200
+ innerWrapper.style.width = `${fragment.geometry.width}px`;
66201
+ innerWrapper.style.height = `${fragment.geometry.height}px`;
66202
+ innerWrapper.style.transformOrigin = "center";
66203
+ const scale = fragment.scale ?? 1;
66204
+ const transforms = ["translate(-50%, -50%)"];
66205
+ if (!isVectorShapeBlock) {
66206
+ transforms.push(`rotate(${fragment.geometry.rotation ?? 0}deg)`);
66207
+ transforms.push(`scaleX(${fragment.geometry.flipH ? -1 : 1})`);
66208
+ transforms.push(`scaleY(${fragment.geometry.flipV ? -1 : 1})`);
66209
+ }
66210
+ transforms.push(`scale(${scale})`);
66211
+ innerWrapper.style.transform = transforms.join(" ");
66212
+ innerWrapper.appendChild(this.renderDrawingContent(block, fragment));
66213
+ fragmentEl.appendChild(innerWrapper);
66214
+ return fragmentEl;
66215
+ } catch (error) {
66216
+ console.error("[DomPainter] Drawing fragment rendering failed:", { fragment, error });
66217
+ return this.createErrorPlaceholder(fragment.blockId, error);
65904
66218
  }
65905
- const block = lookup2.block;
65906
- const isVectorShapeBlock = block.kind === "drawing" && block.drawingKind === "vectorShape";
65907
- const fragmentEl = this.doc.createElement("div");
65908
- fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-drawing-fragment");
65909
- applyStyles$2(fragmentEl, fragmentStyles);
65910
- this.applyFragmentFrame(fragmentEl, fragment);
65911
- fragmentEl.style.height = `${fragment.height}px`;
65912
- fragmentEl.style.position = "absolute";
65913
- if (fragment.isAnchored && fragment.zIndex != null) {
65914
- fragmentEl.style.zIndex = String(fragment.zIndex);
65915
- }
65916
- const innerWrapper = this.doc.createElement("div");
65917
- innerWrapper.classList.add("superdoc-drawing-inner");
65918
- innerWrapper.style.position = "absolute";
65919
- innerWrapper.style.left = "50%";
65920
- innerWrapper.style.top = "50%";
65921
- innerWrapper.style.width = `${fragment.geometry.width}px`;
65922
- innerWrapper.style.height = `${fragment.geometry.height}px`;
65923
- innerWrapper.style.transformOrigin = "center";
65924
- const scale = fragment.scale ?? 1;
65925
- const transforms = ["translate(-50%, -50%)"];
65926
- if (!isVectorShapeBlock) {
65927
- transforms.push(`rotate(${fragment.geometry.rotation ?? 0}deg)`);
65928
- transforms.push(`scaleX(${fragment.geometry.flipH ? -1 : 1})`);
65929
- transforms.push(`scaleY(${fragment.geometry.flipV ? -1 : 1})`);
65930
- }
65931
- transforms.push(`scale(${scale})`);
65932
- innerWrapper.style.transform = transforms.join(" ");
65933
- innerWrapper.appendChild(this.renderDrawingContent(block, fragment));
65934
- fragmentEl.appendChild(innerWrapper);
65935
- return fragmentEl;
65936
66219
  }
65937
66220
  renderDrawingContent(block, fragment) {
65938
66221
  if (!this.doc) {
@@ -66367,6 +66650,7 @@ const _DomPainter = class _DomPainter2 {
66367
66650
  }
66368
66651
  applyRunStyles(elem, run2, isActiveLink);
66369
66652
  elem.style.zIndex = "1";
66653
+ applyRunDataAttributes(elem, run2.dataAttrs);
66370
66654
  if (run2.pmStart != null) elem.dataset.pmStart = String(run2.pmStart);
66371
66655
  if (run2.pmEnd != null) elem.dataset.pmEnd = String(run2.pmEnd);
66372
66656
  if (trackedConfig) {
@@ -66565,6 +66849,33 @@ const _DomPainter = class _DomPainter2 {
66565
66849
  }
66566
66850
  }
66567
66851
  }
66852
+ /**
66853
+ * Estimates the height of a fragment when explicit height is not available.
66854
+ *
66855
+ * This method provides fallback height calculations for footer bottom-alignment
66856
+ * by consulting measure data for paragraphs and list items, or using the
66857
+ * fragment's height property for tables, images, and drawings.
66858
+ *
66859
+ * @param fragment - The fragment to estimate height for
66860
+ * @returns Estimated height in pixels, or 0 if height cannot be determined
66861
+ */
66862
+ estimateFragmentHeight(fragment) {
66863
+ const lookup2 = this.blockLookup.get(fragment.blockId);
66864
+ const measure = lookup2?.measure;
66865
+ if (fragment.kind === "para" && measure?.kind === "paragraph") {
66866
+ return measure.totalHeight;
66867
+ }
66868
+ if (fragment.kind === "list-item" && measure?.kind === "list") {
66869
+ return measure.totalHeight;
66870
+ }
66871
+ if (fragment.kind === "table") {
66872
+ return fragment.height;
66873
+ }
66874
+ if (fragment.kind === "image" || fragment.kind === "drawing") {
66875
+ return fragment.height;
66876
+ }
66877
+ return 0;
66878
+ }
66568
66879
  buildBlockLookup(blocks, measures) {
66569
66880
  if (blocks.length !== measures.length) {
66570
66881
  throw new Error("DomPainter requires the same number of blocks and measures");
@@ -66747,6 +67058,12 @@ const deriveBlockVersion = (block) => {
66747
67058
  run2.kind !== "tab" && run2.bold ? 1 : 0,
66748
67059
  run2.kind !== "tab" && run2.italic ? 1 : 0,
66749
67060
  run2.kind !== "tab" ? run2.color ?? "" : "",
67061
+ // Text decorations - ensures DOM updates when decoration properties change.
67062
+ run2.kind !== "tab" ? run2.underline?.style ?? "" : "",
67063
+ run2.kind !== "tab" ? run2.underline?.color ?? "" : "",
67064
+ run2.kind !== "tab" && run2.strike ? 1 : 0,
67065
+ run2.kind !== "tab" ? run2.highlight ?? "" : "",
67066
+ run2.kind !== "tab" && run2.letterSpacing != null ? run2.letterSpacing : "",
66750
67067
  run2.pmStart ?? "",
66751
67068
  run2.pmEnd ?? "",
66752
67069
  run2.kind !== "tab" ? run2.token ?? "" : ""
@@ -66841,6 +67158,20 @@ const applyRunStyles = (element, run2, isLink = false) => {
66841
67158
  element.style.textDecorationLine = decorations.join(" ");
66842
67159
  }
66843
67160
  };
67161
+ const applyRunDataAttributes = (element, dataAttrs) => {
67162
+ if (!dataAttrs) return;
67163
+ Object.entries(dataAttrs).forEach(([key2, value]) => {
67164
+ if (typeof key2 !== "string" || !key2.toLowerCase().startsWith("data-")) return;
67165
+ if (typeof value !== "string") return;
67166
+ try {
67167
+ element.setAttribute(key2, value);
67168
+ } catch (error) {
67169
+ if (process$1$1.env.NODE_ENV === "development") {
67170
+ console.warn(`[DomPainter] Failed to set data attribute "${key2}":`, error);
67171
+ }
67172
+ }
67173
+ });
67174
+ };
66844
67175
  const applyParagraphBlockStyles = (element, attrs) => {
66845
67176
  if (!attrs) return;
66846
67177
  if (attrs.alignment) {
@@ -67013,8 +67344,8 @@ const createDomPainter = (options) => {
67013
67344
  paint(layout, mount2) {
67014
67345
  painter.paint(layout, mount2);
67015
67346
  },
67016
- setData(blocks, measures) {
67017
- painter.setData(blocks, measures);
67347
+ setData(blocks, measures, headerBlocks, headerMeasures, footerBlocks, footerMeasures) {
67348
+ painter.setData(blocks, measures, headerBlocks, headerMeasures, footerBlocks, footerMeasures);
67018
67349
  },
67019
67350
  // Non-standard extension for demo app to avoid re-instantiating on provider changes
67020
67351
  setProviders(header, footer) {
@@ -70403,7 +70734,30 @@ rerender_fn = async function() {
70403
70734
  if (typeof painter.setProviders === "function") {
70404
70735
  painter.setProviders(__privateGet$1(this, _headerDecorationProvider), __privateGet$1(this, _footerDecorationProvider));
70405
70736
  }
70406
- painter.setData?.(blocks, measures);
70737
+ const headerBlocks = [];
70738
+ const headerMeasures = [];
70739
+ if (headerLayouts) {
70740
+ for (const headerResult of headerLayouts) {
70741
+ headerBlocks.push(...headerResult.blocks);
70742
+ headerMeasures.push(...headerResult.measures);
70743
+ }
70744
+ }
70745
+ const footerBlocks = [];
70746
+ const footerMeasures = [];
70747
+ if (footerLayouts) {
70748
+ for (const footerResult of footerLayouts) {
70749
+ footerBlocks.push(...footerResult.blocks);
70750
+ footerMeasures.push(...footerResult.measures);
70751
+ }
70752
+ }
70753
+ painter.setData?.(
70754
+ blocks,
70755
+ measures,
70756
+ headerBlocks.length > 0 ? headerBlocks : void 0,
70757
+ headerMeasures.length > 0 ? headerMeasures : void 0,
70758
+ footerBlocks.length > 0 ? footerBlocks : void 0,
70759
+ footerMeasures.length > 0 ? footerMeasures : void 0
70760
+ );
70407
70761
  painter.paint(layout, __privateGet$1(this, _painterHost));
70408
70762
  __privateSet(this, _layoutError, null);
70409
70763
  __privateSet(this, _layoutErrorState, "healthy");
@@ -70573,7 +70927,8 @@ createDecorationProvider_fn = function(kind, layout) {
70573
70927
  const finalHeaderId = headerId ?? fallbackId ?? void 0;
70574
70928
  return {
70575
70929
  fragments: slotPage.fragments,
70576
- height: variant.layout.height ?? box.height,
70930
+ height: box.height,
70931
+ contentHeight: variant.layout.height ?? box.height,
70577
70932
  offset: box.offset,
70578
70933
  marginLeft: box.x,
70579
70934
  contentWidth: box.width,
@@ -70600,18 +70955,19 @@ computeDecorationBox_fn = function(kind, pageMargins, pageHeight) {
70600
70955
  const left2 = margins.left ?? DEFAULT_MARGINS.left;
70601
70956
  const right2 = margins.right ?? DEFAULT_MARGINS.right;
70602
70957
  const width = Math.max(pageSize.w - (left2 + right2), 1);
70603
- const defaultHeight = kind === "header" ? margins.top ?? DEFAULT_MARGINS.top : margins.bottom ?? DEFAULT_MARGINS.bottom;
70604
- const { headerSpace, footerSpace } = extractHeaderFooterSpace(margins);
70605
- const target = kind === "header" ? headerSpace : footerSpace;
70606
- const height = Math.max(target || defaultHeight || 1, 1);
70607
70958
  const totalHeight = pageHeight ?? pageSize.h;
70608
- const offset2 = kind === "header" ? 0 : Math.max(0, totalHeight - height);
70609
- return {
70610
- x: left2,
70611
- width,
70612
- height,
70613
- offset: offset2
70614
- };
70959
+ if (kind === "header") {
70960
+ const headerMargin = margins.header ?? 0;
70961
+ const topMargin = margins.top ?? DEFAULT_MARGINS.top ?? 0;
70962
+ const height = Math.max(topMargin - headerMargin, 1);
70963
+ return { x: left2, width, height, offset: headerMargin };
70964
+ } else {
70965
+ const footerMargin = margins.footer ?? 0;
70966
+ const bottomMargin = margins.bottom ?? DEFAULT_MARGINS.bottom ?? 0;
70967
+ const height = Math.max(bottomMargin - footerMargin, 1);
70968
+ const offset2 = Math.max(0, totalHeight - footerMargin - height);
70969
+ return { x: left2, width, height, offset: offset2 };
70970
+ }
70615
70971
  };
70616
70972
  rebuildHeaderFooterRegions_fn = function(layout) {
70617
70973
  __privateGet$1(this, _headerRegions).clear();
@@ -70828,7 +71184,8 @@ getHeaderFooterPageHeight_fn = function() {
70828
71184
  return context.layout.pageSize?.h ?? context.region.height ?? 1;
70829
71185
  };
70830
71186
  renderSelectionRects_fn = function(rects) {
70831
- if (!__privateGet$1(this, _selectionOverlay)) {
71187
+ const localSelectionLayer = __privateGet$1(this, _localSelectionLayer);
71188
+ if (!localSelectionLayer) {
70832
71189
  return;
70833
71190
  }
70834
71191
  const pageHeight = __privateMethod$1(this, _PresentationEditor_instances, getBodyPageHeight_fn).call(this);
@@ -70839,7 +71196,7 @@ renderSelectionRects_fn = function(rects) {
70839
71196
  if (!coords) {
70840
71197
  return;
70841
71198
  }
70842
- const highlight = __privateGet$1(this, _selectionOverlay).ownerDocument?.createElement("div");
71199
+ const highlight = localSelectionLayer.ownerDocument?.createElement("div");
70843
71200
  if (!highlight) {
70844
71201
  return;
70845
71202
  }
@@ -70852,7 +71209,7 @@ renderSelectionRects_fn = function(rects) {
70852
71209
  highlight.style.backgroundColor = "rgba(51, 132, 255, 0.35)";
70853
71210
  highlight.style.borderRadius = "2px";
70854
71211
  highlight.style.pointerEvents = "none";
70855
- __privateGet$1(this, _selectionOverlay).appendChild(highlight);
71212
+ localSelectionLayer.appendChild(highlight);
70856
71213
  });
70857
71214
  };
70858
71215
  renderHoverRegion_fn = function(region) {
@@ -71302,6 +71659,7 @@ class PresentationInputBridge {
71302
71659
  __privateAdd$1(this, _onTargetChanged);
71303
71660
  __privateAdd$1(this, _listeners);
71304
71661
  __privateAdd$1(this, _currentTarget, null);
71662
+ __privateAdd$1(this, _destroyed, false);
71305
71663
  __privateSet(this, _windowRoot, windowRoot);
71306
71664
  __privateSet(this, _visibleHost2, visibleHost);
71307
71665
  __privateSet(this, _getTargetDom, getTargetDom);
@@ -71329,9 +71687,13 @@ class PresentationInputBridge {
71329
71687
  });
71330
71688
  __privateSet(this, _listeners, []);
71331
71689
  __privateSet(this, _currentTarget, null);
71690
+ __privateSet(this, _destroyed, true);
71332
71691
  }
71333
71692
  notifyTargetChanged() {
71334
71693
  var _a2;
71694
+ if (__privateGet$1(this, _destroyed)) {
71695
+ return;
71696
+ }
71335
71697
  const nextTarget = __privateGet$1(this, _getTargetDom).call(this);
71336
71698
  if (nextTarget === __privateGet$1(this, _currentTarget)) {
71337
71699
  return;
@@ -71361,6 +71723,7 @@ _getTargetDom = /* @__PURE__ */ new WeakMap();
71361
71723
  _onTargetChanged = /* @__PURE__ */ new WeakMap();
71362
71724
  _listeners = /* @__PURE__ */ new WeakMap();
71363
71725
  _currentTarget = /* @__PURE__ */ new WeakMap();
71726
+ _destroyed = /* @__PURE__ */ new WeakMap();
71364
71727
  _PresentationInputBridge_instances = /* @__PURE__ */ new WeakSet();
71365
71728
  addListener_fn = function(type2, handler2, target) {
71366
71729
  const bound = handler2.bind(this);
@@ -71368,12 +71731,21 @@ addListener_fn = function(type2, handler2, target) {
71368
71731
  target.addEventListener(type2, bound, true);
71369
71732
  };
71370
71733
  dispatchToTarget_fn = function(originalEvent, synthetic) {
71734
+ if (__privateGet$1(this, _destroyed)) return;
71371
71735
  const target = __privateGet$1(this, _getTargetDom).call(this);
71372
71736
  __privateSet(this, _currentTarget, target);
71373
71737
  if (!target) return;
71374
- const canceled = !target.dispatchEvent(synthetic) || synthetic.defaultPrevented;
71375
- if (canceled) {
71376
- originalEvent.preventDefault();
71738
+ const isConnected = target.isConnected;
71739
+ if (isConnected === false) return;
71740
+ try {
71741
+ const canceled = !target.dispatchEvent(synthetic) || synthetic.defaultPrevented;
71742
+ if (canceled) {
71743
+ originalEvent.preventDefault();
71744
+ }
71745
+ } catch (error) {
71746
+ if (process$1$1.env.NODE_ENV === "development") {
71747
+ console.warn("[PresentationEditor] Failed to dispatch event to target:", error);
71748
+ }
71377
71749
  }
71378
71750
  };
71379
71751
  forwardKeyboardEvent_fn = function(event) {
@@ -100263,7 +100635,7 @@ var __accessCheck = (obj, member, msg2) => member.has(obj) || __typeError("Canno
100263
100635
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
100264
100636
  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);
100265
100637
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
100266
- var _SuperToolbar_instances, initToolbarGroups_fn, _interceptedCommands, makeToolbarItems_fn, initDefaultFonts_fn, updateHighlightColors_fn, deactivateAll_fn, updateToolbarHistory_fn, enrichTrackedChanges_fn, runCommandWithArgumentOnly_fn;
100638
+ 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;
100267
100639
  var eventemitter3 = { exports: {} };
100268
100640
  var hasRequiredEventemitter3;
100269
100641
  function requireEventemitter3() {
@@ -100482,7 +100854,7 @@ const useToolbarItem = (options) => {
100482
100854
  if (!Array.isArray(options.options)) throw new Error("Invalid toolbar item options - " + options.options);
100483
100855
  nestedOptions.value?.push(...options.options);
100484
100856
  }
100485
- const activate = (attrs, ...args) => {
100857
+ const activate = (attrs = {}, ...args) => {
100486
100858
  onActivate(attrs, ...args);
100487
100859
  if (suppressActiveHighlight.value) return;
100488
100860
  active.value = true;
@@ -102754,7 +103126,7 @@ const isNegatedMark = (name, attrs = {}) => {
102754
103126
  if (typeof checker !== "function") return false;
102755
103127
  return Boolean(checker(attrs));
102756
103128
  };
102757
- class SuperToolbar extends EventEmitter2 {
103129
+ const _SuperToolbar = class _SuperToolbar2 extends EventEmitter2 {
102758
103130
  /**
102759
103131
  * Creates a new SuperToolbar instance
102760
103132
  * @param {ToolbarConfig} config - The configuration for the toolbar
@@ -102798,11 +103170,11 @@ class SuperToolbar extends EventEmitter2 {
102798
103170
  const isSmallScreen = window.matchMedia("(max-width: 834px)").matches;
102799
103171
  if (isMobileDevice && isSmallScreen) {
102800
103172
  layers.style.transformOrigin = "0 0";
102801
- layers.style.transform = `scale(${parseInt(argument) / 100})`;
103173
+ layers.style.transform = `scale(${parseInt(argument, 10) / 100})`;
102802
103174
  } else {
102803
- layers.style.zoom = parseInt(argument) / 100;
103175
+ layers.style.zoom = parseInt(argument, 10) / 100;
102804
103176
  }
102805
- this.superdoc.superdocStore.activeZoom = parseInt(argument);
103177
+ this.superdoc.superdocStore.activeZoom = parseInt(argument, 10);
102806
103178
  },
102807
103179
  /**
102808
103180
  * Sets the document mode
@@ -102884,31 +103256,37 @@ class SuperToolbar extends EventEmitter2 {
102884
103256
  * @returns {Promise<void>}
102885
103257
  */
102886
103258
  startImageUpload: async () => {
102887
- let open = getFileOpener();
102888
- let result = await open();
102889
- if (!result?.file) {
102890
- return;
102891
- }
102892
- const { size: size2, file } = await checkAndProcessImage({
102893
- file: result.file,
102894
- getMaxContentSize: () => this.activeEditor.getMaxContentSize()
102895
- });
102896
- if (!file) {
102897
- return;
103259
+ try {
103260
+ let open = getFileOpener();
103261
+ let result = await open();
103262
+ if (!result?.file) {
103263
+ return;
103264
+ }
103265
+ const { size: size2, file } = await checkAndProcessImage({
103266
+ file: result.file,
103267
+ getMaxContentSize: () => this.activeEditor.getMaxContentSize()
103268
+ });
103269
+ if (!file) {
103270
+ return;
103271
+ }
103272
+ const id = {};
103273
+ replaceSelectionWithImagePlaceholder({
103274
+ view: this.activeEditor.view,
103275
+ editorOptions: this.activeEditor.options,
103276
+ id
103277
+ });
103278
+ await uploadAndInsertImage({
103279
+ editor: this.activeEditor,
103280
+ view: this.activeEditor.view,
103281
+ file,
103282
+ size: size2,
103283
+ id
103284
+ });
103285
+ } catch (error) {
103286
+ const err = new Error("[super-toolbar 🎨] Image upload failed");
103287
+ this.emit("exception", { error: err, editor: this.activeEditor, originalError: error });
103288
+ console.error(err, error);
102898
103289
  }
102899
- const id = {};
102900
- replaceSelectionWithImagePlaceholder({
102901
- view: this.activeEditor.view,
102902
- editorOptions: this.activeEditor.options,
102903
- id
102904
- });
102905
- await uploadAndInsertImage({
102906
- editor: this.activeEditor,
102907
- view: this.activeEditor.view,
102908
- file,
102909
- size: size2,
102910
- id
102911
- });
102912
103290
  },
102913
103291
  /**
102914
103292
  * Increases text indentation or list level
@@ -103077,6 +103455,13 @@ class SuperToolbar extends EventEmitter2 {
103077
103455
  };
103078
103456
  this.config.hideButtons = config2.hideButtons ?? true;
103079
103457
  this.config.responsiveToContainer = config2.responsiveToContainer ?? false;
103458
+ this.pendingMarkCommands = [];
103459
+ this.stickyStoredMarks = null;
103460
+ this._boundEditorHandlers = {
103461
+ transaction: null,
103462
+ selectionUpdate: null,
103463
+ focus: null
103464
+ };
103080
103465
  if (!this.config.selector && this.config.element) {
103081
103466
  this.config.selector = this.config.element;
103082
103467
  }
@@ -103136,12 +103521,28 @@ class SuperToolbar extends EventEmitter2 {
103136
103521
  }
103137
103522
  /**
103138
103523
  * The toolbar expects an active Super Editor instance.
103139
- * @param {Object} editor - The editor instance to attach to the toolbar
103524
+ * Removes listeners from the previous editor (if any) before attaching to the new one.
103525
+ * @param {Object|null} editor - The editor instance to attach to the toolbar, or null to detach
103140
103526
  * @returns {void}
103141
103527
  */
103142
103528
  setActiveEditor(editor) {
103529
+ if (this.activeEditor && this._boundEditorHandlers.transaction) {
103530
+ this.activeEditor.off("transaction", this._boundEditorHandlers.transaction);
103531
+ this.activeEditor.off("selectionUpdate", this._boundEditorHandlers.selectionUpdate);
103532
+ this.activeEditor.off("focus", this._boundEditorHandlers.focus);
103533
+ this._boundEditorHandlers.transaction = null;
103534
+ this._boundEditorHandlers.selectionUpdate = null;
103535
+ this._boundEditorHandlers.focus = null;
103536
+ }
103143
103537
  this.activeEditor = editor;
103144
- this.activeEditor.on("transaction", this.onEditorTransaction.bind(this));
103538
+ if (editor) {
103539
+ this._boundEditorHandlers.transaction = this.onEditorTransaction.bind(this);
103540
+ this._boundEditorHandlers.selectionUpdate = this.onEditorSelectionUpdate.bind(this);
103541
+ this._boundEditorHandlers.focus = this.onEditorFocus.bind(this);
103542
+ this.activeEditor.on("transaction", this._boundEditorHandlers.transaction);
103543
+ this.activeEditor.on("selectionUpdate", this._boundEditorHandlers.selectionUpdate);
103544
+ this.activeEditor.on("focus", this._boundEditorHandlers.focus);
103545
+ }
103145
103546
  }
103146
103547
  /**
103147
103548
  * Get toolbar items by group name
@@ -103289,15 +103690,28 @@ class SuperToolbar extends EventEmitter2 {
103289
103690
  * @returns {*} The result of the executed command, undefined if no result is returned
103290
103691
  */
103291
103692
  emitCommand({ item, argument, option }) {
103693
+ const hasFocusFn = this.activeEditor?.view?.hasFocus;
103694
+ const wasFocused = Boolean(typeof hasFocusFn === "function" && hasFocusFn.call(this.activeEditor.view));
103695
+ const { command: command2 } = item;
103696
+ const isMarkToggle = this.isMarkToggle(item);
103697
+ if (!wasFocused && isMarkToggle) {
103698
+ this.pendingMarkCommands.push({ command: command2, argument, item });
103699
+ item?.activate?.();
103700
+ if (this.activeEditor && !this.activeEditor.options.isHeaderOrFooter) {
103701
+ this.activeEditor.focus();
103702
+ }
103703
+ return;
103704
+ }
103292
103705
  if (this.activeEditor && !this.activeEditor.options.isHeaderOrFooter) {
103293
103706
  this.activeEditor.focus();
103294
103707
  }
103295
- const { command: command2 } = item;
103296
103708
  if (!command2) {
103297
103709
  return;
103298
103710
  }
103299
103711
  if (command2 in __privateGet(this, _interceptedCommands)) {
103300
- return __privateGet(this, _interceptedCommands)[command2]({ item, argument });
103712
+ const result = __privateGet(this, _interceptedCommands)[command2]({ item, argument });
103713
+ if (isMarkToggle) __privateMethod(this, _SuperToolbar_instances, syncStickyMarksFromState_fn).call(this);
103714
+ return result;
103301
103715
  }
103302
103716
  if (this.activeEditor && this.activeEditor.commands && command2 in this.activeEditor.commands) {
103303
103717
  this.activeEditor.commands[command2](argument);
@@ -103308,9 +103722,67 @@ class SuperToolbar extends EventEmitter2 {
103308
103722
  this.emit("exception", { error, editor: this.activeEditor });
103309
103723
  throw error;
103310
103724
  }
103725
+ if (isMarkToggle) __privateMethod(this, _SuperToolbar_instances, syncStickyMarksFromState_fn).call(this);
103311
103726
  this.updateToolbarState();
103312
103727
  }
103313
- }
103728
+ /**
103729
+ * Processes and executes pending mark commands when editor selection updates.
103730
+ * This is triggered by the editor's 'selectionUpdate' event after focus is restored.
103731
+ * Clears the pending queue after execution.
103732
+ * @returns {void}
103733
+ */
103734
+ onEditorSelectionUpdate() {
103735
+ if (!this.activeEditor) return;
103736
+ if (this.pendingMarkCommands.length) {
103737
+ const pending = this.pendingMarkCommands;
103738
+ this.pendingMarkCommands = [];
103739
+ pending.forEach(({ command: command2, argument, item }) => {
103740
+ if (!command2) return;
103741
+ try {
103742
+ if (command2 in __privateGet(this, _interceptedCommands)) {
103743
+ __privateGet(this, _interceptedCommands)[command2]({ item, argument });
103744
+ } else if (this.activeEditor.commands && command2 in this.activeEditor.commands) {
103745
+ this.activeEditor.commands[command2](argument);
103746
+ }
103747
+ __privateMethod(this, _SuperToolbar_instances, ensureStoredMarksForMarkToggle_fn).call(this, { command: command2, argument });
103748
+ } catch (error) {
103749
+ const err = new Error(`[super-toolbar 🎨] Failed to execute pending command: ${command2}`);
103750
+ this.emit("exception", { error: err, editor: this.activeEditor, originalError: error });
103751
+ console.error(err, error);
103752
+ }
103753
+ });
103754
+ __privateMethod(this, _SuperToolbar_instances, syncStickyMarksFromState_fn).call(this);
103755
+ this.updateToolbarState();
103756
+ return;
103757
+ }
103758
+ const restored = __privateMethod(this, _SuperToolbar_instances, restoreStickyMarksIfNeeded_fn).call(this);
103759
+ if (restored) this.updateToolbarState();
103760
+ }
103761
+ /**
103762
+ * Handles editor focus events by flushing any pending mark commands.
103763
+ * This is triggered by the editor's 'focus' event.
103764
+ * @returns {void}
103765
+ */
103766
+ onEditorFocus() {
103767
+ if (this.pendingMarkCommands.length) {
103768
+ this.onEditorSelectionUpdate();
103769
+ return;
103770
+ }
103771
+ const restored = __privateMethod(this, _SuperToolbar_instances, restoreStickyMarksIfNeeded_fn).call(this);
103772
+ if (restored) this.updateToolbarState();
103773
+ }
103774
+ /**
103775
+ * Determines if a toolbar item represents a mark toggle command.
103776
+ * Mark toggles include text formatting commands like bold, italic, underline, etc.
103777
+ * @param {ToolbarItem} item - The toolbar item to check
103778
+ * @returns {boolean} True if the item is a mark toggle, false otherwise
103779
+ */
103780
+ isMarkToggle(item) {
103781
+ const name = item?.name?.value;
103782
+ return __privateGet(_SuperToolbar2, _MARK_TOGGLE_NAMES).has(name);
103783
+ }
103784
+ };
103785
+ _MARK_TOGGLE_NAMES = /* @__PURE__ */ new WeakMap();
103314
103786
  _SuperToolbar_instances = /* @__PURE__ */ new WeakSet();
103315
103787
  initToolbarGroups_fn = function() {
103316
103788
  if (this.config.groups && !Array.isArray(this.config.groups) && Object.keys(this.config.groups).length) {
@@ -103423,6 +103895,55 @@ runCommandWithArgumentOnly_fn = function({ item, argument, noArgumentCallback =
103423
103895
  this.updateToolbarState();
103424
103896
  }
103425
103897
  };
103898
+ syncStickyMarksFromState_fn = function() {
103899
+ if (!this.activeEditor) return;
103900
+ const { selection, storedMarks } = this.activeEditor.state || {};
103901
+ if (!selection?.empty) return;
103902
+ this.stickyStoredMarks = storedMarks?.length ? [...storedMarks] : null;
103903
+ };
103904
+ restoreStickyMarksIfNeeded_fn = function() {
103905
+ if (!this.activeEditor) return false;
103906
+ if (!this.stickyStoredMarks?.length) return false;
103907
+ const { state: state2, view } = this.activeEditor;
103908
+ const { selection, storedMarks } = state2 || {};
103909
+ if (!selection?.empty) return false;
103910
+ if (storedMarks?.length) return false;
103911
+ if (!view?.dispatch || !state2?.tr) return false;
103912
+ const hasActiveMarkToggle = getActiveFormatting(this.activeEditor).some(
103913
+ (mark) => __privateGet(_SuperToolbar, _MARK_TOGGLE_NAMES).has(mark.name)
103914
+ );
103915
+ if (hasActiveMarkToggle) return false;
103916
+ const tr = state2.tr.setStoredMarks(this.stickyStoredMarks);
103917
+ view.dispatch(tr);
103918
+ return true;
103919
+ };
103920
+ ensureStoredMarksForMarkToggle_fn = function({ command: command2, argument }) {
103921
+ if (!this.activeEditor) return;
103922
+ if (!this.activeEditor.state?.selection?.empty) return;
103923
+ if (this.activeEditor.state?.storedMarks?.length) return;
103924
+ if (command2 !== "setFontSize") return;
103925
+ const { state: state2, view } = this.activeEditor;
103926
+ const textStyleMark = state2.schema?.marks?.textStyle;
103927
+ if (!textStyleMark || !view?.dispatch || !state2?.tr) return;
103928
+ const [value, unit] = parseSizeUnit(argument ?? "");
103929
+ if (Number.isNaN(value)) return;
103930
+ const clamped = Math.min(96, Math.max(8, Number(value)));
103931
+ const resolvedUnit = unit || "pt";
103932
+ const mark = textStyleMark.create({ fontSize: `${clamped}${resolvedUnit}` });
103933
+ const tr = state2.tr.setStoredMarks([mark]);
103934
+ view.dispatch(tr);
103935
+ };
103936
+ __privateAdd(_SuperToolbar, _MARK_TOGGLE_NAMES, /* @__PURE__ */ new Set([
103937
+ "bold",
103938
+ "italic",
103939
+ "underline",
103940
+ "strike",
103941
+ "highlight",
103942
+ "color",
103943
+ "fontSize",
103944
+ "fontFamily"
103945
+ ]));
103946
+ let SuperToolbar = _SuperToolbar;
103426
103947
  const onMarginClickCursorChange = (event, editor) => {
103427
103948
  const y2 = event.clientY;
103428
103949
  const x2 = event.clientX;