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
@@ -9,11 +9,11 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
9
9
  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);
10
10
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
11
11
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
12
- 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;
12
+ 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;
13
13
  import * as Y from "yjs";
14
14
  import { UndoManager, Item as Item$1, ContentType, Text as Text$1, XmlElement, encodeStateAsUpdate } from "yjs";
15
- import { P as PluginKey, a as Plugin, M as Mapping, N as NodeSelection, S as Selection, T as TextSelection, b as Slice, D as DOMSerializer, F as Fragment, c as DOMParser$1, d as Mark$1, e as dropPoint, A as AllSelection, p as process$1, B as Buffer2, f as callOrGet, g as getExtensionConfigField, h as getMarkType, i as getMarksFromSelection, j as getNodeType, k as getSchemaTypeNameByName, l as Schema$1, m as cleanSchemaItem, n as canSplit, o as defaultBlockAt$1, q as liftTarget, r as canJoin, s as joinPoint, t as replaceStep$1, R as ReplaceAroundStep$1, u as isTextSelection, v as getMarkRange, w as isMarkActive, x as isNodeActive, y as deleteProps, z as processContent, C as htmlHandler, E as ReplaceStep, G as twipsToInches, H as inchesToTwips, I as ptToTwips, J as getResolvedParagraphProperties, K as linesToTwips, L as ListHelpers, O as updateNumberingProperties, Q as changeListLevel, U as findParentNode, V as isList, W as isMacOS, X as isIOS, Y as getSchemaTypeByName, Z as inputRulesPlugin, _ as TrackDeleteMarkName, $ as TrackInsertMarkName, a0 as v4, a1 as TrackFormatMarkName, a2 as comments_module_events, a3 as findMark, a4 as objectIncludes, a5 as AddMarkStep, a6 as RemoveMarkStep, a7 as twipsToLines, a8 as pixelsToTwips, a9 as helpers, aa as posToDOMRect, ab as CommandService, ac as SuperConverter, ad as createDocument, ae as createDocFromMarkdown, af as createDocFromHTML, ag as EditorState, ah as isActive, ai as unflattenListsInHtml, aj as resolveParagraphProperties, ak as _getReferencedTableStyles, al as parseSizeUnit, am as minMax, an as updateDOMAttributes, ao as findChildren$5, ap as generateRandomSigned32BitIntStrId, aq as calculateResolvedParagraphProperties, ar as encodeCSSFromPPr, as as twipsToPixels$2, at as resolveRunProperties, au as encodeCSSFromRPr, av as generateOrderedListIndex, aw as docxNumberingHelpers, ax as InputRule, ay as convertSizeToCSS, az as SelectionRange, aA as Transform, aB as findParentNodeClosestToPos, aC as isInTable$1, aD as generateDocxRandomId, aE as insertNewRelationship, aF as inchesToPixels, aG as kebabCase, aH as getUnderlineCssString } from "./converter-BFGB7hqj.js";
16
- import { D as DocxZipper } from "./docx-zipper-OPbzIk16.js";
15
+ import { P as PluginKey, a as Plugin, M as Mapping, N as NodeSelection, S as Selection, T as TextSelection, b as Slice, D as DOMSerializer, F as Fragment, c as DOMParser$1, d as Mark$1, e as dropPoint, A as AllSelection, p as process$1, B as Buffer2, f as callOrGet, g as getExtensionConfigField, h as getMarkType, i as getMarksFromSelection, j as getNodeType, k as getSchemaTypeNameByName, l as Schema$1, m as cleanSchemaItem, n as canSplit, o as defaultBlockAt$1, q as liftTarget, r as canJoin, s as joinPoint, t as replaceStep$1, R as ReplaceAroundStep$1, u as isTextSelection, v as getMarkRange, w as isMarkActive, x as isNodeActive, y as deleteProps, z as processContent, C as htmlHandler, E as ReplaceStep, G as twipsToInches, H as inchesToTwips, I as ptToTwips, J as getResolvedParagraphProperties, K as linesToTwips, L as ListHelpers, O as updateNumberingProperties, Q as changeListLevel, U as findParentNode, V as isList, W as isMacOS, X as isIOS, Y as getSchemaTypeByName, Z as inputRulesPlugin, _ as TrackDeleteMarkName, $ as TrackInsertMarkName, a0 as v4, a1 as TrackFormatMarkName, a2 as comments_module_events, a3 as findMark, a4 as objectIncludes, a5 as AddMarkStep, a6 as RemoveMarkStep, a7 as twipsToLines, a8 as pixelsToTwips, a9 as helpers, aa as posToDOMRect, ab as CommandService, ac as SuperConverter, ad as createDocument, ae as createDocFromMarkdown, af as createDocFromHTML, ag as EditorState, ah as isActive, ai as unflattenListsInHtml, aj as resolveParagraphProperties, ak as _getReferencedTableStyles, al as parseSizeUnit, am as minMax, an as updateDOMAttributes, ao as findChildren$5, ap as generateRandomSigned32BitIntStrId, aq as calculateResolvedParagraphProperties, ar as encodeCSSFromPPr, as as twipsToPixels$2, at as resolveRunProperties, au as encodeCSSFromRPr, av as generateOrderedListIndex, aw as docxNumberingHelpers, ax as InputRule, ay as convertSizeToCSS, az as SelectionRange, aA as Transform, aB as findParentNodeClosestToPos, aC as isInTable$1, aD as generateDocxRandomId, aE as insertNewRelationship, aF as inchesToPixels, aG as kebabCase, aH as getUnderlineCssString } from "./converter-ZJiSHoiq.js";
16
+ import { D as DocxZipper } from "./docx-zipper-B7FStorN.js";
17
17
  import { ref, computed, createElementBlock, openBlock, withModifiers, Fragment as Fragment$1, renderList, normalizeClass, createCommentVNode, toDisplayString, createElementVNode, createApp } from "vue";
18
18
  var GOOD_LEAF_SIZE = 200;
19
19
  var RopeSequence = function RopeSequence2() {
@@ -13553,7 +13553,7 @@ const isHeadless = (editor) => {
13553
13553
  const shouldSkipNodeView = (editor) => {
13554
13554
  return isHeadless(editor);
13555
13555
  };
13556
- const summaryVersion = "1.0.0-beta.2";
13556
+ const summaryVersion = "1.0.0-beta.4";
13557
13557
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
13558
13558
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
13559
13559
  function mapAttributes(attrs) {
@@ -14335,7 +14335,7 @@ const _Editor = class _Editor extends EventEmitter {
14335
14335
  { default: remarkStringify },
14336
14336
  { default: remarkGfm }
14337
14337
  ] = await Promise.all([
14338
- import("./index-Sn-JVHIg.js"),
14338
+ import("./index-BNGaD3Up.js"),
14339
14339
  import("./index-DRCvimau.js"),
14340
14340
  import("./index-C_x_N6Uh.js"),
14341
14341
  import("./index-D_sWOSiG.js"),
@@ -14540,7 +14540,7 @@ const _Editor = class _Editor extends EventEmitter {
14540
14540
  * Process collaboration migrations
14541
14541
  */
14542
14542
  processCollaborationMigrations() {
14543
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.2");
14543
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.4");
14544
14544
  if (!this.options.ydoc) return;
14545
14545
  const metaMap = this.options.ydoc.getMap("meta");
14546
14546
  let docVersion = metaMap.get("version");
@@ -16247,6 +16247,50 @@ const resolveColorFromAttributes = (attrs, themeColors) => {
16247
16247
  }
16248
16248
  return void 0;
16249
16249
  };
16250
+ const MAX_DATA_ATTR_COUNT = 50;
16251
+ const MAX_DATA_ATTR_VALUE_LENGTH = 1e3;
16252
+ const MAX_DATA_ATTR_NAME_LENGTH = 100;
16253
+ const extractDataAttributes = (attrs) => {
16254
+ if (!attrs) return void 0;
16255
+ const result = {};
16256
+ let attrCount = 0;
16257
+ for (const [key2, value] of Object.entries(attrs)) {
16258
+ if (typeof key2 !== "string" || !key2.toLowerCase().startsWith("data-")) {
16259
+ continue;
16260
+ }
16261
+ if (attrCount >= MAX_DATA_ATTR_COUNT) {
16262
+ if (process$1.env.NODE_ENV === "development") {
16263
+ console.warn(`[PM-Adapter] Rejecting data attributes exceeding ${MAX_DATA_ATTR_COUNT} limit`);
16264
+ }
16265
+ break;
16266
+ }
16267
+ if (key2.length > MAX_DATA_ATTR_NAME_LENGTH) {
16268
+ if (process$1.env.NODE_ENV === "development") {
16269
+ console.warn(
16270
+ `[PM-Adapter] Rejecting data attribute name exceeding ${MAX_DATA_ATTR_NAME_LENGTH} chars: ${key2.substring(0, 50)}...`
16271
+ );
16272
+ }
16273
+ continue;
16274
+ }
16275
+ if (value == null) {
16276
+ continue;
16277
+ }
16278
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
16279
+ const stringValue = String(value);
16280
+ if (stringValue.length > MAX_DATA_ATTR_VALUE_LENGTH) {
16281
+ if (process$1.env.NODE_ENV === "development") {
16282
+ console.warn(
16283
+ `[PM-Adapter] Rejecting data attribute value exceeding ${MAX_DATA_ATTR_VALUE_LENGTH} chars for key: ${key2}`
16284
+ );
16285
+ }
16286
+ continue;
16287
+ }
16288
+ result[key2] = stringValue;
16289
+ attrCount++;
16290
+ }
16291
+ }
16292
+ return Object.keys(result).length > 0 ? result : void 0;
16293
+ };
16250
16294
  const normalizeRunMarkList = (value) => {
16251
16295
  if (!value) return void 0;
16252
16296
  let entries = value;
@@ -16415,6 +16459,19 @@ const sanitizeFontFamily = (fontFamily) => {
16415
16459
  }
16416
16460
  return sanitized;
16417
16461
  };
16462
+ const normalizeFontSizePx = (value) => {
16463
+ if (isFiniteNumber(value)) return value;
16464
+ if (typeof value !== "string") return void 0;
16465
+ const trimmed = value.trim();
16466
+ if (!trimmed) return void 0;
16467
+ const numeric = Number.parseFloat(trimmed);
16468
+ if (!Number.isFinite(numeric)) return void 0;
16469
+ const unit = trimmed.match(/[a-zA-Z%]+$/)?.[0]?.toLowerCase();
16470
+ if (unit === "pt") {
16471
+ return ptToPx(numeric);
16472
+ }
16473
+ return numeric;
16474
+ };
16418
16475
  const applyTextStyleMark = (run, attrs, themeColors) => {
16419
16476
  const resolvedColor = resolveColorFromAttributes(attrs, themeColors);
16420
16477
  if (resolvedColor) {
@@ -16426,11 +16483,9 @@ const applyTextStyleMark = (run, attrs, themeColors) => {
16426
16483
  run.fontFamily = sanitized;
16427
16484
  }
16428
16485
  }
16429
- if (isFiniteNumber(attrs.fontSize)) {
16430
- const size = Number(attrs.fontSize);
16431
- if (size >= 1 && size <= 1e3) {
16432
- run.fontSize = size;
16433
- }
16486
+ const fontSizePx = normalizeFontSizePx(attrs.fontSize);
16487
+ if (fontSizePx !== void 0 && fontSizePx >= 1 && fontSizePx <= 1e3) {
16488
+ run.fontSize = fontSizePx;
16434
16489
  }
16435
16490
  if (isFiniteNumber(attrs.letterSpacing)) {
16436
16491
  const spacing = Number(attrs.letterSpacing);
@@ -16444,6 +16499,7 @@ const DEFAULT_HYPERLINK_CONFIG = {
16444
16499
  };
16445
16500
  const applyMarksToRun = (run, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG, themeColors) => {
16446
16501
  marks.forEach((mark) => {
16502
+ const forwardedDataAttrs = extractDataAttributes(mark.attrs);
16447
16503
  try {
16448
16504
  switch (mark.type) {
16449
16505
  case TRACK_INSERT_MARK:
@@ -16538,6 +16594,9 @@ const applyMarksToRun = (run, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG,
16538
16594
  console.warn(`[PM-Adapter] Failed to apply mark ${mark.type}:`, error);
16539
16595
  }
16540
16596
  }
16597
+ if (forwardedDataAttrs) {
16598
+ run.dataAttrs = { ...run.dataAttrs ?? {}, ...forwardedDataAttrs };
16599
+ }
16541
16600
  });
16542
16601
  };
16543
16602
  function textNodeToRun(textNode, positions, defaultFont, defaultSize, inheritedMarks = [], sdtMetadata, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors) {
@@ -16561,8 +16620,9 @@ function tabNodeToRun(node, positions, tabIndex, paragraph) {
16561
16620
  const pos = positions.get(node);
16562
16621
  if (!pos) return null;
16563
16622
  const paragraphAttrs = paragraph.attrs ?? {};
16564
- const tabStops = Array.isArray(paragraphAttrs.tabStops) ? paragraphAttrs.tabStops : void 0;
16565
- const indent = paragraphAttrs.indent;
16623
+ const paragraphProps = typeof paragraphAttrs.paragraphProperties === "object" && paragraphAttrs.paragraphProperties !== null ? paragraphAttrs.paragraphProperties : {};
16624
+ const tabStops = Array.isArray(paragraphAttrs.tabStops) && paragraphAttrs.tabStops.length ? paragraphAttrs.tabStops : Array.isArray(paragraphProps.tabStops) ? paragraphProps.tabStops : void 0;
16625
+ const indent = paragraphAttrs.indent ?? paragraphProps.indent ?? void 0;
16566
16626
  return {
16567
16627
  kind: "tab",
16568
16628
  text: " ",
@@ -16876,6 +16936,9 @@ const normalizeParagraphSpacing = (value) => {
16876
16936
  const afterRaw = pickNumber(source.after);
16877
16937
  const lineRaw = pickNumber(source.line);
16878
16938
  const lineRule = normalizeLineRule(source.lineRule);
16939
+ const beforeAutospacing = toBooleanFlag(source.beforeAutospacing ?? source.beforeAutoSpacing);
16940
+ const afterAutospacing = toBooleanFlag(source.afterAutospacing ?? source.afterAutoSpacing);
16941
+ const contextualSpacing = toBooleanFlag(source.contextualSpacing);
16879
16942
  const before = beforeRaw != null ? twipsToPx$1(beforeRaw) : pickNumber(source.lineSpaceBefore);
16880
16943
  const after = afterRaw != null ? twipsToPx$1(afterRaw) : pickNumber(source.lineSpaceAfter);
16881
16944
  const line = normalizeLineValue(lineRaw, lineRule);
@@ -16883,8 +16946,24 @@ const normalizeParagraphSpacing = (value) => {
16883
16946
  if (after != null) spacing.after = after;
16884
16947
  if (line != null) spacing.line = line;
16885
16948
  if (lineRule) spacing.lineRule = lineRule;
16949
+ if (beforeAutospacing != null) spacing.beforeAutospacing = beforeAutospacing;
16950
+ if (afterAutospacing != null) spacing.afterAutospacing = afterAutospacing;
16951
+ if (contextualSpacing != null) spacing.contextualSpacing = contextualSpacing;
16886
16952
  return Object.keys(spacing).length > 0 ? spacing : void 0;
16887
16953
  };
16954
+ const toBooleanFlag = (value) => {
16955
+ if (value === true || value === false) return value;
16956
+ if (typeof value === "string") {
16957
+ const normalized = value.trim().toLowerCase();
16958
+ if (["true", "1", "on", "yes"].includes(normalized)) return true;
16959
+ if (["false", "0", "off", "no"].includes(normalized)) return false;
16960
+ }
16961
+ if (typeof value === "number") {
16962
+ if (value === 1) return true;
16963
+ if (value === 0) return false;
16964
+ }
16965
+ return void 0;
16966
+ };
16888
16967
  const normalizeLineValue = (value, lineRule) => {
16889
16968
  if (value == null) return void 0;
16890
16969
  if (lineRule === "auto") {
@@ -18257,15 +18336,17 @@ const hydrateParagraphStyleAttrs = (para, context, preResolved) => {
18257
18336
  return null;
18258
18337
  }
18259
18338
  const attrs = para.attrs ?? {};
18260
- const styleId = typeof attrs.styleId === "string" && attrs.styleId.trim() ? attrs.styleId : null;
18339
+ const paragraphProps = typeof attrs.paragraphProperties === "object" && attrs.paragraphProperties !== null ? attrs.paragraphProperties : {};
18340
+ const styleIdSource = attrs.styleId ?? paragraphProps.styleId;
18341
+ const styleId = typeof styleIdSource === "string" && styleIdSource.trim() ? styleIdSource : null;
18261
18342
  if (!styleId) {
18262
18343
  return null;
18263
18344
  }
18264
18345
  const inlineProps = {
18265
18346
  styleId,
18266
- numberingProperties: cloneIfObject(attrs.numberingProperties),
18267
- indent: cloneIfObject(attrs.indent),
18268
- spacing: cloneIfObject(attrs.spacing)
18347
+ numberingProperties: cloneIfObject(attrs.numberingProperties ?? paragraphProps.numberingProperties),
18348
+ indent: cloneIfObject(attrs.indent ?? paragraphProps.indent),
18349
+ spacing: cloneIfObject(attrs.spacing ?? paragraphProps.spacing)
18269
18350
  };
18270
18351
  const resolverParams = {
18271
18352
  docx: context.docx,
@@ -18543,13 +18624,17 @@ const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleCont
18543
18624
  };
18544
18625
  const computeParagraphAttrs = (para, styleContext, listCounterContext, converterContext, hydrationOverride) => {
18545
18626
  const attrs = para.attrs ?? {};
18627
+ const paragraphProps = typeof attrs.paragraphProperties === "object" && attrs.paragraphProperties !== null ? attrs.paragraphProperties : {};
18546
18628
  const hydrated = hydrationOverride ?? hydrateParagraphStyleAttrs(para, converterContext);
18547
- const spacingSource = attrs.spacing !== void 0 ? attrs.spacing : hydrated?.spacing;
18629
+ const spacingSource = attrs.spacing !== void 0 ? attrs.spacing : paragraphProps.spacing !== void 0 ? paragraphProps.spacing : hydrated?.spacing;
18548
18630
  const normalizedSpacing = normalizeParagraphSpacing(spacingSource);
18549
- const indentSource = attrs.indent ?? hydrated?.indent;
18631
+ const indentSource = attrs.indent ?? paragraphProps.indent ?? hydrated?.indent;
18550
18632
  const normalizedIndent = normalizePxIndent(indentSource) ?? normalizeParagraphIndent(indentSource ?? attrs.textIndent);
18551
- const styleNodeAttrs = hydrated?.tabStops && !attrs.tabStops && !attrs.tabs ? { ...attrs, tabStops: hydrated.tabStops } : attrs;
18633
+ const styleNodeAttrs = hydrated?.tabStops && !attrs.tabStops && !attrs.tabs ? { ...attrs, tabStops: hydrated.tabStops } : !attrs.tabStops && paragraphProps.tabStops ? { ...attrs, tabStops: paragraphProps.tabStops } : attrs;
18552
18634
  const styleNode = buildStyleNodeFromAttrs(styleNodeAttrs, normalizedSpacing, normalizedIndent);
18635
+ if (styleNodeAttrs.styleId == null && paragraphProps.styleId) {
18636
+ styleNode.styleId = paragraphProps.styleId;
18637
+ }
18553
18638
  const computed2 = resolveStyle(styleNode, styleContext);
18554
18639
  const { spacing, indent } = resolveSpacingIndent(computed2.paragraph, computed2.numbering);
18555
18640
  const paragraphAttrs = {};
@@ -18574,6 +18659,18 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
18574
18659
  }
18575
18660
  const spacingPx = spacingPtToPx(spacing, normalizedSpacing);
18576
18661
  if (spacingPx) paragraphAttrs.spacing = spacingPx;
18662
+ if (normalizedSpacing?.beforeAutospacing != null || normalizedSpacing?.afterAutospacing != null) {
18663
+ paragraphAttrs.spacing = paragraphAttrs.spacing ?? {};
18664
+ if (normalizedSpacing?.beforeAutospacing != null) {
18665
+ paragraphAttrs.spacing.beforeAutospacing = normalizedSpacing.beforeAutospacing;
18666
+ }
18667
+ if (normalizedSpacing?.afterAutospacing != null) {
18668
+ paragraphAttrs.spacing.afterAutospacing = normalizedSpacing.afterAutospacing;
18669
+ }
18670
+ }
18671
+ if (normalizedSpacing?.contextualSpacing != null) {
18672
+ paragraphAttrs.contextualSpacing = normalizedSpacing.contextualSpacing;
18673
+ }
18577
18674
  const hasExplicitIndent = Boolean(normalizedIndent);
18578
18675
  const hasNumberingIndent = Boolean(computed2.numbering?.indent?.left || computed2.numbering?.indent?.hanging);
18579
18676
  if (hasExplicitIndent || hasNumberingIndent || bidi && adjustRightInd) {
@@ -18592,10 +18689,20 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
18592
18689
  if (borders) paragraphAttrs.borders = borders;
18593
18690
  const shading = normalizeParagraphShading(attrs.shading ?? hydrated?.shading);
18594
18691
  if (shading) paragraphAttrs.shading = shading;
18692
+ const keepNext = paragraphProps.keepNext ?? hydrated?.keepNext ?? attrs.keepNext;
18693
+ if (keepNext === true) paragraphAttrs.keepNext = true;
18694
+ const keepLines = paragraphProps.keepLines ?? hydrated?.keepLines ?? attrs.keepLines;
18695
+ if (keepLines === true) paragraphAttrs.keepLines = true;
18595
18696
  const paragraphDecimalSeparator = styleContext.defaults?.decimalSeparator ?? DEFAULT_DECIMAL_SEPARATOR$2;
18596
18697
  if (paragraphDecimalSeparator !== DEFAULT_DECIMAL_SEPARATOR$2) {
18597
18698
  paragraphAttrs.decimalSeparator = paragraphDecimalSeparator;
18598
18699
  }
18700
+ const styleIdAttr = typeof attrs.styleId === "string" ? attrs.styleId : void 0;
18701
+ if (styleIdAttr) {
18702
+ paragraphAttrs.styleId = styleIdAttr;
18703
+ } else if (paragraphProps.styleId) {
18704
+ paragraphAttrs.styleId = paragraphProps.styleId;
18705
+ }
18599
18706
  const paraIntervalTwips = pickNumber(attrs.tabIntervalTwips) ?? (() => {
18600
18707
  const px = pickNumber(attrs.tabIntervalPx);
18601
18708
  return px != null ? Math.round(px * 15) : void 0;
@@ -18632,7 +18739,7 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
18632
18739
  paragraphAttrs.floatAlignment = xAlign;
18633
18740
  }
18634
18741
  }
18635
- const numberingSource = attrs.numberingProperties ?? hydrated?.numberingProperties;
18742
+ const numberingSource = attrs.numberingProperties ?? paragraphProps.numberingProperties ?? hydrated?.numberingProperties;
18636
18743
  const rawNumberingProps = toAdapterNumberingProps(numberingSource);
18637
18744
  if (rawNumberingProps) {
18638
18745
  const numberingProps = rawNumberingProps;
@@ -19285,13 +19392,29 @@ const extractRunStyleId = (runProperties) => {
19285
19392
  return null;
19286
19393
  };
19287
19394
  const isTextRun$1 = (run) => run.kind !== "tab";
19395
+ const dataAttrsCompatible = (a, b) => {
19396
+ const aAttrs = a.dataAttrs;
19397
+ const bAttrs = b.dataAttrs;
19398
+ if (!aAttrs && !bAttrs) return true;
19399
+ if (!aAttrs || !bAttrs) return false;
19400
+ const aKeys = Object.keys(aAttrs).sort();
19401
+ const bKeys = Object.keys(bAttrs).sort();
19402
+ if (aKeys.length !== bKeys.length) return false;
19403
+ for (let i = 0; i < aKeys.length; i++) {
19404
+ const key2 = aKeys[i];
19405
+ if (key2 !== bKeys[i] || aAttrs[key2] !== bAttrs[key2]) {
19406
+ return false;
19407
+ }
19408
+ }
19409
+ return true;
19410
+ };
19288
19411
  function mergeAdjacentRuns(runs) {
19289
19412
  if (runs.length <= 1) return runs;
19290
19413
  const merged = [];
19291
19414
  let current = runs[0];
19292
19415
  for (let i = 1; i < runs.length; i++) {
19293
19416
  const next = runs[i];
19294
- 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);
19417
+ 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);
19295
19418
  if (canMerge) {
19296
19419
  const currText = current.text ?? "";
19297
19420
  const nextText = next.text ?? "";
@@ -19308,10 +19431,62 @@ function mergeAdjacentRuns(runs) {
19308
19431
  merged.push(current);
19309
19432
  return merged;
19310
19433
  }
19434
+ const applyBaseRunDefaults = (run, defaults, fallbackFont, fallbackSize) => {
19435
+ if (!run) return;
19436
+ if (defaults.fontFamily && run.fontFamily === fallbackFont) {
19437
+ run.fontFamily = defaults.fontFamily;
19438
+ }
19439
+ if (defaults.fontSizePx != null && run.fontSize === fallbackSize) {
19440
+ run.fontSize = defaults.fontSizePx;
19441
+ }
19442
+ if (defaults.color && !run.color) {
19443
+ run.color = defaults.color;
19444
+ }
19445
+ if (defaults.letterSpacing != null && run.letterSpacing == null) {
19446
+ run.letterSpacing = defaults.letterSpacing;
19447
+ }
19448
+ if (defaults.bold && run.bold === void 0) {
19449
+ run.bold = true;
19450
+ }
19451
+ if (defaults.italic && run.italic === void 0) {
19452
+ run.italic = true;
19453
+ }
19454
+ if (defaults.underline && !run.underline) {
19455
+ run.underline = defaults.underline;
19456
+ }
19457
+ };
19311
19458
  function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defaultSize, styleContext, listCounterContext, trackedChanges, bookmarks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors, converters, converterContext) {
19312
19459
  const baseBlockId = nextBlockId("paragraph");
19313
- const paragraphStyleId = typeof para.attrs?.styleId === "string" ? para.attrs.styleId : null;
19460
+ const paragraphProps = typeof para.attrs?.paragraphProperties === "object" && para.attrs.paragraphProperties !== null ? para.attrs.paragraphProperties : {};
19461
+ const paragraphStyleId = typeof para.attrs?.styleId === "string" && para.attrs.styleId.trim() ? para.attrs.styleId : typeof paragraphProps.styleId === "string" && paragraphProps.styleId.trim() ? paragraphProps.styleId : null;
19314
19462
  const paragraphHydration = converterContext ? hydrateParagraphStyleAttrs(para, converterContext) : null;
19463
+ let baseRunDefaults = {};
19464
+ try {
19465
+ const spacingSource = para.attrs?.spacing !== void 0 ? para.attrs.spacing : paragraphProps.spacing !== void 0 ? paragraphProps.spacing : paragraphHydration?.spacing;
19466
+ const indentSource = para.attrs?.indent ?? paragraphProps.indent ?? paragraphHydration?.indent;
19467
+ const normalizedSpacing = normalizeParagraphSpacing(spacingSource);
19468
+ const normalizedIndent = normalizePxIndent(indentSource) ?? normalizeParagraphIndent(indentSource ?? para.attrs?.textIndent);
19469
+ const styleNodeAttrs = paragraphHydration?.tabStops && !para.attrs?.tabStops && !para.attrs?.tabs ? { ...para.attrs ?? {}, tabStops: paragraphHydration.tabStops } : para.attrs ?? {};
19470
+ const styleNode = buildStyleNodeFromAttrs(styleNodeAttrs, normalizedSpacing, normalizedIndent);
19471
+ if (styleNodeAttrs.styleId == null && paragraphProps.styleId) {
19472
+ styleNode.styleId = paragraphProps.styleId;
19473
+ }
19474
+ const resolved = resolveStyle(styleNode, styleContext);
19475
+ baseRunDefaults = {
19476
+ fontFamily: resolved.character.font?.family,
19477
+ fontSizePx: ptToPx(resolved.character.font?.size),
19478
+ color: resolved.character.color,
19479
+ bold: resolved.character.font?.weight != null ? resolved.character.font.weight >= 600 : void 0,
19480
+ italic: resolved.character.font?.italic,
19481
+ underline: resolved.character.underline ? {
19482
+ style: resolved.character.underline.style,
19483
+ color: resolved.character.underline.color
19484
+ } : void 0,
19485
+ letterSpacing: ptToPx(resolved.character.letterSpacing)
19486
+ };
19487
+ } catch {
19488
+ baseRunDefaults = {};
19489
+ }
19315
19490
  const paragraphAttrs = computeParagraphAttrs(
19316
19491
  para,
19317
19492
  styleContext,
@@ -19319,6 +19494,18 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
19319
19494
  converterContext,
19320
19495
  paragraphHydration
19321
19496
  );
19497
+ if (paragraphAttrs?.spacing) {
19498
+ const spacing = { ...paragraphAttrs.spacing };
19499
+ const effectiveFontSize = baseRunDefaults.fontSizePx ?? defaultSize;
19500
+ const isList2 = Boolean(paragraphAttrs.numberingProperties);
19501
+ if (spacing.beforeAutospacing) {
19502
+ spacing.before = isList2 ? 0 : Math.max(0, Number(spacing.before ?? 0) + effectiveFontSize * 0.5);
19503
+ }
19504
+ if (spacing.afterAutospacing) {
19505
+ spacing.after = isList2 ? 0 : Math.max(0, Number(spacing.after ?? 0) + effectiveFontSize * 0.5);
19506
+ }
19507
+ paragraphAttrs.spacing = spacing;
19508
+ }
19322
19509
  const linkedStyleResolver = createLinkedStyleResolver(converterContext?.linkedStyles);
19323
19510
  const blocks = [];
19324
19511
  if (hasPageBreakBefore(para)) {
@@ -19396,6 +19583,7 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
19396
19583
  );
19397
19584
  const inlineStyleId = getInlineStyleId(inheritedMarks);
19398
19585
  applyRunStyles2(run, inlineStyleId, activeRunStyleId);
19586
+ applyBaseRunDefaults(run, baseRunDefaults, defaultFont, defaultSize);
19399
19587
  currentRuns.push(run);
19400
19588
  return;
19401
19589
  }
@@ -19431,6 +19619,7 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
19431
19619
  );
19432
19620
  const inlineStyleId = getInlineStyleId(inheritedMarks);
19433
19621
  applyRunStyles2(run, inlineStyleId, activeRunStyleId);
19622
+ applyBaseRunDefaults(run, baseRunDefaults, defaultFont, defaultSize);
19434
19623
  currentRuns.push(run);
19435
19624
  }
19436
19625
  }
@@ -19468,6 +19657,7 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
19468
19657
  );
19469
19658
  const inlineStyleId = getInlineStyleId(mergedMarks);
19470
19659
  applyRunStyles2(tokenRun, inlineStyleId, activeRunStyleId);
19660
+ applyBaseRunDefaults(tokenRun, baseRunDefaults, defaultFont, defaultSize);
19471
19661
  if (pageRefPos) {
19472
19662
  tokenRun.pmStart = pageRefPos.start;
19473
19663
  tokenRun.pmEnd = pageRefPos.end;
@@ -19526,6 +19716,7 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
19526
19716
  }
19527
19717
  const inlineStyleId = getInlineStyleId(inheritedMarks);
19528
19718
  applyRunStyles2(tokenRun, inlineStyleId, activeRunStyleId);
19719
+ applyBaseRunDefaults(tokenRun, baseRunDefaults, defaultFont, defaultSize);
19529
19720
  currentRuns.push(tokenRun);
19530
19721
  }
19531
19722
  return;
@@ -21554,7 +21745,9 @@ function layoutParagraphBlock(ctx2, anchors) {
21554
21745
  let lines = normalizeLines(measure);
21555
21746
  let fromLine = 0;
21556
21747
  const spacing = block.attrs?.spacing ?? {};
21557
- const spacingBefore = Math.max(0, Number(spacing.before ?? spacing.lineSpaceBefore ?? 0));
21748
+ const styleId = block.attrs?.styleId;
21749
+ const contextualSpacing = Boolean(block.attrs?.contextualSpacing);
21750
+ let spacingBefore = Math.max(0, Number(spacing.before ?? spacing.lineSpaceBefore ?? 0));
21558
21751
  const spacingAfter = Math.max(0, Number(spacing.after ?? spacing.lineSpaceAfter ?? 0));
21559
21752
  let appliedSpacingBefore = spacingBefore === 0;
21560
21753
  let lastState = null;
@@ -21570,6 +21763,15 @@ function layoutParagraphBlock(ctx2, anchors) {
21570
21763
  while (fromLine < lines.length) {
21571
21764
  let state = ensurePage();
21572
21765
  if (state.trailingSpacing == null) state.trailingSpacing = 0;
21766
+ if (contextualSpacing) {
21767
+ const prevStyle = state.lastParagraphStyleId;
21768
+ if (styleId && prevStyle && prevStyle === styleId) {
21769
+ spacingBefore = 0;
21770
+ }
21771
+ }
21772
+ if (contextualSpacing && state.lastParagraphStyleId && styleId && state.lastParagraphStyleId === styleId) {
21773
+ spacingBefore = 0;
21774
+ }
21573
21775
  if (!appliedSpacingBefore && spacingBefore > 0) {
21574
21776
  while (!appliedSpacingBefore) {
21575
21777
  const prevTrailing = state.trailingSpacing ?? 0;
@@ -21738,6 +21940,7 @@ function layoutParagraphBlock(ctx2, anchors) {
21738
21940
  } else {
21739
21941
  lastState.trailingSpacing = 0;
21740
21942
  }
21943
+ lastState.lastParagraphStyleId = styleId;
21741
21944
  }
21742
21945
  }
21743
21946
  function layoutImageBlock({
@@ -21976,7 +22179,8 @@ function createPaginator(opts) {
21976
22179
  contentBottom,
21977
22180
  constraintBoundaries: [],
21978
22181
  activeConstraintIndex: -1,
21979
- trailingSpacing: 0
22182
+ trailingSpacing: 0,
22183
+ lastParagraphStyleId: void 0
21980
22184
  };
21981
22185
  states.push(state);
21982
22186
  pages.push(state.page);
@@ -21998,6 +22202,7 @@ function createPaginator(opts) {
21998
22202
  state.cursorY = state.topMargin;
21999
22203
  }
22000
22204
  state.trailingSpacing = 0;
22205
+ state.lastParagraphStyleId = void 0;
22001
22206
  return state;
22002
22207
  }
22003
22208
  return startNewPage();
@@ -26540,8 +26745,59 @@ const _DomPainter = class _DomPainter {
26540
26745
  this.headerProvider = header;
26541
26746
  this.footerProvider = footer;
26542
26747
  }
26543
- setData(blocks, measures) {
26748
+ /**
26749
+ * Updates the painter's block and measure data.
26750
+ *
26751
+ * @param blocks - Main document blocks
26752
+ * @param measures - Measures corresponding to main document blocks
26753
+ * @param headerBlocks - Optional header blocks from header/footer layout results
26754
+ * @param headerMeasures - Optional measures corresponding to header blocks
26755
+ * @param footerBlocks - Optional footer blocks from header/footer layout results
26756
+ * @param footerMeasures - Optional measures corresponding to footer blocks
26757
+ */
26758
+ setData(blocks, measures, headerBlocks, headerMeasures, footerBlocks, footerMeasures) {
26759
+ if (blocks.length !== measures.length) {
26760
+ throw new Error(
26761
+ `setData: blocks and measures arrays must have the same length. Got blocks.length=${blocks.length}, measures.length=${measures.length}`
26762
+ );
26763
+ }
26764
+ const hasHeaderBlocks = headerBlocks !== void 0;
26765
+ const hasHeaderMeasures = headerMeasures !== void 0;
26766
+ if (hasHeaderBlocks !== hasHeaderMeasures) {
26767
+ throw new Error(
26768
+ `setData: headerBlocks and headerMeasures must both be provided or both be omitted. Got headerBlocks=${hasHeaderBlocks ? "provided" : "omitted"}, headerMeasures=${hasHeaderMeasures ? "provided" : "omitted"}`
26769
+ );
26770
+ }
26771
+ if (hasHeaderBlocks && hasHeaderMeasures && headerBlocks.length !== headerMeasures.length) {
26772
+ throw new Error(
26773
+ `setData: headerBlocks and headerMeasures arrays must have the same length. Got headerBlocks.length=${headerBlocks.length}, headerMeasures.length=${headerMeasures.length}`
26774
+ );
26775
+ }
26776
+ const hasFooterBlocks = footerBlocks !== void 0;
26777
+ const hasFooterMeasures = footerMeasures !== void 0;
26778
+ if (hasFooterBlocks !== hasFooterMeasures) {
26779
+ throw new Error(
26780
+ `setData: footerBlocks and footerMeasures must both be provided or both be omitted. Got footerBlocks=${hasFooterBlocks ? "provided" : "omitted"}, footerMeasures=${hasFooterMeasures ? "provided" : "omitted"}`
26781
+ );
26782
+ }
26783
+ if (hasFooterBlocks && hasFooterMeasures && footerBlocks.length !== footerMeasures.length) {
26784
+ throw new Error(
26785
+ `setData: footerBlocks and footerMeasures arrays must have the same length. Got footerBlocks.length=${footerBlocks.length}, footerMeasures.length=${footerMeasures.length}`
26786
+ );
26787
+ }
26544
26788
  const nextLookup = this.buildBlockLookup(blocks, measures);
26789
+ if (headerBlocks && headerMeasures) {
26790
+ const headerLookup = this.buildBlockLookup(headerBlocks, headerMeasures);
26791
+ headerLookup.forEach((entry, id) => {
26792
+ nextLookup.set(id, entry);
26793
+ });
26794
+ }
26795
+ if (footerBlocks && footerMeasures) {
26796
+ const footerLookup = this.buildBlockLookup(footerBlocks, footerMeasures);
26797
+ footerLookup.forEach((entry, id) => {
26798
+ nextLookup.set(id, entry);
26799
+ });
26800
+ }
26545
26801
  const changed = /* @__PURE__ */ new Set();
26546
26802
  nextLookup.forEach((entry, id) => {
26547
26803
  const previous = this.blockLookup.get(id);
@@ -26864,6 +27120,14 @@ const _DomPainter = class _DomPainter {
26864
27120
  container.style.height = `${data.height}px`;
26865
27121
  container.style.top = `${Math.max(0, offset2)}px`;
26866
27122
  container.style.zIndex = "1";
27123
+ let footerYOffset = 0;
27124
+ if (kind === "footer" && data.fragments.length > 0) {
27125
+ const contentHeight = typeof data.contentHeight === "number" ? data.contentHeight : data.fragments.reduce((max2, f2) => {
27126
+ const fragHeight = "height" in f2 && typeof f2.height === "number" ? f2.height : this.estimateFragmentHeight(f2);
27127
+ return Math.max(max2, f2.y + Math.max(0, fragHeight));
27128
+ }, 0);
27129
+ footerYOffset = Math.max(0, data.height - contentHeight);
27130
+ }
26867
27131
  const context = {
26868
27132
  pageNumber: page.number,
26869
27133
  totalPages: this.totalPages,
@@ -26872,6 +27136,10 @@ const _DomPainter = class _DomPainter {
26872
27136
  };
26873
27137
  data.fragments.forEach((fragment) => {
26874
27138
  const fragEl = this.renderFragment(fragment, context);
27139
+ if (footerYOffset > 0) {
27140
+ const currentTop = parseFloat(fragEl.style.top) || fragment.y;
27141
+ fragEl.style.top = `${currentTop + footerYOffset}px`;
27142
+ }
26875
27143
  container.appendChild(fragEl);
26876
27144
  });
26877
27145
  if (!existing) {
@@ -27149,147 +27417,162 @@ const _DomPainter = class _DomPainter {
27149
27417
  return el;
27150
27418
  }
27151
27419
  renderListItemFragment(fragment, context) {
27152
- const lookup = this.blockLookup.get(fragment.blockId);
27153
- if (!lookup || lookup.block.kind !== "list" || lookup.measure.kind !== "list") {
27154
- throw new Error(`DomPainter: missing list data for fragment ${fragment.blockId}`);
27155
- }
27156
- if (!this.doc) {
27157
- throw new Error("DomPainter: document is not available");
27420
+ try {
27421
+ const lookup = this.blockLookup.get(fragment.blockId);
27422
+ if (!lookup || lookup.block.kind !== "list" || lookup.measure.kind !== "list") {
27423
+ throw new Error(`DomPainter: missing list data for fragment ${fragment.blockId}`);
27424
+ }
27425
+ if (!this.doc) {
27426
+ throw new Error("DomPainter: document is not available");
27427
+ }
27428
+ const block = lookup.block;
27429
+ const measure = lookup.measure;
27430
+ const item = block.items.find((entry) => entry.id === fragment.itemId);
27431
+ const itemMeasure = measure.items.find((entry) => entry.itemId === fragment.itemId);
27432
+ if (!item || !itemMeasure) {
27433
+ throw new Error(`DomPainter: missing list item ${fragment.itemId}`);
27434
+ }
27435
+ const fragmentEl = this.doc.createElement("div");
27436
+ fragmentEl.classList.add(CLASS_NAMES.fragment, `${CLASS_NAMES.fragment}-list-item`);
27437
+ applyStyles$2(fragmentEl, fragmentStyles);
27438
+ fragmentEl.style.left = `${fragment.x - fragment.markerWidth}px`;
27439
+ fragmentEl.style.top = `${fragment.y}px`;
27440
+ fragmentEl.style.width = `${fragment.markerWidth + fragment.width}px`;
27441
+ fragmentEl.dataset.blockId = fragment.blockId;
27442
+ fragmentEl.dataset.itemId = fragment.itemId;
27443
+ const paragraphMetadata = item.paragraph.attrs?.sdt;
27444
+ this.applySdtDataset(fragmentEl, paragraphMetadata);
27445
+ if (fragment.continuesFromPrev) {
27446
+ fragmentEl.dataset.continuesFromPrev = "true";
27447
+ }
27448
+ if (fragment.continuesOnNext) {
27449
+ fragmentEl.dataset.continuesOnNext = "true";
27450
+ }
27451
+ const markerEl = this.doc.createElement("span");
27452
+ markerEl.classList.add("superdoc-list-marker");
27453
+ const wordLayout = item.paragraph.attrs?.wordLayout;
27454
+ const marker = wordLayout?.marker;
27455
+ if (marker) {
27456
+ markerEl.textContent = marker.markerText ?? null;
27457
+ markerEl.style.display = "inline-block";
27458
+ markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
27459
+ markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
27460
+ markerEl.style.textAlign = marker.justification ?? "";
27461
+ markerEl.style.fontFamily = marker.run.fontFamily;
27462
+ markerEl.style.fontSize = `${marker.run.fontSize}px`;
27463
+ if (marker.run.bold) markerEl.style.fontWeight = "bold";
27464
+ if (marker.run.italic) markerEl.style.fontStyle = "italic";
27465
+ if (marker.run.color) markerEl.style.color = marker.run.color;
27466
+ if (marker.run.letterSpacing) markerEl.style.letterSpacing = `${marker.run.letterSpacing}px`;
27467
+ } else {
27468
+ markerEl.textContent = item.marker.text;
27469
+ markerEl.style.display = "inline-block";
27470
+ markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
27471
+ markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
27472
+ if (item.marker.align) {
27473
+ markerEl.style.textAlign = item.marker.align;
27474
+ }
27475
+ }
27476
+ fragmentEl.appendChild(markerEl);
27477
+ const contentEl = this.doc.createElement("div");
27478
+ contentEl.classList.add("superdoc-list-content");
27479
+ this.applySdtDataset(contentEl, paragraphMetadata);
27480
+ contentEl.style.display = "inline-block";
27481
+ contentEl.style.width = `${fragment.width}px`;
27482
+ const lines = itemMeasure.paragraph.lines.slice(fragment.fromLine, fragment.toLine);
27483
+ const contentAttrs = wordLayout ? item.paragraph.attrs : stripListIndent(item.paragraph.attrs);
27484
+ applyParagraphBlockStyles(contentEl, contentAttrs);
27485
+ lines.forEach((line) => {
27486
+ const lineEl = this.renderLine(item.paragraph, line, context);
27487
+ contentEl.appendChild(lineEl);
27488
+ });
27489
+ fragmentEl.appendChild(contentEl);
27490
+ return fragmentEl;
27491
+ } catch (error) {
27492
+ console.error("[DomPainter] List item fragment rendering failed:", { fragment, error });
27493
+ return this.createErrorPlaceholder(fragment.blockId, error);
27158
27494
  }
27159
- const block = lookup.block;
27160
- const measure = lookup.measure;
27161
- const item = block.items.find((entry) => entry.id === fragment.itemId);
27162
- const itemMeasure = measure.items.find((entry) => entry.itemId === fragment.itemId);
27163
- if (!item || !itemMeasure) {
27164
- throw new Error(`DomPainter: missing list item ${fragment.itemId}`);
27165
- }
27166
- const fragmentEl = this.doc.createElement("div");
27167
- fragmentEl.classList.add(CLASS_NAMES.fragment, `${CLASS_NAMES.fragment}-list-item`);
27168
- applyStyles$2(fragmentEl, fragmentStyles);
27169
- fragmentEl.style.left = `${fragment.x - fragment.markerWidth}px`;
27170
- fragmentEl.style.top = `${fragment.y}px`;
27171
- fragmentEl.style.width = `${fragment.markerWidth + fragment.width}px`;
27172
- fragmentEl.dataset.blockId = fragment.blockId;
27173
- fragmentEl.dataset.itemId = fragment.itemId;
27174
- const paragraphMetadata = item.paragraph.attrs?.sdt;
27175
- this.applySdtDataset(fragmentEl, paragraphMetadata);
27176
- if (fragment.continuesFromPrev) {
27177
- fragmentEl.dataset.continuesFromPrev = "true";
27178
- }
27179
- if (fragment.continuesOnNext) {
27180
- fragmentEl.dataset.continuesOnNext = "true";
27181
- }
27182
- const markerEl = this.doc.createElement("span");
27183
- markerEl.classList.add("superdoc-list-marker");
27184
- const wordLayout = item.paragraph.attrs?.wordLayout;
27185
- if (wordLayout?.marker) {
27186
- const marker = wordLayout.marker;
27187
- markerEl.textContent = marker.markerText;
27188
- markerEl.style.display = "inline-block";
27189
- markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
27190
- markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
27191
- markerEl.style.textAlign = marker.justification;
27192
- markerEl.style.fontFamily = marker.run.fontFamily;
27193
- markerEl.style.fontSize = `${marker.run.fontSize}px`;
27194
- if (marker.run.bold) markerEl.style.fontWeight = "bold";
27195
- if (marker.run.italic) markerEl.style.fontStyle = "italic";
27196
- if (marker.run.color) markerEl.style.color = marker.run.color;
27197
- if (marker.run.letterSpacing) markerEl.style.letterSpacing = `${marker.run.letterSpacing}px`;
27198
- } else {
27199
- markerEl.textContent = item.marker.text;
27200
- markerEl.style.display = "inline-block";
27201
- markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
27202
- markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
27203
- if (item.marker.align) {
27204
- markerEl.style.textAlign = item.marker.align;
27205
- }
27206
- }
27207
- fragmentEl.appendChild(markerEl);
27208
- const contentEl = this.doc.createElement("div");
27209
- contentEl.classList.add("superdoc-list-content");
27210
- this.applySdtDataset(contentEl, paragraphMetadata);
27211
- contentEl.style.display = "inline-block";
27212
- contentEl.style.width = `${fragment.width}px`;
27213
- const lines = itemMeasure.paragraph.lines.slice(fragment.fromLine, fragment.toLine);
27214
- const contentAttrs = wordLayout ? item.paragraph.attrs : stripListIndent(item.paragraph.attrs);
27215
- applyParagraphBlockStyles(contentEl, contentAttrs);
27216
- lines.forEach((line) => {
27217
- const lineEl = this.renderLine(item.paragraph, line, context);
27218
- contentEl.appendChild(lineEl);
27219
- });
27220
- fragmentEl.appendChild(contentEl);
27221
- return fragmentEl;
27222
27495
  }
27223
27496
  renderImageFragment(fragment) {
27224
- const lookup = this.blockLookup.get(fragment.blockId);
27225
- if (!lookup || lookup.block.kind !== "image" || lookup.measure.kind !== "image") {
27226
- throw new Error(`DomPainter: missing image block for fragment ${fragment.blockId}`);
27227
- }
27228
- if (!this.doc) {
27229
- throw new Error("DomPainter: document is not available");
27230
- }
27231
- const block = lookup.block;
27232
- const fragmentEl = this.doc.createElement("div");
27233
- fragmentEl.classList.add(CLASS_NAMES.fragment);
27234
- applyStyles$2(fragmentEl, fragmentStyles);
27235
- this.applyFragmentFrame(fragmentEl, fragment);
27236
- fragmentEl.style.height = `${fragment.height}px`;
27237
- this.applySdtDataset(fragmentEl, block.attrs?.sdt);
27238
- this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
27239
- if (fragment.isAnchored && fragment.zIndex != null) {
27240
- fragmentEl.style.zIndex = String(fragment.zIndex);
27241
- }
27242
- const img = this.doc.createElement("img");
27243
- if (block.src) {
27244
- img.src = block.src;
27497
+ try {
27498
+ const lookup = this.blockLookup.get(fragment.blockId);
27499
+ if (!lookup || lookup.block.kind !== "image" || lookup.measure.kind !== "image") {
27500
+ throw new Error(`DomPainter: missing image block for fragment ${fragment.blockId}`);
27501
+ }
27502
+ if (!this.doc) {
27503
+ throw new Error("DomPainter: document is not available");
27504
+ }
27505
+ const block = lookup.block;
27506
+ const fragmentEl = this.doc.createElement("div");
27507
+ fragmentEl.classList.add(CLASS_NAMES.fragment);
27508
+ applyStyles$2(fragmentEl, fragmentStyles);
27509
+ this.applyFragmentFrame(fragmentEl, fragment);
27510
+ fragmentEl.style.height = `${fragment.height}px`;
27511
+ this.applySdtDataset(fragmentEl, block.attrs?.sdt);
27512
+ this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
27513
+ if (fragment.isAnchored && fragment.zIndex != null) {
27514
+ fragmentEl.style.zIndex = String(fragment.zIndex);
27515
+ }
27516
+ const img = this.doc.createElement("img");
27517
+ if (block.src) {
27518
+ img.src = block.src;
27519
+ }
27520
+ img.alt = block.alt ?? "";
27521
+ img.style.width = "100%";
27522
+ img.style.height = "100%";
27523
+ img.style.objectFit = block.objectFit ?? "contain";
27524
+ img.style.display = block.display === "inline" ? "inline-block" : "block";
27525
+ fragmentEl.appendChild(img);
27526
+ return fragmentEl;
27527
+ } catch (error) {
27528
+ console.error("[DomPainter] Image fragment rendering failed:", { fragment, error });
27529
+ return this.createErrorPlaceholder(fragment.blockId, error);
27245
27530
  }
27246
- img.alt = block.alt ?? "";
27247
- img.style.width = "100%";
27248
- img.style.height = "100%";
27249
- img.style.objectFit = block.objectFit ?? "contain";
27250
- img.style.display = block.display === "inline" ? "inline-block" : "block";
27251
- fragmentEl.appendChild(img);
27252
- return fragmentEl;
27253
27531
  }
27254
27532
  renderDrawingFragment(fragment) {
27255
- const lookup = this.blockLookup.get(fragment.blockId);
27256
- if (!lookup || lookup.block.kind !== "drawing" || lookup.measure.kind !== "drawing") {
27257
- throw new Error(`DomPainter: missing drawing block for fragment ${fragment.blockId}`);
27258
- }
27259
- if (!this.doc) {
27260
- throw new Error("DomPainter: document is not available");
27533
+ try {
27534
+ const lookup = this.blockLookup.get(fragment.blockId);
27535
+ if (!lookup || lookup.block.kind !== "drawing" || lookup.measure.kind !== "drawing") {
27536
+ throw new Error(`DomPainter: missing drawing block for fragment ${fragment.blockId}`);
27537
+ }
27538
+ if (!this.doc) {
27539
+ throw new Error("DomPainter: document is not available");
27540
+ }
27541
+ const block = lookup.block;
27542
+ const isVectorShapeBlock = block.kind === "drawing" && block.drawingKind === "vectorShape";
27543
+ const fragmentEl = this.doc.createElement("div");
27544
+ fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-drawing-fragment");
27545
+ applyStyles$2(fragmentEl, fragmentStyles);
27546
+ this.applyFragmentFrame(fragmentEl, fragment);
27547
+ fragmentEl.style.height = `${fragment.height}px`;
27548
+ fragmentEl.style.position = "absolute";
27549
+ if (fragment.isAnchored && fragment.zIndex != null) {
27550
+ fragmentEl.style.zIndex = String(fragment.zIndex);
27551
+ }
27552
+ const innerWrapper = this.doc.createElement("div");
27553
+ innerWrapper.classList.add("superdoc-drawing-inner");
27554
+ innerWrapper.style.position = "absolute";
27555
+ innerWrapper.style.left = "50%";
27556
+ innerWrapper.style.top = "50%";
27557
+ innerWrapper.style.width = `${fragment.geometry.width}px`;
27558
+ innerWrapper.style.height = `${fragment.geometry.height}px`;
27559
+ innerWrapper.style.transformOrigin = "center";
27560
+ const scale = fragment.scale ?? 1;
27561
+ const transforms = ["translate(-50%, -50%)"];
27562
+ if (!isVectorShapeBlock) {
27563
+ transforms.push(`rotate(${fragment.geometry.rotation ?? 0}deg)`);
27564
+ transforms.push(`scaleX(${fragment.geometry.flipH ? -1 : 1})`);
27565
+ transforms.push(`scaleY(${fragment.geometry.flipV ? -1 : 1})`);
27566
+ }
27567
+ transforms.push(`scale(${scale})`);
27568
+ innerWrapper.style.transform = transforms.join(" ");
27569
+ innerWrapper.appendChild(this.renderDrawingContent(block, fragment));
27570
+ fragmentEl.appendChild(innerWrapper);
27571
+ return fragmentEl;
27572
+ } catch (error) {
27573
+ console.error("[DomPainter] Drawing fragment rendering failed:", { fragment, error });
27574
+ return this.createErrorPlaceholder(fragment.blockId, error);
27261
27575
  }
27262
- const block = lookup.block;
27263
- const isVectorShapeBlock = block.kind === "drawing" && block.drawingKind === "vectorShape";
27264
- const fragmentEl = this.doc.createElement("div");
27265
- fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-drawing-fragment");
27266
- applyStyles$2(fragmentEl, fragmentStyles);
27267
- this.applyFragmentFrame(fragmentEl, fragment);
27268
- fragmentEl.style.height = `${fragment.height}px`;
27269
- fragmentEl.style.position = "absolute";
27270
- if (fragment.isAnchored && fragment.zIndex != null) {
27271
- fragmentEl.style.zIndex = String(fragment.zIndex);
27272
- }
27273
- const innerWrapper = this.doc.createElement("div");
27274
- innerWrapper.classList.add("superdoc-drawing-inner");
27275
- innerWrapper.style.position = "absolute";
27276
- innerWrapper.style.left = "50%";
27277
- innerWrapper.style.top = "50%";
27278
- innerWrapper.style.width = `${fragment.geometry.width}px`;
27279
- innerWrapper.style.height = `${fragment.geometry.height}px`;
27280
- innerWrapper.style.transformOrigin = "center";
27281
- const scale = fragment.scale ?? 1;
27282
- const transforms = ["translate(-50%, -50%)"];
27283
- if (!isVectorShapeBlock) {
27284
- transforms.push(`rotate(${fragment.geometry.rotation ?? 0}deg)`);
27285
- transforms.push(`scaleX(${fragment.geometry.flipH ? -1 : 1})`);
27286
- transforms.push(`scaleY(${fragment.geometry.flipV ? -1 : 1})`);
27287
- }
27288
- transforms.push(`scale(${scale})`);
27289
- innerWrapper.style.transform = transforms.join(" ");
27290
- innerWrapper.appendChild(this.renderDrawingContent(block, fragment));
27291
- fragmentEl.appendChild(innerWrapper);
27292
- return fragmentEl;
27293
27576
  }
27294
27577
  renderDrawingContent(block, fragment) {
27295
27578
  if (!this.doc) {
@@ -27724,6 +28007,7 @@ const _DomPainter = class _DomPainter {
27724
28007
  }
27725
28008
  applyRunStyles(elem, run, isActiveLink);
27726
28009
  elem.style.zIndex = "1";
28010
+ applyRunDataAttributes(elem, run.dataAttrs);
27727
28011
  if (run.pmStart != null) elem.dataset.pmStart = String(run.pmStart);
27728
28012
  if (run.pmEnd != null) elem.dataset.pmEnd = String(run.pmEnd);
27729
28013
  if (trackedConfig) {
@@ -27922,6 +28206,33 @@ const _DomPainter = class _DomPainter {
27922
28206
  }
27923
28207
  }
27924
28208
  }
28209
+ /**
28210
+ * Estimates the height of a fragment when explicit height is not available.
28211
+ *
28212
+ * This method provides fallback height calculations for footer bottom-alignment
28213
+ * by consulting measure data for paragraphs and list items, or using the
28214
+ * fragment's height property for tables, images, and drawings.
28215
+ *
28216
+ * @param fragment - The fragment to estimate height for
28217
+ * @returns Estimated height in pixels, or 0 if height cannot be determined
28218
+ */
28219
+ estimateFragmentHeight(fragment) {
28220
+ const lookup = this.blockLookup.get(fragment.blockId);
28221
+ const measure = lookup?.measure;
28222
+ if (fragment.kind === "para" && measure?.kind === "paragraph") {
28223
+ return measure.totalHeight;
28224
+ }
28225
+ if (fragment.kind === "list-item" && measure?.kind === "list") {
28226
+ return measure.totalHeight;
28227
+ }
28228
+ if (fragment.kind === "table") {
28229
+ return fragment.height;
28230
+ }
28231
+ if (fragment.kind === "image" || fragment.kind === "drawing") {
28232
+ return fragment.height;
28233
+ }
28234
+ return 0;
28235
+ }
27925
28236
  buildBlockLookup(blocks, measures) {
27926
28237
  if (blocks.length !== measures.length) {
27927
28238
  throw new Error("DomPainter requires the same number of blocks and measures");
@@ -28104,6 +28415,12 @@ const deriveBlockVersion = (block) => {
28104
28415
  run.kind !== "tab" && run.bold ? 1 : 0,
28105
28416
  run.kind !== "tab" && run.italic ? 1 : 0,
28106
28417
  run.kind !== "tab" ? run.color ?? "" : "",
28418
+ // Text decorations - ensures DOM updates when decoration properties change.
28419
+ run.kind !== "tab" ? run.underline?.style ?? "" : "",
28420
+ run.kind !== "tab" ? run.underline?.color ?? "" : "",
28421
+ run.kind !== "tab" && run.strike ? 1 : 0,
28422
+ run.kind !== "tab" ? run.highlight ?? "" : "",
28423
+ run.kind !== "tab" && run.letterSpacing != null ? run.letterSpacing : "",
28107
28424
  run.pmStart ?? "",
28108
28425
  run.pmEnd ?? "",
28109
28426
  run.kind !== "tab" ? run.token ?? "" : ""
@@ -28198,6 +28515,20 @@ const applyRunStyles = (element, run, isLink = false) => {
28198
28515
  element.style.textDecorationLine = decorations.join(" ");
28199
28516
  }
28200
28517
  };
28518
+ const applyRunDataAttributes = (element, dataAttrs) => {
28519
+ if (!dataAttrs) return;
28520
+ Object.entries(dataAttrs).forEach(([key2, value]) => {
28521
+ if (typeof key2 !== "string" || !key2.toLowerCase().startsWith("data-")) return;
28522
+ if (typeof value !== "string") return;
28523
+ try {
28524
+ element.setAttribute(key2, value);
28525
+ } catch (error) {
28526
+ if (process$1.env.NODE_ENV === "development") {
28527
+ console.warn(`[DomPainter] Failed to set data attribute "${key2}":`, error);
28528
+ }
28529
+ }
28530
+ });
28531
+ };
28201
28532
  const applyParagraphBlockStyles = (element, attrs) => {
28202
28533
  if (!attrs) return;
28203
28534
  if (attrs.alignment) {
@@ -28370,8 +28701,8 @@ const createDomPainter = (options) => {
28370
28701
  paint(layout, mount) {
28371
28702
  painter.paint(layout, mount);
28372
28703
  },
28373
- setData(blocks, measures) {
28374
- painter.setData(blocks, measures);
28704
+ setData(blocks, measures, headerBlocks, headerMeasures, footerBlocks, footerMeasures) {
28705
+ painter.setData(blocks, measures, headerBlocks, headerMeasures, footerBlocks, footerMeasures);
28375
28706
  },
28376
28707
  // Non-standard extension for demo app to avoid re-instantiating on provider changes
28377
28708
  setProviders(header, footer) {
@@ -32007,7 +32338,30 @@ rerender_fn = async function() {
32007
32338
  if (typeof painter.setProviders === "function") {
32008
32339
  painter.setProviders(__privateGet(this, _headerDecorationProvider), __privateGet(this, _footerDecorationProvider));
32009
32340
  }
32010
- painter.setData?.(blocks, measures);
32341
+ const headerBlocks = [];
32342
+ const headerMeasures = [];
32343
+ if (headerLayouts) {
32344
+ for (const headerResult of headerLayouts) {
32345
+ headerBlocks.push(...headerResult.blocks);
32346
+ headerMeasures.push(...headerResult.measures);
32347
+ }
32348
+ }
32349
+ const footerBlocks = [];
32350
+ const footerMeasures = [];
32351
+ if (footerLayouts) {
32352
+ for (const footerResult of footerLayouts) {
32353
+ footerBlocks.push(...footerResult.blocks);
32354
+ footerMeasures.push(...footerResult.measures);
32355
+ }
32356
+ }
32357
+ painter.setData?.(
32358
+ blocks,
32359
+ measures,
32360
+ headerBlocks.length > 0 ? headerBlocks : void 0,
32361
+ headerMeasures.length > 0 ? headerMeasures : void 0,
32362
+ footerBlocks.length > 0 ? footerBlocks : void 0,
32363
+ footerMeasures.length > 0 ? footerMeasures : void 0
32364
+ );
32011
32365
  painter.paint(layout, __privateGet(this, _painterHost));
32012
32366
  __privateSet(this, _layoutError, null);
32013
32367
  __privateSet(this, _layoutErrorState, "healthy");
@@ -32177,7 +32531,8 @@ createDecorationProvider_fn = function(kind, layout) {
32177
32531
  const finalHeaderId = headerId ?? fallbackId ?? void 0;
32178
32532
  return {
32179
32533
  fragments: slotPage.fragments,
32180
- height: variant.layout.height ?? box.height,
32534
+ height: box.height,
32535
+ contentHeight: variant.layout.height ?? box.height,
32181
32536
  offset: box.offset,
32182
32537
  marginLeft: box.x,
32183
32538
  contentWidth: box.width,
@@ -32204,18 +32559,19 @@ computeDecorationBox_fn = function(kind, pageMargins, pageHeight) {
32204
32559
  const left2 = margins.left ?? DEFAULT_MARGINS.left;
32205
32560
  const right2 = margins.right ?? DEFAULT_MARGINS.right;
32206
32561
  const width = Math.max(pageSize.w - (left2 + right2), 1);
32207
- const defaultHeight = kind === "header" ? margins.top ?? DEFAULT_MARGINS.top : margins.bottom ?? DEFAULT_MARGINS.bottom;
32208
- const { headerSpace, footerSpace } = extractHeaderFooterSpace(margins);
32209
- const target = kind === "header" ? headerSpace : footerSpace;
32210
- const height = Math.max(target || defaultHeight || 1, 1);
32211
32562
  const totalHeight = pageHeight ?? pageSize.h;
32212
- const offset2 = kind === "header" ? 0 : Math.max(0, totalHeight - height);
32213
- return {
32214
- x: left2,
32215
- width,
32216
- height,
32217
- offset: offset2
32218
- };
32563
+ if (kind === "header") {
32564
+ const headerMargin = margins.header ?? 0;
32565
+ const topMargin = margins.top ?? DEFAULT_MARGINS.top ?? 0;
32566
+ const height = Math.max(topMargin - headerMargin, 1);
32567
+ return { x: left2, width, height, offset: headerMargin };
32568
+ } else {
32569
+ const footerMargin = margins.footer ?? 0;
32570
+ const bottomMargin = margins.bottom ?? DEFAULT_MARGINS.bottom ?? 0;
32571
+ const height = Math.max(bottomMargin - footerMargin, 1);
32572
+ const offset2 = Math.max(0, totalHeight - footerMargin - height);
32573
+ return { x: left2, width, height, offset: offset2 };
32574
+ }
32219
32575
  };
32220
32576
  rebuildHeaderFooterRegions_fn = function(layout) {
32221
32577
  __privateGet(this, _headerRegions).clear();
@@ -32437,7 +32793,8 @@ getHeaderFooterPageHeight_fn = function() {
32437
32793
  return context.layout.pageSize?.h ?? context.region.height ?? 1;
32438
32794
  };
32439
32795
  renderSelectionRects_fn = function(rects) {
32440
- if (!__privateGet(this, _selectionOverlay)) {
32796
+ const localSelectionLayer = __privateGet(this, _localSelectionLayer);
32797
+ if (!localSelectionLayer) {
32441
32798
  return;
32442
32799
  }
32443
32800
  const pageHeight = __privateMethod(this, _PresentationEditor_instances, getBodyPageHeight_fn).call(this);
@@ -32448,7 +32805,7 @@ renderSelectionRects_fn = function(rects) {
32448
32805
  if (!coords) {
32449
32806
  return;
32450
32807
  }
32451
- const highlight = __privateGet(this, _selectionOverlay).ownerDocument?.createElement("div");
32808
+ const highlight = localSelectionLayer.ownerDocument?.createElement("div");
32452
32809
  if (!highlight) {
32453
32810
  return;
32454
32811
  }
@@ -32461,7 +32818,7 @@ renderSelectionRects_fn = function(rects) {
32461
32818
  highlight.style.backgroundColor = "rgba(51, 132, 255, 0.35)";
32462
32819
  highlight.style.borderRadius = "2px";
32463
32820
  highlight.style.pointerEvents = "none";
32464
- __privateGet(this, _selectionOverlay).appendChild(highlight);
32821
+ localSelectionLayer.appendChild(highlight);
32465
32822
  });
32466
32823
  };
32467
32824
  renderHoverRegion_fn = function(region) {
@@ -32912,6 +33269,7 @@ class PresentationInputBridge {
32912
33269
  __privateAdd(this, _onTargetChanged);
32913
33270
  __privateAdd(this, _listeners);
32914
33271
  __privateAdd(this, _currentTarget, null);
33272
+ __privateAdd(this, _destroyed, false);
32915
33273
  __privateSet(this, _windowRoot, windowRoot);
32916
33274
  __privateSet(this, _visibleHost2, visibleHost);
32917
33275
  __privateSet(this, _getTargetDom, getTargetDom);
@@ -32939,9 +33297,13 @@ class PresentationInputBridge {
32939
33297
  });
32940
33298
  __privateSet(this, _listeners, []);
32941
33299
  __privateSet(this, _currentTarget, null);
33300
+ __privateSet(this, _destroyed, true);
32942
33301
  }
32943
33302
  notifyTargetChanged() {
32944
33303
  var _a;
33304
+ if (__privateGet(this, _destroyed)) {
33305
+ return;
33306
+ }
32945
33307
  const nextTarget = __privateGet(this, _getTargetDom).call(this);
32946
33308
  if (nextTarget === __privateGet(this, _currentTarget)) {
32947
33309
  return;
@@ -32971,6 +33333,7 @@ _getTargetDom = new WeakMap();
32971
33333
  _onTargetChanged = new WeakMap();
32972
33334
  _listeners = new WeakMap();
32973
33335
  _currentTarget = new WeakMap();
33336
+ _destroyed = new WeakMap();
32974
33337
  _PresentationInputBridge_instances = new WeakSet();
32975
33338
  addListener_fn = function(type, handler, target) {
32976
33339
  const bound = handler.bind(this);
@@ -32978,12 +33341,21 @@ addListener_fn = function(type, handler, target) {
32978
33341
  target.addEventListener(type, bound, true);
32979
33342
  };
32980
33343
  dispatchToTarget_fn = function(originalEvent, synthetic) {
33344
+ if (__privateGet(this, _destroyed)) return;
32981
33345
  const target = __privateGet(this, _getTargetDom).call(this);
32982
33346
  __privateSet(this, _currentTarget, target);
32983
33347
  if (!target) return;
32984
- const canceled = !target.dispatchEvent(synthetic) || synthetic.defaultPrevented;
32985
- if (canceled) {
32986
- originalEvent.preventDefault();
33348
+ const isConnected = target.isConnected;
33349
+ if (isConnected === false) return;
33350
+ try {
33351
+ const canceled = !target.dispatchEvent(synthetic) || synthetic.defaultPrevented;
33352
+ if (canceled) {
33353
+ originalEvent.preventDefault();
33354
+ }
33355
+ } catch (error) {
33356
+ if (process$1.env.NODE_ENV === "development") {
33357
+ console.warn("[PresentationEditor] Failed to dispatch event to target:", error);
33358
+ }
32987
33359
  }
32988
33360
  };
32989
33361
  forwardKeyboardEvent_fn = function(event) {