superdoc 1.0.0-beta.15 → 1.0.0-beta.17

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 (29) hide show
  1. package/dist/chunks/{PdfViewer-DltPlBWC.cjs → PdfViewer-BIlJaTm7.cjs} +1 -1
  2. package/dist/chunks/{PdfViewer-CjlHzt9e.es.js → PdfViewer-cvzMUtBh.es.js} +1 -1
  3. package/dist/chunks/{index-qg0AxQJC.es.js → index-CrIfBvBN.es.js} +3 -3
  4. package/dist/chunks/{index-BZnlco_f.cjs → index-DDx90Dl3.cjs} +3 -3
  5. package/dist/chunks/{index-Bds7gW4r-JPDW6c39.cjs → index-VCeRjVPO-DjkejB6t.cjs} +1 -1
  6. package/dist/chunks/{index-Bds7gW4r-Pk_xAuWe.es.js → index-VCeRjVPO-FBgR9qxX.es.js} +1 -1
  7. package/dist/chunks/{super-editor.es-CQTkj_nb.es.js → super-editor.es-00SpI-wK.es.js} +1909 -273
  8. package/dist/chunks/{super-editor.es-CuAhqbzW.cjs → super-editor.es-Mlj7AGyt.cjs} +1909 -273
  9. package/dist/style.css +6 -6
  10. package/dist/super-editor/ai-writer.es.js +2 -2
  11. package/dist/super-editor/chunks/{converter-qMoZOGGn.js → converter-B9zUZjYT.js} +71 -34
  12. package/dist/super-editor/chunks/{docx-zipper-QKiyORxV.js → docx-zipper-r5KdE_SA.js} +1 -1
  13. package/dist/super-editor/chunks/{editor-D8ZdjC2V.js → editor-D2k2BwSG.js} +1743 -232
  14. package/dist/super-editor/chunks/{index-Bds7gW4r.js → index-VCeRjVPO.js} +1 -1
  15. package/dist/super-editor/chunks/{toolbar-Spi7vpev.js → toolbar-8o_LgoiW.js} +2 -2
  16. package/dist/super-editor/converter.es.js +1 -1
  17. package/dist/super-editor/docx-zipper.es.js +2 -2
  18. package/dist/super-editor/editor.es.js +3 -3
  19. package/dist/super-editor/file-zipper.es.js +1 -1
  20. package/dist/super-editor/style.css +6 -6
  21. package/dist/super-editor/super-editor.es.js +131 -42
  22. package/dist/super-editor/toolbar.es.js +2 -2
  23. package/dist/super-editor.cjs +1 -1
  24. package/dist/super-editor.es.js +1 -1
  25. package/dist/superdoc.cjs +2 -2
  26. package/dist/superdoc.es.js +2 -2
  27. package/dist/superdoc.umd.js +1911 -275
  28. package/dist/superdoc.umd.js.map +1 -1
  29. package/package.json +1 -1
@@ -12,8 +12,8 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
12
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, _lastSelectedImageBlockId, _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, findHeaderFooterPageForPageNumber_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, computeCaretLayoutRectFromDOM_fn, computeTableCaretLayoutRect_fn, findLineContainingPos_fn, lineHeightBeforeIndex_fn, getCurrentPageIndex_fn, findRegionForPage_fn, handleLayoutError_fn, decorateError_fn, showLayoutErrorBanner_fn, dismissErrorBanner_fn, createHiddenHost_fn, _windowRoot, _layoutSurfaces, _getTargetDom, _onTargetChanged, _listeners, _currentTarget, _destroyed, _useWindowFallback, _PresentationInputBridge_instances, addListener_fn, dispatchToTarget_fn, forwardKeyboardEvent_fn, forwardTextEvent_fn, forwardCompositionEvent_fn, forwardContextMenu_fn, isEventOnActiveTarget_fn, shouldSkipSurface_fn, isInLayoutSurface_fn, getListenerTargets_fn, isPlainCharacterKey_fn, _DocumentSectionView_instances, init_fn2, addToolTip_fn, _ParagraphNodeView_instances, checkShouldUpdate_fn, updateHTMLAttributes_fn, updateDOMStyles_fn, resolveNeighborParagraphProperties_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, _VectorShapeView_instances, ensureParentPositioned_fn, _ShapeGroupView_instances, ensureParentPositioned_fn2;
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-qMoZOGGn.js";
16
- import { D as DocxZipper } from "./docx-zipper-QKiyORxV.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 decodeRPrFromMarks, ar as calculateResolvedParagraphProperties, as as encodeCSSFromPPr, at as twipsToPixels$2, au as resolveRunProperties, av as encodeCSSFromRPr, aw as generateOrderedListIndex, ax as docxNumberingHelpers, ay as InputRule, az as convertSizeToCSS, aA as SelectionRange, aB as Transform, aC as findParentNodeClosestToPos, aD as isInTable$1, aE as generateDocxRandomId, aF as insertNewRelationship, aG as inchesToPixels, aH as kebabCase, aI as getUnderlineCssString } from "./converter-B9zUZjYT.js";
16
+ import { D as DocxZipper } from "./docx-zipper-r5KdE_SA.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() {
@@ -8225,6 +8225,83 @@ const insertTabChar = () => ({ tr }) => {
8225
8225
  tr.insertText(" ", tr.selection.from, tr.selection.to);
8226
8226
  return true;
8227
8227
  };
8228
+ const splitRunToParagraph = () => (props) => {
8229
+ const { state, view, tr } = props;
8230
+ const { $from, empty: empty2 } = state.selection;
8231
+ if (!empty2) return false;
8232
+ if ($from.parent.type.name !== "run") return false;
8233
+ const handled = splitBlockPatch(state, (transaction) => {
8234
+ view.dispatch(transaction);
8235
+ });
8236
+ if (handled) {
8237
+ tr.setMeta("preventDispatch", true);
8238
+ }
8239
+ return handled;
8240
+ };
8241
+ function splitBlockPatch(state, dispatch) {
8242
+ let { $from } = state.selection;
8243
+ if (state.selection instanceof NodeSelection && state.selection.node.isBlock) {
8244
+ if (!$from.parentOffset || !canSplit(state.doc, $from.pos)) return false;
8245
+ if (dispatch) dispatch(state.tr.split($from.pos).scrollIntoView());
8246
+ return true;
8247
+ }
8248
+ if (!$from.depth) return false;
8249
+ let types = [];
8250
+ let splitDepth, deflt, atEnd = false, atStart = false;
8251
+ for (let d2 = $from.depth; ; d2--) {
8252
+ let node = $from.node(d2);
8253
+ if (node.isBlock) {
8254
+ atEnd = $from.end(d2) == $from.pos + ($from.depth - d2);
8255
+ atStart = $from.start(d2) == $from.pos - ($from.depth - d2);
8256
+ deflt = defaultBlockAt$1($from.node(d2 - 1).contentMatchAt($from.indexAfter(d2 - 1)));
8257
+ types.unshift(null);
8258
+ splitDepth = d2;
8259
+ break;
8260
+ } else {
8261
+ if (d2 == 1) return false;
8262
+ types.unshift(null);
8263
+ }
8264
+ }
8265
+ let tr = state.tr;
8266
+ if (state.selection instanceof TextSelection || state.selection instanceof AllSelection) tr.deleteSelection();
8267
+ let splitPos = tr.mapping.map($from.pos);
8268
+ let can = canSplit(tr.doc, splitPos, types.length, types);
8269
+ if (!can) {
8270
+ types[0] = deflt ? { type: deflt } : null;
8271
+ can = canSplit(tr.doc, splitPos, types.length, types);
8272
+ }
8273
+ if (!can) return false;
8274
+ tr.split(splitPos, types.length, types);
8275
+ if (!atEnd && atStart && $from.node(splitDepth).type != deflt) {
8276
+ let first2 = tr.mapping.map($from.before(splitDepth)), $first = tr.doc.resolve(first2);
8277
+ if (deflt && $from.node(splitDepth - 1).canReplaceWith($first.index(), $first.index() + 1, deflt))
8278
+ tr.setNodeMarkup(tr.mapping.map($from.before(splitDepth)), deflt);
8279
+ }
8280
+ if (dispatch) dispatch(tr.scrollIntoView());
8281
+ return true;
8282
+ }
8283
+ const splitRunAtCursor = () => (props) => {
8284
+ let { state, dispatch, tr } = props;
8285
+ const sel = state.selection;
8286
+ if (!sel.empty) return false;
8287
+ const $pos = sel.$from;
8288
+ const runType = state.schema.nodes.run;
8289
+ if ($pos.parent.type !== runType) return false;
8290
+ const run = $pos.parent;
8291
+ const offset2 = $pos.parentOffset;
8292
+ const runStart = $pos.before();
8293
+ const runEnd = runStart + run.nodeSize;
8294
+ const leftFrag = run.content.cut(0, offset2);
8295
+ const rightFrag = run.content.cut(offset2);
8296
+ const leftRun = runType.create(run.attrs, leftFrag, run.marks);
8297
+ const rightRun = runType.create(run.attrs, rightFrag, run.marks);
8298
+ const gapPos = runStart + leftRun.nodeSize;
8299
+ tr.replaceWith(runStart, runEnd, [leftRun, rightRun]).setSelection(TextSelection.create(tr.doc, gapPos));
8300
+ if (dispatch) {
8301
+ dispatch(tr);
8302
+ }
8303
+ return true;
8304
+ };
8228
8305
  const insertTabCharacter = ({ tr, state, dispatch }) => {
8229
8306
  const { from: from2 } = tr.selection;
8230
8307
  const tabText = state.schema.text(" ");
@@ -8234,10 +8311,23 @@ const insertTabCharacter = ({ tr, state, dispatch }) => {
8234
8311
  return true;
8235
8312
  };
8236
8313
  const insertTabNode = () => ({ tr, state, dispatch }) => {
8237
- const newPos = tr.selection.from;
8314
+ let newPos = tr.selection.from;
8238
8315
  const tabNode = state.schema?.nodes?.tab?.create();
8239
8316
  if (!tabNode) return insertTabCharacter({ tr, state, dispatch });
8317
+ const { from: from2 } = tr.selection;
8318
+ const $pos = tr.doc.resolve(from2);
8319
+ if ($pos.parent.type === state.schema.nodes.run) {
8320
+ if (from2 === $pos.end()) {
8321
+ newPos = $pos.end() + 1;
8322
+ } else if (from2 === $pos.start()) {
8323
+ newPos = $pos.start() - 1;
8324
+ } else {
8325
+ splitRunAtCursor()({ tr, state });
8326
+ newPos = tr.selection.from;
8327
+ }
8328
+ }
8240
8329
  tr.insert(newPos, tabNode);
8330
+ tr = tr.setSelection(TextSelection.create(tr.doc, newPos + tabNode.nodeSize));
8241
8331
  if (dispatch) dispatch(tr);
8242
8332
  return true;
8243
8333
  };
@@ -9693,6 +9783,139 @@ const unsetLineHeight = () => ({ commands: commands2 }) => {
9693
9783
  "paragraphProperties.spacing.lineRule"
9694
9784
  );
9695
9785
  };
9786
+ const backspaceEmptyRunParagraph = () => ({ state, dispatch }) => {
9787
+ const { $from } = state.selection;
9788
+ if (!state.selection.empty) return false;
9789
+ const paraType = state.schema.nodes.paragraph;
9790
+ const runType = state.schema.nodes.run;
9791
+ const para = $from.parent;
9792
+ if (para.type !== paraType || para.childCount !== 1 || para.firstChild.type !== runType || para.firstChild.content.size)
9793
+ return false;
9794
+ if (state.doc.childCount === 1 && $from.depth === 1) return false;
9795
+ if (dispatch) {
9796
+ const paraPos = $from.before();
9797
+ let tr = state.tr.deleteRange(paraPos, paraPos + para.nodeSize).scrollIntoView();
9798
+ const targetPos = Math.max(1, Math.min(paraPos - 1, tr.doc.content.size));
9799
+ tr = tr.setSelection(TextSelection.create(tr.doc, targetPos));
9800
+ dispatch(tr);
9801
+ }
9802
+ return true;
9803
+ };
9804
+ const backspaceSkipEmptyRun = () => ({ state, dispatch }) => {
9805
+ const sel = state.selection;
9806
+ if (!sel.empty) return false;
9807
+ const runType = state.schema.nodes.run;
9808
+ const $pos = sel.$from;
9809
+ const emptyRun = (n) => n && n.type === runType && n.content.size === 0;
9810
+ if ($pos.parent.type !== runType || $pos.pos !== $pos.end() || !emptyRun(state.doc.nodeAt($pos.pos + 1))) {
9811
+ return false;
9812
+ }
9813
+ const leftTextSel = Selection.findFrom($pos, -1, true);
9814
+ if (!leftTextSel) return false;
9815
+ const pos = leftTextSel.$from.pos;
9816
+ if (dispatch) {
9817
+ dispatch(state.tr.delete(pos - 1, pos).scrollIntoView());
9818
+ }
9819
+ return true;
9820
+ };
9821
+ const backspaceNextToRun = () => ({ state, tr, dispatch }) => {
9822
+ const sel = state.selection;
9823
+ if (!sel.empty) return false;
9824
+ const runType = state.schema.nodes.run;
9825
+ const $pos = sel.$from;
9826
+ if ($pos.nodeBefore?.type !== runType && $pos.pos !== $pos.start()) return false;
9827
+ if ($pos.nodeBefore) {
9828
+ if ($pos.nodeBefore.content.size === 0) return false;
9829
+ tr.delete($pos.pos - 2, $pos.pos - 1).setSelection(Selection.near(tr.doc.resolve($pos.pos - 2)));
9830
+ if (dispatch) {
9831
+ dispatch(tr.scrollIntoView());
9832
+ }
9833
+ } else {
9834
+ const prevNode = state.doc.resolve($pos.start() - 1).nodeBefore;
9835
+ if (prevNode?.type !== runType || prevNode.content.size === 0) return false;
9836
+ tr.delete($pos.pos - 3, $pos.pos - 2).setSelection(Selection.near(tr.doc.resolve($pos.pos - 3)));
9837
+ if (dispatch) {
9838
+ dispatch(tr.scrollIntoView());
9839
+ }
9840
+ }
9841
+ return true;
9842
+ };
9843
+ const deleteSkipEmptyRun = () => ({ state, dispatch }) => {
9844
+ const sel = state.selection;
9845
+ if (!sel.empty) return false;
9846
+ const runType = state.schema.nodes.run;
9847
+ const $pos = sel.$from;
9848
+ const emptyRun = (n) => n && n.type === runType && n.content.size === 0;
9849
+ if ($pos.parent.type === runType && emptyRun(state.doc.nodeAt($pos.end() + 1))) {
9850
+ if ($pos.pos === $pos.end()) {
9851
+ return deleteFromEndOfRun(state, dispatch, $pos);
9852
+ } else if ($pos.pos === $pos.end() - 1) {
9853
+ return deleteFromLastCharacter(state, dispatch, $pos);
9854
+ }
9855
+ return false;
9856
+ }
9857
+ return false;
9858
+ };
9859
+ function deleteFromEndOfRun(state, dispatch, $pos) {
9860
+ const rightRun = state.doc.nodeAt($pos.pos + 1);
9861
+ const $afterRightRunPos = state.doc.resolve($pos.pos + 2 + rightRun.nodeSize);
9862
+ const rightTextSel = Selection.findFrom($afterRightRunPos, 1, true);
9863
+ if (!rightTextSel) return false;
9864
+ const pos = rightTextSel.$from.pos;
9865
+ if (dispatch) {
9866
+ dispatch(state.tr.delete(pos, pos + 1).scrollIntoView());
9867
+ }
9868
+ return true;
9869
+ }
9870
+ function deleteFromLastCharacter(state, dispatch, $pos) {
9871
+ if (dispatch) {
9872
+ dispatch(state.tr.delete($pos.pos, $pos.pos + 1).scrollIntoView());
9873
+ }
9874
+ return true;
9875
+ }
9876
+ const deleteNextToRun = () => ({ state, tr, dispatch }) => {
9877
+ const sel = state.selection;
9878
+ if (!sel.empty) return false;
9879
+ const runType = state.schema.nodes.run;
9880
+ const $pos = sel.$from;
9881
+ if ($pos.nodeAfter?.type !== runType && $pos.pos !== $pos.end()) return false;
9882
+ if ($pos.nodeAfter) {
9883
+ if ($pos.nodeAfter.content.size === 0) return false;
9884
+ tr.delete($pos.pos + 1, $pos.pos + 2).setSelection(Selection.near(tr.doc.resolve($pos.pos + 1)));
9885
+ if (dispatch) {
9886
+ dispatch(tr.scrollIntoView());
9887
+ }
9888
+ } else {
9889
+ const nextNode = state.doc.resolve($pos.end() + 1).nodeAfter;
9890
+ if (nextNode?.type !== runType || nextNode.content.size === 0) return false;
9891
+ tr.delete($pos.pos + 2, $pos.pos + 3).setSelection(Selection.near(tr.doc.resolve($pos.pos + 2)));
9892
+ if (dispatch) {
9893
+ dispatch(tr.scrollIntoView());
9894
+ }
9895
+ }
9896
+ return true;
9897
+ };
9898
+ function skipTab(dir) {
9899
+ return ({ state, dispatch }) => {
9900
+ const tab = state.schema.nodes.tab;
9901
+ const run = state.schema.nodes.run;
9902
+ const sel = state.selection;
9903
+ if (!tab || !sel.empty) return false;
9904
+ const $pos = sel.$from;
9905
+ if ($pos.parent.type !== run) return false;
9906
+ if (dir > 0 && $pos.pos < $pos.end()) return false;
9907
+ if (dir < 0 && $pos.pos > $pos.start()) return false;
9908
+ const step = dir > 0 ? 1 : -1;
9909
+ let $nextPos = state.doc.resolve($pos.pos + step);
9910
+ const nextNode = dir > 0 ? $nextPos.nodeAfter : $nextPos.nodeBefore;
9911
+ if (!nextNode || nextNode.type !== tab) return false;
9912
+ const nextPos = dir > 0 ? Math.min($nextPos.pos + nextNode.nodeSize + 1, state.doc.nodeSize) : Math.max(0, $nextPos.pos - nextNode.nodeSize - 1);
9913
+ if (dispatch) {
9914
+ dispatch(state.tr.setSelection(TextSelection.create(state.doc, nextPos)));
9915
+ }
9916
+ return true;
9917
+ };
9918
+ }
9696
9919
  const toggleList = (listType) => ({ editor, state, tr, dispatch }) => {
9697
9920
  let predicate;
9698
9921
  if (listType === "orderedList") {
@@ -9768,6 +9991,13 @@ const toggleList = (listType) => ({ editor, state, tr, dispatch }) => {
9768
9991
  }
9769
9992
  updateNumberingProperties(sharedNumberingProperties, node, pos, editor, tr);
9770
9993
  }
9994
+ const newTo = tr.mapping.map(to);
9995
+ if (newTo >= 0 && newTo <= tr.doc.content.size) {
9996
+ try {
9997
+ tr.setSelection(state.selection.constructor.near(tr.doc.resolve(newTo)));
9998
+ } catch {
9999
+ }
10000
+ }
9771
10001
  if (dispatch) dispatch(tr);
9772
10002
  return true;
9773
10003
  };
@@ -9886,6 +10116,9 @@ const getSelectionMarks = () => ({ state, tr }) => {
9886
10116
  };
9887
10117
  const commands$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
9888
10118
  __proto__: null,
10119
+ backspaceEmptyRunParagraph,
10120
+ backspaceNextToRun,
10121
+ backspaceSkipEmptyRun,
9889
10122
  changeListLevel,
9890
10123
  clearNodes,
9891
10124
  command,
@@ -9893,7 +10126,9 @@ const commands$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
9893
10126
  decreaseListIndent,
9894
10127
  decreaseTextIndent,
9895
10128
  defaultStyleDetector,
10129
+ deleteNextToRun,
9896
10130
  deleteSelection,
10131
+ deleteSkipEmptyRun,
9897
10132
  exitCode,
9898
10133
  first,
9899
10134
  getEffectiveStyleId,
@@ -9931,6 +10166,7 @@ const commands$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
9931
10166
  setSectionHeaderFooterAtSelection,
9932
10167
  setTextIndentation,
9933
10168
  setTextSelection,
10169
+ skipTab,
9934
10170
  splitBlock: splitBlock$1,
9935
10171
  toggleList,
9936
10172
  toggleMark,
@@ -9952,7 +10188,7 @@ const Commands = Extension.create({
9952
10188
  });
9953
10189
  const handleEnter = (editor) => {
9954
10190
  return editor.commands.first(({ commands: commands2 }) => [
9955
- () => commands2.splitRun(),
10191
+ () => commands2.splitRunToParagraph(),
9956
10192
  () => commands2.newlineInCode(),
9957
10193
  () => commands2.createParagraphNear(),
9958
10194
  () => commands2.liftEmptyBlock(),
@@ -9966,6 +10202,9 @@ const handleBackspace = (editor) => {
9966
10202
  tr.setMeta("inputType", "deleteContentBackward");
9967
10203
  return false;
9968
10204
  },
10205
+ () => commands2.backspaceEmptyRunParagraph(),
10206
+ () => commands2.backspaceSkipEmptyRun(),
10207
+ () => commands2.backspaceNextToRun(),
9969
10208
  () => commands2.deleteSelection(),
9970
10209
  () => commands2.removeNumberingProperties(),
9971
10210
  () => commands2.joinBackward(),
@@ -9974,6 +10213,8 @@ const handleBackspace = (editor) => {
9974
10213
  };
9975
10214
  const handleDelete = (editor) => {
9976
10215
  return editor.commands.first(({ commands: commands2 }) => [
10216
+ () => commands2.deleteSkipEmptyRun(),
10217
+ () => commands2.deleteNextToRun(),
9977
10218
  () => commands2.deleteSelection(),
9978
10219
  () => commands2.joinForward(),
9979
10220
  () => commands2.selectNodeForward()
@@ -9992,7 +10233,9 @@ const Keymap = Extension.create({
9992
10233
  Delete: () => handleDelete(this.editor),
9993
10234
  "Mod-Delete": () => handleDelete(this.editor),
9994
10235
  "Mod-a": () => this.editor.commands.selectAll(),
9995
- Tab: () => this.editor.commands.insertTabNode()
10236
+ Tab: () => this.editor.commands.insertTabNode(),
10237
+ ArrowLeft: () => this.editor.commands.skipTab(-1),
10238
+ ArrowRight: () => this.editor.commands.skipTab(1)
9996
10239
  };
9997
10240
  const pcBaseKeymap = {
9998
10241
  ...baseKeymap
@@ -13574,7 +13817,7 @@ const isHeadless = (editor) => {
13574
13817
  const shouldSkipNodeView = (editor) => {
13575
13818
  return isHeadless(editor);
13576
13819
  };
13577
- const summaryVersion = "1.0.0-beta.15";
13820
+ const summaryVersion = "1.0.0-beta.17";
13578
13821
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
13579
13822
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
13580
13823
  function mapAttributes(attrs) {
@@ -14087,12 +14330,9 @@ const _Editor = class _Editor extends EventEmitter {
14087
14330
  if (!this.schema) {
14088
14331
  throw new Error("Schema is not initialized.");
14089
14332
  }
14090
- const topNodeName = this.schema.topNodeType?.name || "doc";
14091
- const normalizedDoc = Array.isArray(doc2) ? { type: topNodeName, content: doc2 } : doc2 && typeof doc2 === "object" && doc2.type ? doc2.type === topNodeName || doc2.type === "doc" ? doc2 : { type: topNodeName, content: [doc2] } : (() => {
14092
- throw new Error("Invalid document shape: expected a node object or an array of node objects.");
14093
- })();
14094
14333
  try {
14095
- return this.schema.nodeFromJSON(normalizedDoc);
14334
+ if (Array.isArray(doc2)) return doc2.map((d2) => this.schema.nodeFromJSON(d2));
14335
+ return this.schema.nodeFromJSON(doc2);
14096
14336
  } catch (error) {
14097
14337
  const detail = error instanceof Error ? error.message : String(error);
14098
14338
  const validationError = new Error(`Invalid document for current schema: ${detail}`);
@@ -14356,7 +14596,7 @@ const _Editor = class _Editor extends EventEmitter {
14356
14596
  { default: remarkStringify },
14357
14597
  { default: remarkGfm }
14358
14598
  ] = await Promise.all([
14359
- import("./index-Bds7gW4r.js"),
14599
+ import("./index-VCeRjVPO.js"),
14360
14600
  import("./index-DRCvimau.js"),
14361
14601
  import("./index-C_x_N6Uh.js"),
14362
14602
  import("./index-D_sWOSiG.js"),
@@ -14561,7 +14801,7 @@ const _Editor = class _Editor extends EventEmitter {
14561
14801
  * Process collaboration migrations
14562
14802
  */
14563
14803
  processCollaborationMigrations() {
14564
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.15");
14804
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.17");
14565
14805
  if (!this.options.ydoc) return;
14566
14806
  const metaMap = this.options.ydoc.getMap("meta");
14567
14807
  let docVersion = metaMap.get("version");
@@ -15724,7 +15964,7 @@ const pickLang = (value) => {
15724
15964
  const normalized = value.trim().toLowerCase();
15725
15965
  return normalized || void 0;
15726
15966
  };
15727
- const normalizeColor = (value) => {
15967
+ const normalizeColor$1 = (value) => {
15728
15968
  if (typeof value !== "string") return void 0;
15729
15969
  const trimmed = value.trim();
15730
15970
  if (!trimmed || trimmed === "auto" || trimmed === "none") return void 0;
@@ -16364,14 +16604,14 @@ const resolveThemeColor = (attrs, themeColors) => {
16364
16604
  const resolveColorFromAttributes = (attrs, themeColors) => {
16365
16605
  if (!attrs) return void 0;
16366
16606
  if (typeof attrs.color === "string") {
16367
- const normalized = normalizeColor(attrs.color);
16607
+ const normalized = normalizeColor$1(attrs.color);
16368
16608
  if (normalized) {
16369
16609
  return normalized;
16370
16610
  }
16371
16611
  }
16372
16612
  const theme = resolveThemeColor(attrs, themeColors);
16373
16613
  if (theme) {
16374
- return normalizeColor(theme);
16614
+ return normalizeColor$1(theme);
16375
16615
  }
16376
16616
  return void 0;
16377
16617
  };
@@ -16806,13 +17046,8 @@ const MAX_BORDER_SIZE_PX = 100;
16806
17046
  const borderSizeToPx = (size) => {
16807
17047
  if (!isFiniteNumber(size)) return void 0;
16808
17048
  if (size <= 0) return 0;
16809
- let pixelValue;
16810
- if (size < EIGHTHS_PER_POINT) {
16811
- pixelValue = size;
16812
- } else {
16813
- const points = size / EIGHTHS_PER_POINT;
16814
- pixelValue = points * PX_PER_PT;
16815
- }
17049
+ const points = size / EIGHTHS_PER_POINT;
17050
+ const pixelValue = points * PX_PER_PT;
16816
17051
  return Math.min(MAX_BORDER_SIZE_PX, Math.max(MIN_BORDER_SIZE_PX, pixelValue));
16817
17052
  };
16818
17053
  const normalizeColorWithDefault = (color) => {
@@ -16951,7 +17186,7 @@ const normalizeBorderSide = (value) => {
16951
17186
  if (style === "none") return void 0;
16952
17187
  const width = pickNumber(raw.size);
16953
17188
  const widthPx = borderSizeToPx(width);
16954
- const color = normalizeColor(raw.color);
17189
+ const color = normalizeColor$1(raw.color);
16955
17190
  const space = pickNumber(raw.space);
16956
17191
  if (!style && widthPx == null && space == null && !color) {
16957
17192
  return void 0;
@@ -17007,7 +17242,7 @@ const normalizeParagraphShading = (value) => {
17007
17242
  return Object.keys(shading).length > 0 ? shading : void 0;
17008
17243
  };
17009
17244
  const normalizeShadingColor = (value) => {
17010
- const normalized = normalizeColor(value);
17245
+ const normalized = normalizeColor$1(value);
17011
17246
  if (!normalized) return void 0;
17012
17247
  if (normalized.toLowerCase() === "#auto") {
17013
17248
  return void 0;
@@ -18170,11 +18405,11 @@ const buildMarkerLayout = ({
18170
18405
  baselineOffsetPx: markerRun.baselineShift ?? 0,
18171
18406
  gutterWidthPx: markerBoxWidthPx,
18172
18407
  justification: numbering.lvlJc ?? "left",
18173
- suffix: normalizeSuffix(numbering.suffix) ?? "tab",
18408
+ suffix: normalizeSuffix$1(numbering.suffix) ?? "tab",
18174
18409
  run: markerRun,
18175
18410
  path: numbering.path
18176
18411
  });
18177
- const normalizeSuffix = (suffix) => {
18412
+ const normalizeSuffix$1 = (suffix) => {
18178
18413
  if (suffix === "tab" || suffix === "space" || suffix === "nothing") {
18179
18414
  return suffix;
18180
18415
  }
@@ -18628,6 +18863,154 @@ const cloneIfObject = (value) => {
18628
18863
  };
18629
18864
  const { resolveSpacingIndent } = Engines;
18630
18865
  const DEFAULT_DECIMAL_SEPARATOR$2 = ".";
18866
+ const asOoxmlElement = (value) => {
18867
+ if (!value || typeof value !== "object") return void 0;
18868
+ const element = value;
18869
+ if (element.name == null && element.attributes == null && element.elements == null) return void 0;
18870
+ return element;
18871
+ };
18872
+ const findChild = (parent, name) => {
18873
+ return parent?.elements?.find((child) => child?.name === name);
18874
+ };
18875
+ const getAttribute = (element, key2) => {
18876
+ if (!element?.attributes) return void 0;
18877
+ const attrs = element.attributes;
18878
+ return attrs[key2] ?? attrs[key2.startsWith("w:") ? key2.slice(2) : `w:${key2}`];
18879
+ };
18880
+ const parseNumberAttr = (value) => {
18881
+ if (value == null) return void 0;
18882
+ const num = typeof value === "number" ? value : Number.parseInt(String(value), 10);
18883
+ return Number.isFinite(num) ? num : void 0;
18884
+ };
18885
+ const normalizeNumFmt = (value) => {
18886
+ if (typeof value !== "string") return void 0;
18887
+ switch (value) {
18888
+ case "decimal":
18889
+ return "decimal";
18890
+ case "lowerLetter":
18891
+ return "lowerLetter";
18892
+ case "upperLetter":
18893
+ return "upperLetter";
18894
+ case "lowerRoman":
18895
+ return "lowerRoman";
18896
+ case "upperRoman":
18897
+ return "upperRoman";
18898
+ case "bullet":
18899
+ return "bullet";
18900
+ default:
18901
+ return void 0;
18902
+ }
18903
+ };
18904
+ const normalizeSuffix = (value) => {
18905
+ if (typeof value !== "string") return void 0;
18906
+ if (value === "tab" || value === "space" || value === "nothing") {
18907
+ return value;
18908
+ }
18909
+ return void 0;
18910
+ };
18911
+ const normalizeJustification = (value) => {
18912
+ if (typeof value !== "string") return void 0;
18913
+ if (value === "start") return "left";
18914
+ if (value === "end") return "right";
18915
+ if (value === "left" || value === "center" || value === "right") return value;
18916
+ return void 0;
18917
+ };
18918
+ const extractIndentFromLevel = (lvl) => {
18919
+ const pPr = findChild(lvl, "w:pPr");
18920
+ const ind = findChild(pPr, "w:ind");
18921
+ if (!ind) return void 0;
18922
+ const left2 = parseNumberAttr(getAttribute(ind, "w:left"));
18923
+ const right2 = parseNumberAttr(getAttribute(ind, "w:right"));
18924
+ const firstLine = parseNumberAttr(getAttribute(ind, "w:firstLine"));
18925
+ const hanging = parseNumberAttr(getAttribute(ind, "w:hanging"));
18926
+ const indent = {};
18927
+ if (left2 != null) indent.left = left2;
18928
+ if (right2 != null) indent.right = right2;
18929
+ if (firstLine != null) indent.firstLine = firstLine;
18930
+ if (hanging != null) indent.hanging = hanging;
18931
+ return Object.keys(indent).length ? indent : void 0;
18932
+ };
18933
+ const normalizeColor = (value) => {
18934
+ if (typeof value !== "string") return void 0;
18935
+ const trimmed = value.trim();
18936
+ if (!trimmed || trimmed.toLowerCase() === "auto") return void 0;
18937
+ const upper = trimmed.startsWith("#") ? trimmed.slice(1) : trimmed;
18938
+ return `#${upper.toUpperCase()}`;
18939
+ };
18940
+ const extractMarkerRun = (lvl) => {
18941
+ const rPr = findChild(lvl, "w:rPr");
18942
+ if (!rPr) return void 0;
18943
+ const run = {};
18944
+ const rFonts = findChild(rPr, "w:rFonts");
18945
+ const font = getAttribute(rFonts, "w:ascii") ?? getAttribute(rFonts, "w:hAnsi") ?? getAttribute(rFonts, "w:eastAsia");
18946
+ if (typeof font === "string" && font.trim()) {
18947
+ run.fontFamily = font;
18948
+ }
18949
+ const sz = parseNumberAttr(getAttribute(findChild(rPr, "w:sz"), "w:val")) ?? parseNumberAttr(getAttribute(findChild(rPr, "w:szCs"), "w:val"));
18950
+ if (sz != null) {
18951
+ run.fontSize = sz / 2;
18952
+ }
18953
+ const color = normalizeColor(getAttribute(findChild(rPr, "w:color"), "w:val"));
18954
+ if (color) run.color = color;
18955
+ if (findChild(rPr, "w:b")) run.bold = true;
18956
+ if (findChild(rPr, "w:i")) run.italic = true;
18957
+ const spacingTwips = parseNumberAttr(getAttribute(findChild(rPr, "w:spacing"), "w:val"));
18958
+ if (spacingTwips != null && Number.isFinite(spacingTwips)) {
18959
+ run.letterSpacing = twipsToPx$1(spacingTwips);
18960
+ }
18961
+ return Object.keys(run).length ? run : void 0;
18962
+ };
18963
+ const findNumFmtElement = (lvl) => {
18964
+ if (!lvl) return void 0;
18965
+ const direct = findChild(lvl, "w:numFmt");
18966
+ if (direct) return direct;
18967
+ const alternate = findChild(lvl, "mc:AlternateContent");
18968
+ const choice = findChild(alternate, "mc:Choice");
18969
+ if (choice) {
18970
+ return findChild(choice, "w:numFmt");
18971
+ }
18972
+ return void 0;
18973
+ };
18974
+ const resolveNumberingFromContext = (numId, ilvl, numbering) => {
18975
+ const definitions = numbering?.definitions;
18976
+ const abstracts = numbering?.abstracts;
18977
+ if (!definitions || !abstracts) return void 0;
18978
+ const numDef = asOoxmlElement(definitions[String(numId)]);
18979
+ if (!numDef) return void 0;
18980
+ const abstractId = getAttribute(findChild(numDef, "w:abstractNumId"), "w:val");
18981
+ if (abstractId == null) return void 0;
18982
+ const abstract = asOoxmlElement(abstracts[String(abstractId)]);
18983
+ if (!abstract) return void 0;
18984
+ let levelDef = abstract.elements?.find(
18985
+ (el) => el?.name === "w:lvl" && parseNumberAttr(el.attributes?.["w:ilvl"]) === ilvl
18986
+ );
18987
+ const override = numDef.elements?.find(
18988
+ (el) => el?.name === "w:lvlOverride" && parseNumberAttr(el.attributes?.["w:ilvl"]) === ilvl
18989
+ );
18990
+ const overrideLvl = findChild(override, "w:lvl");
18991
+ if (overrideLvl) {
18992
+ levelDef = overrideLvl;
18993
+ }
18994
+ const startOverride = parseNumberAttr(getAttribute(findChild(override, "w:startOverride"), "w:val"));
18995
+ if (!levelDef) return void 0;
18996
+ const numFmtEl = findNumFmtElement(levelDef);
18997
+ const lvlText = getAttribute(findChild(levelDef, "w:lvlText"), "w:val");
18998
+ const start2 = startOverride ?? parseNumberAttr(getAttribute(findChild(levelDef, "w:start"), "w:val"));
18999
+ const suffix = normalizeSuffix(getAttribute(findChild(levelDef, "w:suff"), "w:val"));
19000
+ const lvlJc = normalizeJustification(getAttribute(findChild(levelDef, "w:lvlJc"), "w:val"));
19001
+ const indent = extractIndentFromLevel(levelDef);
19002
+ const markerRun = extractMarkerRun(levelDef);
19003
+ const numFmt = normalizeNumFmt(getAttribute(numFmtEl, "w:val"));
19004
+ return {
19005
+ format: numFmt,
19006
+ lvlText,
19007
+ start: start2,
19008
+ suffix,
19009
+ lvlJc,
19010
+ resolvedLevelIndent: indent,
19011
+ resolvedMarkerRpr: markerRun
19012
+ };
19013
+ };
18631
19014
  const isTruthy = (value) => {
18632
19015
  if (value === true || value === 1) return true;
18633
19016
  if (typeof value === "string") {
@@ -19260,6 +19643,30 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
19260
19643
  const ilvl = Number.isFinite(numberingProps.ilvl) ? Math.max(0, Math.floor(Number(numberingProps.ilvl))) : 0;
19261
19644
  const listRendering = normalizeListRenderingAttrs(attrs.listRendering);
19262
19645
  const numericNumId = typeof numId === "number" ? numId : void 0;
19646
+ const resolvedLevel = resolveNumberingFromContext(numId, ilvl, converterContext?.numbering);
19647
+ if (resolvedLevel) {
19648
+ if (resolvedLevel.format && numberingProps.format == null) {
19649
+ numberingProps.format = resolvedLevel.format;
19650
+ }
19651
+ if (resolvedLevel.lvlText && numberingProps.lvlText == null) {
19652
+ numberingProps.lvlText = resolvedLevel.lvlText;
19653
+ }
19654
+ if (resolvedLevel.start != null && numberingProps.start == null) {
19655
+ numberingProps.start = resolvedLevel.start;
19656
+ }
19657
+ if (resolvedLevel.suffix && numberingProps.suffix == null) {
19658
+ numberingProps.suffix = resolvedLevel.suffix;
19659
+ }
19660
+ if (resolvedLevel.lvlJc && numberingProps.lvlJc == null) {
19661
+ numberingProps.lvlJc = resolvedLevel.lvlJc;
19662
+ }
19663
+ if (resolvedLevel.resolvedLevelIndent && !numberingProps.resolvedLevelIndent) {
19664
+ numberingProps.resolvedLevelIndent = resolvedLevel.resolvedLevelIndent;
19665
+ }
19666
+ if (resolvedLevel.resolvedMarkerRpr && !numberingProps.resolvedMarkerRpr) {
19667
+ numberingProps.resolvedMarkerRpr = resolvedLevel.resolvedMarkerRpr;
19668
+ }
19669
+ }
19263
19670
  let counterValue = 1;
19264
19671
  if (listCounterContext && typeof numericNumId === "number") {
19265
19672
  counterValue = listCounterContext.incrementListCounter(numericNumId, ilvl);
@@ -20485,41 +20892,45 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
20485
20892
  }
20486
20893
  return;
20487
20894
  }
20488
- if (node.type === "hardBreak") {
20489
- flushParagraph();
20490
- blocks.push({
20491
- kind: "pageBreak",
20492
- id: nextId(),
20493
- attrs: node.attrs || {}
20494
- });
20495
- return;
20496
- }
20497
- if (node.type === "lineBreak") {
20895
+ if (node.type === "hardBreak" || node.type === "lineBreak") {
20498
20896
  const attrs = node.attrs ?? {};
20499
- if (attrs.lineBreakType === "column") {
20897
+ const breakType = attrs.pageBreakType ?? attrs.lineBreakType ?? "line";
20898
+ if (breakType === "page") {
20899
+ flushParagraph();
20900
+ blocks.push({
20901
+ kind: "pageBreak",
20902
+ id: nextId(),
20903
+ attrs: node.attrs || {}
20904
+ });
20905
+ return;
20906
+ }
20907
+ if (breakType === "column") {
20500
20908
  flushParagraph();
20501
20909
  blocks.push({
20502
20910
  kind: "columnBreak",
20503
20911
  id: nextId(),
20504
20912
  attrs: node.attrs || {}
20505
20913
  });
20914
+ return;
20915
+ }
20916
+ const lineBreakRun = { kind: "lineBreak", attrs: {} };
20917
+ const lbAttrs = {};
20918
+ if (attrs.lineBreakType) lbAttrs.lineBreakType = String(attrs.lineBreakType);
20919
+ if (attrs.clear) lbAttrs.clear = String(attrs.clear);
20920
+ if (Object.keys(lbAttrs).length > 0) {
20921
+ lineBreakRun.attrs = lbAttrs;
20506
20922
  } else {
20507
- const lineBreakRun = { kind: "lineBreak", attrs: {} };
20508
- const lbAttrs = {};
20509
- if (attrs.lineBreakType) lbAttrs.lineBreakType = String(attrs.lineBreakType);
20510
- if (attrs.clear) lbAttrs.clear = String(attrs.clear);
20511
- if (Object.keys(lbAttrs).length > 0) {
20512
- lineBreakRun.attrs = lbAttrs;
20513
- } else {
20514
- delete lineBreakRun.attrs;
20515
- }
20516
- const pos = positions.get(node);
20517
- if (pos) {
20518
- lineBreakRun.pmStart = pos.start;
20519
- lineBreakRun.pmEnd = pos.end;
20520
- }
20521
- currentRuns.push(lineBreakRun);
20923
+ delete lineBreakRun.attrs;
20924
+ }
20925
+ const pos = positions.get(node);
20926
+ if (pos) {
20927
+ lineBreakRun.pmStart = pos.start;
20928
+ lineBreakRun.pmEnd = pos.end;
20522
20929
  }
20930
+ if (activeSdt) {
20931
+ lineBreakRun.sdt = activeSdt;
20932
+ }
20933
+ currentRuns.push(lineBreakRun);
20523
20934
  return;
20524
20935
  }
20525
20936
  };
@@ -21112,6 +21523,22 @@ const normalizeTableWidth = (value) => {
21112
21523
  };
21113
21524
  const isTableRowNode = (node) => node.type === "tableRow" || node.type === "table_row";
21114
21525
  const isTableCellNode = (node) => node.type === "tableCell" || node.type === "table_cell" || node.type === "tableHeader" || node.type === "table_header";
21526
+ const normalizeRowHeight = (rowProps) => {
21527
+ if (!rowProps || typeof rowProps !== "object") return void 0;
21528
+ const rawRowHeight = rowProps.rowHeight;
21529
+ if (!rawRowHeight || typeof rawRowHeight !== "object") return void 0;
21530
+ const heightObj = rawRowHeight;
21531
+ const rawValue = pickNumber(heightObj.value ?? heightObj.val);
21532
+ if (rawValue == null) return void 0;
21533
+ const rawRule = heightObj.rule ?? heightObj.hRule;
21534
+ const rule = rawRule === "exact" || rawRule === "atLeast" || rawRule === "auto" ? rawRule : "atLeast";
21535
+ const isLikelyTwips = rawValue >= 300 || Math.abs(rawValue % 15) < 1e-6;
21536
+ const valuePx = isLikelyTwips ? twipsToPx$1(rawValue) : rawValue;
21537
+ return {
21538
+ value: valuePx,
21539
+ rule
21540
+ };
21541
+ };
21115
21542
  const parseTableCell = (args) => {
21116
21543
  const { cellNode, rowIndex, cellIndex, context, defaultCellPadding } = args;
21117
21544
  if (!isTableCellNode(cellNode) || !Array.isArray(cellNode.content)) {
@@ -21149,8 +21576,9 @@ const parseTableCell = (args) => {
21149
21576
  const padding = extractCellPadding(cellNode.attrs ?? {}) ?? (defaultCellPadding ? { ...defaultCellPadding } : void 0);
21150
21577
  if (padding) cellAttrs.padding = padding;
21151
21578
  const verticalAlign = cellNode.attrs?.verticalAlign;
21152
- if (verticalAlign === "top" || verticalAlign === "middle" || verticalAlign === "bottom") {
21153
- cellAttrs.verticalAlign = verticalAlign;
21579
+ const normalizedVerticalAlign = verticalAlign === "middle" ? "center" : verticalAlign === "center" ? "center" : verticalAlign;
21580
+ if (normalizedVerticalAlign === "top" || normalizedVerticalAlign === "center" || normalizedVerticalAlign === "bottom") {
21581
+ cellAttrs.verticalAlign = normalizedVerticalAlign;
21154
21582
  }
21155
21583
  const background = cellNode.attrs?.background;
21156
21584
  if (background && typeof background.color === "string") {
@@ -21193,15 +21621,89 @@ const parseTableRow = (args) => {
21193
21621
  });
21194
21622
  if (cells.length === 0) return null;
21195
21623
  const rowProps = rowNode.attrs?.tableRowProperties;
21624
+ const rowHeight = normalizeRowHeight(rowProps);
21196
21625
  const attrs = rowProps && typeof rowProps === "object" ? {
21197
- tableRowProperties: rowProps
21198
- } : void 0;
21626
+ tableRowProperties: rowProps,
21627
+ ...rowHeight ? { rowHeight } : {}
21628
+ } : rowHeight ? { rowHeight } : void 0;
21199
21629
  return {
21200
21630
  id: context.nextBlockId(`row-${rowIndex}`),
21201
21631
  cells,
21202
21632
  attrs
21203
21633
  };
21204
21634
  };
21635
+ function extractFloatingTableAnchorWrap(node) {
21636
+ const tableProperties = node.attrs?.tableProperties;
21637
+ const floatingProps = tableProperties?.floatingTableProperties;
21638
+ if (!floatingProps) {
21639
+ return {};
21640
+ }
21641
+ const hasPositioning = floatingProps.tblpX !== void 0 || floatingProps.tblpY !== void 0 || floatingProps.tblpXSpec !== void 0 || floatingProps.tblpYSpec !== void 0 || floatingProps.horzAnchor !== void 0 || floatingProps.vertAnchor !== void 0;
21642
+ if (!hasPositioning) {
21643
+ return {};
21644
+ }
21645
+ const mapHorzAnchor = (val) => {
21646
+ switch (val) {
21647
+ case "page":
21648
+ return "page";
21649
+ case "margin":
21650
+ return "margin";
21651
+ case "text":
21652
+ default:
21653
+ return "column";
21654
+ }
21655
+ };
21656
+ const mapVertAnchor = (val) => {
21657
+ switch (val) {
21658
+ case "page":
21659
+ return "page";
21660
+ case "margin":
21661
+ return "margin";
21662
+ case "text":
21663
+ default:
21664
+ return "paragraph";
21665
+ }
21666
+ };
21667
+ const anchor = {
21668
+ isAnchored: true,
21669
+ hRelativeFrom: mapHorzAnchor(floatingProps.horzAnchor),
21670
+ vRelativeFrom: mapVertAnchor(floatingProps.vertAnchor)
21671
+ };
21672
+ if (floatingProps.tblpXSpec) {
21673
+ anchor.alignH = floatingProps.tblpXSpec;
21674
+ }
21675
+ if (floatingProps.tblpYSpec) {
21676
+ anchor.alignV = floatingProps.tblpYSpec;
21677
+ }
21678
+ if (floatingProps.tblpX !== void 0) {
21679
+ anchor.offsetH = twipsToPx$1(floatingProps.tblpX);
21680
+ }
21681
+ if (floatingProps.tblpY !== void 0) {
21682
+ anchor.offsetV = twipsToPx$1(floatingProps.tblpY);
21683
+ }
21684
+ const hasDistances = floatingProps.leftFromText !== void 0 || floatingProps.rightFromText !== void 0 || floatingProps.topFromText !== void 0 || floatingProps.bottomFromText !== void 0;
21685
+ const wrap = {
21686
+ type: "Square",
21687
+ // Floating tables with text distances use square wrapping
21688
+ wrapText: "bothSides"
21689
+ // Default to text on both sides
21690
+ };
21691
+ if (hasDistances) {
21692
+ if (floatingProps.topFromText !== void 0) {
21693
+ wrap.distTop = twipsToPx$1(floatingProps.topFromText);
21694
+ }
21695
+ if (floatingProps.bottomFromText !== void 0) {
21696
+ wrap.distBottom = twipsToPx$1(floatingProps.bottomFromText);
21697
+ }
21698
+ if (floatingProps.leftFromText !== void 0) {
21699
+ wrap.distLeft = twipsToPx$1(floatingProps.leftFromText);
21700
+ }
21701
+ if (floatingProps.rightFromText !== void 0) {
21702
+ wrap.distRight = twipsToPx$1(floatingProps.rightFromText);
21703
+ }
21704
+ }
21705
+ return { anchor, wrap };
21706
+ }
21205
21707
  function tableNodeToBlock$1(node, nextBlockId, positions, defaultFont, defaultSize, _styleContext, trackedChanges, bookmarks, hyperlinkConfig, themeColors, paragraphToFlowBlocks2, converterContext) {
21206
21708
  if (!Array.isArray(node.content) || node.content.length === 0) return null;
21207
21709
  if (!paragraphToFlowBlocks2) return null;
@@ -21266,6 +21768,10 @@ function tableNodeToBlock$1(node, nextBlockId, positions, defaultFont, defaultSi
21266
21768
  if (tableLayout) {
21267
21769
  tableAttrs.tableLayout = tableLayout;
21268
21770
  }
21771
+ const tableProperties = node.attrs?.tableProperties;
21772
+ if (tableProperties && typeof tableProperties === "object") {
21773
+ tableAttrs.tableProperties = tableProperties;
21774
+ }
21269
21775
  let columnWidths = void 0;
21270
21776
  const twipsToPixels2 = (twips) => {
21271
21777
  const PIXELS_PER_INCH2 = 96;
@@ -21309,12 +21815,15 @@ function tableNodeToBlock$1(node, nextBlockId, positions, defaultFont, defaultSi
21309
21815
  columnWidths = void 0;
21310
21816
  }
21311
21817
  }
21818
+ const { anchor, wrap } = extractFloatingTableAnchorWrap(node);
21312
21819
  const tableBlock = {
21313
21820
  kind: "table",
21314
21821
  id: nextBlockId("table"),
21315
21822
  rows,
21316
21823
  attrs: Object.keys(tableAttrs).length > 0 ? tableAttrs : void 0,
21317
- columnWidths
21824
+ columnWidths,
21825
+ ...anchor ? { anchor } : {},
21826
+ ...wrap ? { wrap } : {}
21318
21827
  };
21319
21828
  return tableBlock;
21320
21829
  }
@@ -21650,7 +22159,7 @@ function getMeasurementContext() {
21650
22159
  return measurementCtx;
21651
22160
  }
21652
22161
  function getRunFontString(run) {
21653
- if (run.kind === "tab" || run.kind === "lineBreak" || "src" in run) {
22162
+ if (run.kind === "tab" || run.kind === "lineBreak" || run.kind === "break" || "src" in run) {
21654
22163
  return "normal normal 16px Arial";
21655
22164
  }
21656
22165
  const style = run.italic ? "italic" : "normal";
@@ -21677,6 +22186,10 @@ function sliceRunsForLine$1(block, line) {
21677
22186
  result.push(run);
21678
22187
  continue;
21679
22188
  }
22189
+ if (run.kind === "break") {
22190
+ result.push(run);
22191
+ continue;
22192
+ }
21680
22193
  const text = run.text ?? "";
21681
22194
  const isFirstRun = runIndex === line.fromRun;
21682
22195
  const isLastRun = runIndex === line.toRun;
@@ -21710,7 +22223,7 @@ function measureCharacterX(block, line, charOffset) {
21710
22223
  1,
21711
22224
  runs2.reduce((sum, run) => {
21712
22225
  if (isTabRun$1(run)) return sum + TAB_CHAR_LENGTH;
21713
- if ("src" in run || run.kind === "lineBreak") return sum;
22226
+ if ("src" in run || run.kind === "lineBreak" || run.kind === "break") return sum;
21714
22227
  return sum + (run.text ?? "").length;
21715
22228
  }, 0)
21716
22229
  );
@@ -21731,7 +22244,7 @@ function measureCharacterX(block, line, charOffset) {
21731
22244
  currentCharOffset += runLength2;
21732
22245
  continue;
21733
22246
  }
21734
- const text = "src" in run || run.kind === "lineBreak" ? "" : run.text ?? "";
22247
+ const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
21735
22248
  const runLength = text.length;
21736
22249
  if (currentCharOffset + runLength >= charOffset) {
21737
22250
  const offsetInRun = charOffset - currentCharOffset;
@@ -21774,7 +22287,7 @@ function measureCharacterXSegmentBased(block, line, charOffset, ctx2) {
21774
22287
  if (isTabRun$1(run)) {
21775
22288
  return segmentBaseX + (offsetInSegment > 0 ? segment.width ?? 0 : 0);
21776
22289
  }
21777
- if ("src" in run || run.kind === "lineBreak") {
22290
+ if ("src" in run || run.kind === "lineBreak" || run.kind === "break") {
21778
22291
  return segmentBaseX + (offsetInSegment >= segmentChars ? segment.width ?? 0 : 0);
21779
22292
  }
21780
22293
  const text = run.text ?? "";
@@ -21797,7 +22310,7 @@ function findCharacterAtX(block, line, x, pmStart) {
21797
22310
  1,
21798
22311
  runs2.reduce((sum, run) => {
21799
22312
  if (isTabRun$1(run)) return sum + TAB_CHAR_LENGTH;
21800
- if ("src" in run || run.kind === "lineBreak") return sum;
22313
+ if ("src" in run || run.kind === "lineBreak" || run.kind === "break") return sum;
21801
22314
  return sum + (run.text ?? "").length;
21802
22315
  }, 0)
21803
22316
  );
@@ -21832,7 +22345,7 @@ function findCharacterAtX(block, line, x, pmStart) {
21832
22345
  currentCharOffset += TAB_CHAR_LENGTH;
21833
22346
  continue;
21834
22347
  }
21835
- const text = "src" in run || run.kind === "lineBreak" ? "" : run.text ?? "";
22348
+ const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
21836
22349
  const runLength = text.length;
21837
22350
  if (runLength === 0) continue;
21838
22351
  ctx2.font = getRunFontString(run);
@@ -22265,6 +22778,40 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
22265
22778
  };
22266
22779
  zones.push(zone);
22267
22780
  },
22781
+ registerTable(tableBlock, measure, anchorY, columnIndex, pageNumber) {
22782
+ if (!tableBlock.anchor?.isAnchored) {
22783
+ return;
22784
+ }
22785
+ const { wrap, anchor } = tableBlock;
22786
+ const wrapType = wrap?.type ?? "None";
22787
+ if (wrapType === "None") {
22788
+ return;
22789
+ }
22790
+ const tableWidth = measure.totalWidth ?? 0;
22791
+ const tableHeight = measure.totalHeight ?? 0;
22792
+ const x = computeTableAnchorX(anchor, columnIndex, columns, tableWidth, margins, pageWidth);
22793
+ const y = anchorY + (anchor.offsetV ?? 0);
22794
+ const zone = {
22795
+ imageBlockId: tableBlock.id,
22796
+ // Reusing imageBlockId field for table id
22797
+ pageNumber,
22798
+ columnIndex,
22799
+ bounds: {
22800
+ x,
22801
+ y,
22802
+ width: tableWidth,
22803
+ height: tableHeight
22804
+ },
22805
+ distances: {
22806
+ top: wrap?.distTop ?? 0,
22807
+ bottom: wrap?.distBottom ?? 0,
22808
+ left: wrap?.distLeft ?? 0,
22809
+ right: wrap?.distRight ?? 0
22810
+ },
22811
+ wrapMode: computeTableWrapMode(wrap)
22812
+ };
22813
+ zones.push(zone);
22814
+ },
22268
22815
  getExclusionsForLine(lineY, lineHeight, columnIndex, pageNumber) {
22269
22816
  const result = zones.filter((zone) => {
22270
22817
  if (zone.pageNumber !== pageNumber || zone.columnIndex !== columnIndex) {
@@ -22372,6 +22919,49 @@ function computeWrapMode(wrap, _anchor) {
22372
22919
  if (wrapText === "largest") return "largest";
22373
22920
  return "both";
22374
22921
  }
22922
+ function computeTableAnchorX(anchor, columnIndex, columns, tableWidth, margins, pageWidth) {
22923
+ const alignH = anchor.alignH ?? "left";
22924
+ const offsetH = anchor.offsetH ?? 0;
22925
+ const marginLeft = Math.max(0, margins?.left ?? 0);
22926
+ const marginRight = Math.max(0, margins?.right ?? 0);
22927
+ const contentWidth = pageWidth != null ? Math.max(1, pageWidth - (marginLeft + marginRight)) : columns.width;
22928
+ const contentLeft = marginLeft;
22929
+ const columnLeft = contentLeft + columnIndex * (columns.width + columns.gap);
22930
+ const relativeFrom = anchor.hRelativeFrom ?? "column";
22931
+ let baseX;
22932
+ let availableWidth;
22933
+ if (relativeFrom === "page") {
22934
+ if (columns.count === 1) {
22935
+ baseX = contentLeft;
22936
+ availableWidth = contentWidth;
22937
+ } else {
22938
+ baseX = 0;
22939
+ availableWidth = pageWidth != null ? pageWidth : contentWidth;
22940
+ }
22941
+ } else if (relativeFrom === "margin") {
22942
+ baseX = contentLeft;
22943
+ availableWidth = contentWidth;
22944
+ } else {
22945
+ baseX = columnLeft;
22946
+ availableWidth = columns.width;
22947
+ }
22948
+ let effectiveAlignH = alignH;
22949
+ if (alignH === "inside") effectiveAlignH = "left";
22950
+ if (alignH === "outside") effectiveAlignH = "right";
22951
+ const result = effectiveAlignH === "left" ? baseX + offsetH : effectiveAlignH === "right" ? baseX + availableWidth - tableWidth - offsetH : effectiveAlignH === "center" ? baseX + (availableWidth - tableWidth) / 2 + offsetH : baseX;
22952
+ return result;
22953
+ }
22954
+ function computeTableWrapMode(wrap) {
22955
+ if (!wrap) return "none";
22956
+ if (wrap.type === "None") {
22957
+ return "none";
22958
+ }
22959
+ const wrapText = wrap.wrapText ?? "bothSides";
22960
+ if (wrapText === "left") return "right";
22961
+ if (wrapText === "right") return "left";
22962
+ if (wrapText === "largest") return "largest";
22963
+ return "both";
22964
+ }
22375
22965
  function computeNextSectionPropsAtBreak(blocks) {
22376
22966
  const nextSectionPropsAtBreak = /* @__PURE__ */ new Map();
22377
22967
  const docxBreakIndexes = [];
@@ -22790,6 +23380,9 @@ function layoutParagraphBlock(ctx2, anchors) {
22790
23380
  };
22791
23381
  if (measure.marker) {
22792
23382
  fragment.markerWidth = measure.marker.markerWidth;
23383
+ if (measure.marker.markerTextWidth != null) {
23384
+ fragment.markerTextWidth = measure.marker.markerTextWidth;
23385
+ }
22793
23386
  }
22794
23387
  state.page.fragments.push(fragment);
22795
23388
  state.trailingSpacing = 0;
@@ -22891,6 +23484,12 @@ function layoutParagraphBlock(ctx2, anchors) {
22891
23484
  };
22892
23485
  if (measure.marker && fromLine === 0) {
22893
23486
  fragment.markerWidth = measure.marker.markerWidth;
23487
+ if (measure.marker.markerTextWidth != null) {
23488
+ fragment.markerTextWidth = measure.marker.markerTextWidth;
23489
+ }
23490
+ if (measure.kind === "paragraph" && measure.marker?.gutterWidth != null) {
23491
+ fragment.markerGutter = measure.marker.gutterWidth;
23492
+ }
22894
23493
  }
22895
23494
  if (fromLine > 0) fragment.continuesFromPrev = true;
22896
23495
  if (slice2.toLine < lines.length) fragment.continuesOnNext = true;
@@ -23068,6 +23667,206 @@ function generateColumnBoundaries(measure) {
23068
23667
  }
23069
23668
  return boundaries;
23070
23669
  }
23670
+ function countHeaderRows(block) {
23671
+ let count = 0;
23672
+ for (let i = 0; i < block.rows.length; i++) {
23673
+ const row = block.rows[i];
23674
+ const repeatHeader = row.attrs?.tableRowProperties?.repeatHeader;
23675
+ if (repeatHeader === true) {
23676
+ count++;
23677
+ } else {
23678
+ break;
23679
+ }
23680
+ }
23681
+ return count;
23682
+ }
23683
+ function sumRowHeights(rows, fromRow, toRow) {
23684
+ let total = 0;
23685
+ for (let i = fromRow; i < toRow && i < rows.length; i++) {
23686
+ total += rows[i].height;
23687
+ }
23688
+ return total;
23689
+ }
23690
+ function calculateFragmentHeight(fragment, measure, _headerCount) {
23691
+ let height = 0;
23692
+ if (fragment.repeatHeaderCount && fragment.repeatHeaderCount > 0) {
23693
+ height += sumRowHeights(measure.rows, 0, fragment.repeatHeaderCount);
23694
+ }
23695
+ height += sumRowHeights(measure.rows, fragment.fromRow, fragment.toRow);
23696
+ return height;
23697
+ }
23698
+ const MIN_PARTIAL_ROW_HEIGHT = 20;
23699
+ function getCellLines(cell) {
23700
+ if (cell.blocks && cell.blocks.length > 0) {
23701
+ const allLines = [];
23702
+ for (const block of cell.blocks) {
23703
+ if (block.kind === "paragraph") {
23704
+ if (block.kind === "paragraph" && "lines" in block) {
23705
+ const paraBlock = block;
23706
+ if (paraBlock.lines) {
23707
+ allLines.push(...paraBlock.lines);
23708
+ }
23709
+ }
23710
+ }
23711
+ }
23712
+ return allLines;
23713
+ }
23714
+ if (cell.paragraph?.lines) {
23715
+ return cell.paragraph.lines;
23716
+ }
23717
+ return [];
23718
+ }
23719
+ function getCellPadding(cellIdx, blockRow) {
23720
+ const padding = blockRow?.cells?.[cellIdx]?.attrs?.padding ?? {};
23721
+ return {
23722
+ top: padding.top ?? 2,
23723
+ bottom: padding.bottom ?? 2,
23724
+ left: padding.left ?? 4,
23725
+ right: padding.right ?? 4
23726
+ };
23727
+ }
23728
+ function getCellTotalLines(cell) {
23729
+ return getCellLines(cell).length;
23730
+ }
23731
+ function computePartialRow(rowIndex, blockRow, measure, availableHeight, fromLineByCell) {
23732
+ const row = measure.rows[rowIndex];
23733
+ if (!row) {
23734
+ throw new Error(`Invalid rowIndex ${rowIndex}: measure.rows has ${measure.rows.length} rows`);
23735
+ }
23736
+ const cellCount = row.cells.length;
23737
+ const startLines = fromLineByCell || new Array(cellCount).fill(0);
23738
+ const toLineByCell = [];
23739
+ const heightByCell = [];
23740
+ const cellPaddings = row.cells.map((_, idx) => getCellPadding(idx, blockRow));
23741
+ for (let cellIdx = 0; cellIdx < cellCount; cellIdx++) {
23742
+ const cell = row.cells[cellIdx];
23743
+ const startLine = startLines[cellIdx] || 0;
23744
+ const cellPadding = cellPaddings[cellIdx];
23745
+ const availableForLines = Math.max(0, availableHeight - (cellPadding.top + cellPadding.bottom));
23746
+ const lines = getCellLines(cell);
23747
+ let cumulativeHeight = 0;
23748
+ let cutLine = startLine;
23749
+ for (let i = startLine; i < lines.length; i++) {
23750
+ const lineHeight = lines[i].lineHeight || 0;
23751
+ if (cumulativeHeight + lineHeight > availableForLines) {
23752
+ break;
23753
+ }
23754
+ cumulativeHeight += lineHeight;
23755
+ cutLine = i + 1;
23756
+ }
23757
+ toLineByCell.push(cutLine);
23758
+ heightByCell.push(cumulativeHeight);
23759
+ }
23760
+ const positiveHeights = heightByCell.filter((h) => h > 0);
23761
+ const minHeight = positiveHeights.length > 0 ? Math.min(...positiveHeights) : 0;
23762
+ let actualPartialHeight = 0;
23763
+ let maxPaddingTotal = 0;
23764
+ for (let cellIdx = 0; cellIdx < cellCount; cellIdx++) {
23765
+ const cell = row.cells[cellIdx];
23766
+ const startLine = startLines[cellIdx] || 0;
23767
+ const lines = getCellLines(cell);
23768
+ const cellPadding = cellPaddings[cellIdx];
23769
+ const paddingTotal = cellPadding.top + cellPadding.bottom;
23770
+ maxPaddingTotal = Math.max(maxPaddingTotal, paddingTotal);
23771
+ let cumulativeHeight = 0;
23772
+ let cutLine = startLine;
23773
+ for (let i = startLine; i < lines.length; i++) {
23774
+ const lineHeight = lines[i].lineHeight || 0;
23775
+ if (cumulativeHeight + lineHeight > minHeight) {
23776
+ break;
23777
+ }
23778
+ cumulativeHeight += lineHeight;
23779
+ cutLine = i + 1;
23780
+ }
23781
+ toLineByCell[cellIdx] = cutLine;
23782
+ actualPartialHeight = Math.max(actualPartialHeight, cumulativeHeight + paddingTotal);
23783
+ }
23784
+ const madeProgress = toLineByCell.some((cutLine, idx) => cutLine > (startLines[idx] || 0));
23785
+ const isFirstPart = startLines.every((l) => l === 0);
23786
+ const allCellsExhausted = toLineByCell.every((cutLine, idx) => {
23787
+ const totalLines = getCellTotalLines(row.cells[idx]);
23788
+ return cutLine >= totalLines;
23789
+ });
23790
+ const isLastPart = allCellsExhausted || !madeProgress;
23791
+ if (actualPartialHeight === 0 && isFirstPart) {
23792
+ actualPartialHeight = maxPaddingTotal;
23793
+ }
23794
+ return {
23795
+ rowIndex,
23796
+ fromLineByCell: startLines,
23797
+ toLineByCell,
23798
+ isFirstPart,
23799
+ isLastPart,
23800
+ partialHeight: actualPartialHeight
23801
+ };
23802
+ }
23803
+ function findSplitPoint(block, measure, startRow, availableHeight, fullPageHeight, _pendingPartialRow) {
23804
+ let accumulatedHeight = 0;
23805
+ let lastFitRow = startRow;
23806
+ for (let i = startRow; i < block.rows.length; i++) {
23807
+ const row = block.rows[i];
23808
+ const rowHeight = measure.rows[i]?.height || 0;
23809
+ const cantSplit = row.attrs?.tableRowProperties?.cantSplit === true;
23810
+ if (accumulatedHeight + rowHeight <= availableHeight) {
23811
+ accumulatedHeight += rowHeight;
23812
+ lastFitRow = i + 1;
23813
+ } else {
23814
+ const remainingHeight = availableHeight - accumulatedHeight;
23815
+ if (fullPageHeight && rowHeight > fullPageHeight) {
23816
+ const partialRow = computePartialRow(i, block.rows[i], measure, remainingHeight);
23817
+ return { endRow: i + 1, partialRow };
23818
+ }
23819
+ if (cantSplit) {
23820
+ if (lastFitRow === startRow) {
23821
+ return { endRow: startRow, partialRow: null };
23822
+ }
23823
+ return { endRow: lastFitRow, partialRow: null };
23824
+ }
23825
+ if (remainingHeight >= MIN_PARTIAL_ROW_HEIGHT) {
23826
+ const partialRow = computePartialRow(i, block.rows[i], measure, remainingHeight);
23827
+ const hasContent = partialRow.toLineByCell.some(
23828
+ (cutLine, idx) => cutLine > (partialRow.fromLineByCell[idx] || 0)
23829
+ );
23830
+ if (hasContent) {
23831
+ return { endRow: i + 1, partialRow };
23832
+ }
23833
+ }
23834
+ return { endRow: lastFitRow, partialRow: null };
23835
+ }
23836
+ }
23837
+ return { endRow: block.rows.length, partialRow: null };
23838
+ }
23839
+ function generateFragmentMetadata(measure, _fromRow, _toRow, _repeatHeaderCount) {
23840
+ return {
23841
+ columnBoundaries: generateColumnBoundaries(measure),
23842
+ coordinateSystem: "fragment"
23843
+ };
23844
+ }
23845
+ function layoutMonolithicTable(context) {
23846
+ let state = context.ensurePage();
23847
+ if (state.cursorY + context.measure.totalHeight > state.contentBottom && state.page.fragments.length > 0) {
23848
+ state = context.advanceColumn(state);
23849
+ }
23850
+ state = context.ensurePage();
23851
+ const height = Math.min(context.measure.totalHeight, state.contentBottom - state.cursorY);
23852
+ const metadata = {
23853
+ columnBoundaries: generateColumnBoundaries(context.measure),
23854
+ coordinateSystem: "fragment"
23855
+ };
23856
+ const fragment = {
23857
+ kind: "table",
23858
+ blockId: context.block.id,
23859
+ fromRow: 0,
23860
+ toRow: context.block.rows.length,
23861
+ x: context.columnX(state.columnIndex),
23862
+ y: state.cursorY,
23863
+ width: Math.min(context.columnWidth, context.measure.totalWidth || context.columnWidth),
23864
+ height,
23865
+ metadata
23866
+ };
23867
+ state.page.fragments.push(fragment);
23868
+ state.cursorY += height;
23869
+ }
23071
23870
  function layoutTableBlock({
23072
23871
  block,
23073
23872
  measure,
@@ -23076,30 +23875,176 @@ function layoutTableBlock({
23076
23875
  advanceColumn,
23077
23876
  columnX
23078
23877
  }) {
23878
+ if (block.anchor?.isAnchored) {
23879
+ return;
23880
+ }
23881
+ const tableProps = block.attrs?.tableProperties;
23882
+ const floatingProps = tableProps?.floatingTableProperties;
23883
+ if (floatingProps && Object.keys(floatingProps).length > 0) {
23884
+ layoutMonolithicTable({ block, measure, columnWidth, ensurePage, advanceColumn, columnX });
23885
+ return;
23886
+ }
23887
+ const headerCount = countHeaderRows(block);
23888
+ const headerHeight = headerCount > 0 ? sumRowHeights(measure.rows, 0, headerCount) : 0;
23079
23889
  let state = ensurePage();
23080
- if (state.cursorY + measure.totalHeight > state.contentBottom && state.page.fragments.length > 0) {
23081
- state = advanceColumn(state);
23890
+ let currentRow = 0;
23891
+ let isTableContinuation = false;
23892
+ let pendingPartialRow = null;
23893
+ while (currentRow < block.rows.length || pendingPartialRow !== null) {
23894
+ state = ensurePage();
23895
+ const availableHeight = state.contentBottom - state.cursorY;
23896
+ let repeatHeaderCount = 0;
23897
+ if (currentRow === 0 && !pendingPartialRow) {
23898
+ repeatHeaderCount = 0;
23899
+ } else {
23900
+ if (headerCount > 0 && headerHeight <= availableHeight) {
23901
+ repeatHeaderCount = headerCount;
23902
+ } else if (headerCount > 0 && headerHeight > availableHeight) {
23903
+ repeatHeaderCount = 0;
23904
+ }
23905
+ }
23906
+ const availableForBody = repeatHeaderCount > 0 ? availableHeight - headerHeight : availableHeight;
23907
+ const fullPageHeight = state.contentBottom;
23908
+ if (pendingPartialRow !== null) {
23909
+ const rowIndex = pendingPartialRow.rowIndex;
23910
+ const fromLineByCell = pendingPartialRow.toLineByCell;
23911
+ const continuationPartialRow = computePartialRow(
23912
+ rowIndex,
23913
+ block.rows[rowIndex],
23914
+ measure,
23915
+ availableForBody,
23916
+ fromLineByCell
23917
+ );
23918
+ const madeProgress = continuationPartialRow.toLineByCell.some(
23919
+ (toLine, idx) => toLine > (fromLineByCell[idx] || 0)
23920
+ );
23921
+ const hasRemainingLinesAfterContinuation = continuationPartialRow.toLineByCell.some(
23922
+ (toLine, idx) => {
23923
+ const totalLines = getCellTotalLines(measure.rows[rowIndex].cells[idx]);
23924
+ return toLine < totalLines;
23925
+ }
23926
+ );
23927
+ const hadRemainingLinesBefore = fromLineByCell.some((fromLine, idx) => {
23928
+ const totalLines = getCellTotalLines(measure.rows[rowIndex].cells[idx]);
23929
+ return fromLine < totalLines;
23930
+ });
23931
+ const fragmentHeight2 = continuationPartialRow.partialHeight + (repeatHeaderCount > 0 ? headerHeight : 0);
23932
+ if (fragmentHeight2 > 0) {
23933
+ const fragment2 = {
23934
+ kind: "table",
23935
+ blockId: block.id,
23936
+ fromRow: rowIndex,
23937
+ toRow: rowIndex + 1,
23938
+ x: columnX(state.columnIndex),
23939
+ y: state.cursorY,
23940
+ width: Math.min(columnWidth, measure.totalWidth || columnWidth),
23941
+ height: fragmentHeight2,
23942
+ continuesFromPrev: true,
23943
+ continuesOnNext: hasRemainingLinesAfterContinuation || rowIndex + 1 < block.rows.length,
23944
+ repeatHeaderCount,
23945
+ partialRow: continuationPartialRow,
23946
+ metadata: generateFragmentMetadata(measure)
23947
+ };
23948
+ state.page.fragments.push(fragment2);
23949
+ state.cursorY += fragmentHeight2;
23950
+ }
23951
+ const rowComplete = !hasRemainingLinesAfterContinuation;
23952
+ if (rowComplete) {
23953
+ currentRow = rowIndex + 1;
23954
+ pendingPartialRow = null;
23955
+ } else if (!madeProgress && hadRemainingLinesBefore) {
23956
+ state = advanceColumn(state);
23957
+ } else {
23958
+ state = advanceColumn(state);
23959
+ pendingPartialRow = continuationPartialRow;
23960
+ }
23961
+ isTableContinuation = true;
23962
+ continue;
23963
+ }
23964
+ const bodyStartRow = currentRow;
23965
+ const { endRow, partialRow } = findSplitPoint(block, measure, bodyStartRow, availableForBody, fullPageHeight);
23966
+ if (endRow === bodyStartRow && partialRow === null && state.page.fragments.length > 0) {
23967
+ state = advanceColumn(state);
23968
+ continue;
23969
+ }
23970
+ if (endRow === bodyStartRow && partialRow === null) {
23971
+ const forcedPartialRow = computePartialRow(bodyStartRow, block.rows[bodyStartRow], measure, availableForBody);
23972
+ const forcedEndRow = bodyStartRow + 1;
23973
+ const fragmentHeight2 = forcedPartialRow.partialHeight + (repeatHeaderCount > 0 ? headerHeight : 0);
23974
+ const fragment2 = {
23975
+ kind: "table",
23976
+ blockId: block.id,
23977
+ fromRow: bodyStartRow,
23978
+ toRow: forcedEndRow,
23979
+ x: columnX(state.columnIndex),
23980
+ y: state.cursorY,
23981
+ width: Math.min(columnWidth, measure.totalWidth || columnWidth),
23982
+ height: fragmentHeight2,
23983
+ continuesFromPrev: isTableContinuation,
23984
+ continuesOnNext: !forcedPartialRow.isLastPart || forcedEndRow < block.rows.length,
23985
+ repeatHeaderCount,
23986
+ partialRow: forcedPartialRow,
23987
+ metadata: generateFragmentMetadata(measure)
23988
+ };
23989
+ state.page.fragments.push(fragment2);
23990
+ state.cursorY += fragmentHeight2;
23991
+ pendingPartialRow = forcedPartialRow;
23992
+ isTableContinuation = true;
23993
+ continue;
23994
+ }
23995
+ let fragmentHeight;
23996
+ if (partialRow) {
23997
+ const fullRowsHeight = sumRowHeights(measure.rows, bodyStartRow, endRow - 1);
23998
+ fragmentHeight = fullRowsHeight + partialRow.partialHeight + (repeatHeaderCount > 0 ? headerHeight : 0);
23999
+ } else {
24000
+ fragmentHeight = calculateFragmentHeight(
24001
+ { fromRow: bodyStartRow, toRow: endRow, repeatHeaderCount },
24002
+ measure
24003
+ );
24004
+ }
24005
+ const fragment = {
24006
+ kind: "table",
24007
+ blockId: block.id,
24008
+ fromRow: bodyStartRow,
24009
+ toRow: endRow,
24010
+ x: columnX(state.columnIndex),
24011
+ y: state.cursorY,
24012
+ width: Math.min(columnWidth, measure.totalWidth || columnWidth),
24013
+ height: fragmentHeight,
24014
+ continuesFromPrev: isTableContinuation,
24015
+ continuesOnNext: endRow < block.rows.length || (partialRow ? !partialRow.isLastPart : false),
24016
+ repeatHeaderCount,
24017
+ partialRow: partialRow || void 0,
24018
+ metadata: generateFragmentMetadata(measure)
24019
+ };
24020
+ state.page.fragments.push(fragment);
24021
+ state.cursorY += fragmentHeight;
24022
+ if (partialRow && !partialRow.isLastPart) {
24023
+ pendingPartialRow = partialRow;
24024
+ currentRow = partialRow.rowIndex;
24025
+ } else {
24026
+ currentRow = endRow;
24027
+ pendingPartialRow = null;
24028
+ }
24029
+ isTableContinuation = true;
23082
24030
  }
23083
- state = ensurePage();
23084
- const height = Math.min(measure.totalHeight, state.contentBottom - state.cursorY);
24031
+ }
24032
+ function createAnchoredTableFragment(block, measure, x, y) {
23085
24033
  const metadata = {
23086
24034
  columnBoundaries: generateColumnBoundaries(measure),
23087
24035
  coordinateSystem: "fragment"
23088
- // rowBoundaries omitted - not needed for column resize, reduces DOM overhead
23089
24036
  };
23090
- const fragment = {
24037
+ return {
23091
24038
  kind: "table",
23092
24039
  blockId: block.id,
23093
24040
  fromRow: 0,
23094
24041
  toRow: block.rows.length,
23095
- x: columnX(state.columnIndex),
23096
- y: state.cursorY,
23097
- width: Math.min(columnWidth, measure.totalWidth || columnWidth),
23098
- height,
24042
+ x,
24043
+ y,
24044
+ width: measure.totalWidth ?? 0,
24045
+ height: measure.totalHeight ?? 0,
23099
24046
  metadata
23100
24047
  };
23101
- state.page.fragments.push(fragment);
23102
- state.cursorY += height;
23103
24048
  }
23104
24049
  function isPageRelativeAnchor(block) {
23105
24050
  const vRelativeFrom = block.anchor?.vRelativeFrom;
@@ -23126,9 +24071,6 @@ function collectPreRegisteredAnchors(blocks, measures) {
23126
24071
  function collectAnchoredDrawings(blocks, measures) {
23127
24072
  const map2 = /* @__PURE__ */ new Map();
23128
24073
  const len = Math.min(blocks.length, measures.length);
23129
- for (let i = 0; i < len; i += 1) {
23130
- if (blocks[i].kind === "paragraph") ;
23131
- }
23132
24074
  const nearestPrevParagraph = (fromIndex) => {
23133
24075
  for (let i = fromIndex - 1; i >= 0; i -= 1) {
23134
24076
  if (blocks[i].kind === "paragraph") return i;
@@ -23164,6 +24106,36 @@ function collectAnchoredDrawings(blocks, measures) {
23164
24106
  }
23165
24107
  return map2;
23166
24108
  }
24109
+ function collectAnchoredTables(blocks, measures) {
24110
+ const map2 = /* @__PURE__ */ new Map();
24111
+ const nearestPrevParagraph = (fromIndex) => {
24112
+ for (let i = fromIndex - 1; i >= 0; i -= 1) {
24113
+ if (blocks[i].kind === "paragraph") return i;
24114
+ }
24115
+ return null;
24116
+ };
24117
+ const nearestNextParagraph = (fromIndex) => {
24118
+ for (let i = fromIndex + 1; i < blocks.length; i += 1) {
24119
+ if (blocks[i].kind === "paragraph") return i;
24120
+ }
24121
+ return null;
24122
+ };
24123
+ for (let i = 0; i < blocks.length; i += 1) {
24124
+ const block = blocks[i];
24125
+ const measure = measures[i];
24126
+ if (block.kind !== "table" || measure?.kind !== "table") continue;
24127
+ const tableBlock = block;
24128
+ const tableMeasure = measure;
24129
+ if (!tableBlock.anchor?.isAnchored) continue;
24130
+ let anchorParaIndex = nearestPrevParagraph(i);
24131
+ if (anchorParaIndex == null) anchorParaIndex = nearestNextParagraph(i);
24132
+ if (anchorParaIndex == null) continue;
24133
+ const list = map2.get(anchorParaIndex) ?? [];
24134
+ list.push({ block: tableBlock, measure: tableMeasure });
24135
+ map2.set(anchorParaIndex, list);
24136
+ }
24137
+ return map2;
24138
+ }
23167
24139
  function createPaginator(opts) {
23168
24140
  const states = [];
23169
24141
  const pages = [];
@@ -23749,7 +24721,9 @@ function layoutDocument(blocks, measures, options = {}) {
23749
24721
  cachedColumnsState.state = null;
23750
24722
  };
23751
24723
  const anchoredByParagraph = collectAnchoredDrawings(blocks, measures);
24724
+ const anchoredTablesByParagraph = collectAnchoredTables(blocks, measures);
23752
24725
  const placedAnchoredIds = /* @__PURE__ */ new Set();
24726
+ const placedAnchoredTableIds = /* @__PURE__ */ new Set();
23753
24727
  const preRegisteredAnchors = collectPreRegisteredAnchors(blocks, measures);
23754
24728
  const preRegisteredPositions = /* @__PURE__ */ new Map();
23755
24729
  for (const entry of preRegisteredAnchors) {
@@ -23927,6 +24901,19 @@ function layoutDocument(blocks, measures, options = {}) {
23927
24901
  }
23928
24902
  }
23929
24903
  const anchorsForPara = anchoredByParagraph.get(index2);
24904
+ const tablesForPara = anchoredTablesByParagraph.get(index2);
24905
+ if (tablesForPara) {
24906
+ const state = paginator.ensurePage();
24907
+ for (const { block: tableBlock, measure: tableMeasure } of tablesForPara) {
24908
+ if (placedAnchoredTableIds.has(tableBlock.id)) continue;
24909
+ floatManager.registerTable(tableBlock, tableMeasure, state.cursorY, state.columnIndex, state.page.number);
24910
+ const anchorX = tableBlock.anchor?.offsetH ?? columnX(state.columnIndex);
24911
+ const anchorY = state.cursorY + (tableBlock.anchor?.offsetV ?? 0);
24912
+ const tableFragment = createAnchoredTableFragment(tableBlock, tableMeasure, anchorX, anchorY);
24913
+ state.page.fragments.push(tableFragment);
24914
+ placedAnchoredTableIds.add(tableBlock.id);
24915
+ }
24916
+ }
23930
24917
  layoutParagraphBlock(
23931
24918
  {
23932
24919
  block,
@@ -24198,7 +25185,9 @@ const hashRuns = (block) => {
24198
25185
  const trackedMode = block.attrs && "trackedChangesMode" in block.attrs && block.attrs.trackedChangesMode || "review";
24199
25186
  const trackedEnabled = resolveTrackedChangesEnabled(block.attrs, true);
24200
25187
  const runsHash = block.runs.map((run) => {
24201
- const text = normalizeText("src" in run || run.kind === "lineBreak" ? "" : run.text ?? "");
25188
+ const text = normalizeText(
25189
+ "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? ""
25190
+ );
24202
25191
  const bold = "bold" in run ? run.bold : false;
24203
25192
  const italic = "italic" in run ? run.italic : false;
24204
25193
  const color = "color" in run ? run.color : void 0;
@@ -24212,7 +25201,22 @@ const hashRuns = (block) => {
24212
25201
  }
24213
25202
  return `${text}:${marks}${trackedKey}`;
24214
25203
  }).join("|");
24215
- return `${trackedMode}:${trackedEnabled ? "on" : "off"}|${runsHash}`;
25204
+ let numberingKey = "";
25205
+ if (block.attrs) {
25206
+ const attrs = block.attrs;
25207
+ if (attrs.numberingProperties) {
25208
+ const np = attrs.numberingProperties;
25209
+ let markerTextKey;
25210
+ if (!attrs.wordLayout?.marker) {
25211
+ markerTextKey = "<NULL>";
25212
+ } else {
25213
+ const markerText = attrs.wordLayout.marker.markerText;
25214
+ markerTextKey = markerText === "" ? "<EMPTY>" : markerText ?? "<NULL>";
25215
+ }
25216
+ numberingKey = `|num:${np.numId ?? ""}:${np.ilvl ?? 0}:${markerTextKey}`;
25217
+ }
25218
+ }
25219
+ return `${trackedMode}:${trackedEnabled ? "on" : "off"}|${runsHash}${numberingKey}`;
24216
25220
  };
24217
25221
  const createStats = () => ({
24218
25222
  hits: 0,
@@ -24858,7 +25862,7 @@ function fontString(run) {
24858
25862
  return `${italic}${bold}${size}px ${family}`.trim();
24859
25863
  }
24860
25864
  function runText(run) {
24861
- return "src" in run || run.kind === "lineBreak" ? "" : run.text ?? "";
25865
+ return "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
24862
25866
  }
24863
25867
  function measureRunSliceWidth(run, fromChar, toChar) {
24864
25868
  const context = getCtx();
@@ -25020,7 +26024,7 @@ const paragraphBlocksEqual = (a, b) => {
25020
26024
  for (let i = 0; i < a.runs.length; i += 1) {
25021
26025
  const runA = a.runs[i];
25022
26026
  const runB = b.runs[i];
25023
- if (("src" in runA || runA.kind === "lineBreak" ? "" : runA.text) !== ("src" in runB || runB.kind === "lineBreak" ? "" : runB.text) || ("bold" in runA ? runA.bold : false) !== ("bold" in runB ? runB.bold : false) || ("italic" in runA ? runA.italic : false) !== ("italic" in runB ? runB.italic : false) || ("color" in runA ? runA.color : void 0) !== ("color" in runB ? runB.color : void 0) || getTrackedChangeKey(runA) !== getTrackedChangeKey(runB)) {
26027
+ if (("src" in runA || runA.kind === "lineBreak" || runA.kind === "break" ? "" : runA.text) !== ("src" in runB || runB.kind === "lineBreak" || runB.kind === "break" ? "" : runB.text) || ("bold" in runA ? runA.bold : false) !== ("bold" in runB ? runB.bold : false) || ("italic" in runA ? runA.italic : false) !== ("italic" in runB ? runB.italic : false) || ("color" in runA ? runA.color : void 0) !== ("color" in runB ? runB.color : void 0) || getTrackedChangeKey(runA) !== getTrackedChangeKey(runB)) {
25024
26028
  return false;
25025
26029
  }
25026
26030
  }
@@ -25140,7 +26144,7 @@ function computeHeaderFooterContentHash(blocks) {
25140
26144
  parts.push(block.id);
25141
26145
  if (block.kind === "paragraph") {
25142
26146
  for (const run of block.runs) {
25143
- if (!("src" in run) && run.kind !== "lineBreak") {
26147
+ if (!("src" in run) && run.kind !== "lineBreak" && run.kind !== "break") {
25144
26148
  parts.push(run.text ?? "");
25145
26149
  }
25146
26150
  if ("bold" in run && run.bold) parts.push("b");
@@ -26111,7 +27115,7 @@ function computeLinePmRange$1(block, line) {
26111
27115
  for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
26112
27116
  const run = block.runs[runIndex];
26113
27117
  if (!run) continue;
26114
- const text = "src" in run || run.kind === "lineBreak" ? "" : run.text ?? "";
27118
+ const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
26115
27119
  const runLength = text.length;
26116
27120
  const runPmStart = run.pmStart ?? null;
26117
27121
  const runPmEnd = run.pmEnd ?? (runPmStart != null ? runPmStart + runLength : null);
@@ -28719,7 +29723,20 @@ const resolveTableCellBorders = (tableBorders, rowIndex, colIndex, totalRows, to
28719
29723
  };
28720
29724
  };
28721
29725
  const renderTableCell = (deps) => {
28722
- const { doc: doc2, x, y, rowHeight, cellMeasure, cell, borders, renderLine, context, applySdtDataset } = deps;
29726
+ const {
29727
+ doc: doc2,
29728
+ x,
29729
+ y,
29730
+ rowHeight,
29731
+ cellMeasure,
29732
+ cell,
29733
+ borders,
29734
+ renderLine,
29735
+ context,
29736
+ applySdtDataset,
29737
+ fromLine,
29738
+ toLine
29739
+ } = deps;
28723
29740
  const cellEl = doc2.createElement("div");
28724
29741
  cellEl.style.position = "absolute";
28725
29742
  cellEl.style.left = `${x}px`;
@@ -28727,6 +29744,7 @@ const renderTableCell = (deps) => {
28727
29744
  cellEl.style.width = `${cellMeasure.width}px`;
28728
29745
  cellEl.style.height = `${rowHeight}px`;
28729
29746
  cellEl.style.boxSizing = "border-box";
29747
+ cellEl.style.overflow = "hidden";
28730
29748
  if (borders) {
28731
29749
  applyCellBorders(cellEl, borders);
28732
29750
  }
@@ -28740,36 +29758,87 @@ const renderTableCell = (deps) => {
28740
29758
  }
28741
29759
  let contentElement;
28742
29760
  const attrs = cell?.attrs;
28743
- const padding = attrs?.padding || { top: 2, left: 4, right: 4 };
29761
+ const padding = attrs?.padding || { top: 2, left: 4, right: 4, bottom: 2 };
28744
29762
  const paddingLeft = padding.left ?? 4;
28745
29763
  const paddingTop = padding.top ?? 2;
28746
29764
  const paddingRight = padding.right ?? 4;
29765
+ const paddingBottom = padding.bottom ?? 2;
28747
29766
  const cellBlocks = cell?.blocks ?? (cell?.paragraph ? [cell.paragraph] : []);
28748
- const blockMeasures = cellMeasure.blocks ?? (cellMeasure.paragraph ? [cellMeasure.paragraph] : []);
29767
+ const blockMeasures = cellMeasure?.blocks ?? (cellMeasure?.paragraph ? [cellMeasure.paragraph] : []);
28749
29768
  if (cellBlocks.length > 0 && blockMeasures.length > 0) {
28750
29769
  const content = doc2.createElement("div");
28751
29770
  content.style.position = "absolute";
28752
29771
  content.style.left = `${x + paddingLeft}px`;
28753
29772
  content.style.top = `${y + paddingTop}px`;
28754
- content.style.width = `${Math.max(0, cellMeasure.width - paddingLeft - paddingRight)}px`;
28755
- let blockY = 0;
29773
+ const contentWidth = Math.max(0, cellMeasure.width - paddingLeft - paddingRight);
29774
+ const contentHeight = Math.max(0, rowHeight - paddingTop - paddingBottom);
29775
+ content.style.width = `${contentWidth + 1}px`;
29776
+ content.style.height = `${contentHeight}px`;
29777
+ content.style.display = "flex";
29778
+ content.style.flexDirection = "column";
29779
+ content.style.overflowX = "visible";
29780
+ content.style.overflowY = "hidden";
29781
+ if (cell?.attrs?.verticalAlign === "center") {
29782
+ content.style.justifyContent = "center";
29783
+ } else if (cell?.attrs?.verticalAlign === "bottom") {
29784
+ content.style.justifyContent = "flex-end";
29785
+ } else {
29786
+ content.style.justifyContent = "flex-start";
29787
+ }
29788
+ const blockLineCounts = [];
29789
+ for (let i = 0; i < Math.min(blockMeasures.length, cellBlocks.length); i++) {
29790
+ const bm = blockMeasures[i];
29791
+ if (bm.kind === "paragraph") {
29792
+ blockLineCounts.push(bm.lines?.length || 0);
29793
+ } else {
29794
+ blockLineCounts.push(0);
29795
+ }
29796
+ }
29797
+ const totalLines = blockLineCounts.reduce((a, b) => a + b, 0);
29798
+ const globalFromLine = fromLine ?? 0;
29799
+ const globalToLine = toLine === -1 || toLine === void 0 ? totalLines : toLine;
29800
+ let cumulativeLineCount = 0;
28756
29801
  for (let i = 0; i < Math.min(blockMeasures.length, cellBlocks.length); i++) {
28757
29802
  const blockMeasure = blockMeasures[i];
28758
29803
  const block = cellBlocks[i];
28759
29804
  if (blockMeasure.kind === "paragraph" && block?.kind === "paragraph") {
29805
+ const lines = blockMeasure.lines;
29806
+ const blockLineCount = lines?.length || 0;
29807
+ const blockStartGlobal = cumulativeLineCount;
29808
+ const blockEndGlobal = cumulativeLineCount + blockLineCount;
29809
+ if (blockEndGlobal <= globalFromLine) {
29810
+ cumulativeLineCount += blockLineCount;
29811
+ continue;
29812
+ }
29813
+ if (blockStartGlobal >= globalToLine) {
29814
+ cumulativeLineCount += blockLineCount;
29815
+ continue;
29816
+ }
29817
+ const localStartLine = Math.max(0, globalFromLine - blockStartGlobal);
29818
+ const localEndLine = Math.min(blockLineCount, globalToLine - blockStartGlobal);
28760
29819
  const paraWrapper = doc2.createElement("div");
28761
- paraWrapper.style.position = "absolute";
28762
- paraWrapper.style.top = `${blockY}px`;
29820
+ paraWrapper.style.position = "relative";
28763
29821
  paraWrapper.style.left = "0";
28764
29822
  paraWrapper.style.width = "100%";
28765
29823
  applySdtDataset(paraWrapper, block.attrs?.sdt);
28766
- const lines = blockMeasure.lines;
28767
- lines.forEach((line) => {
29824
+ let renderedHeight = 0;
29825
+ for (let lineIdx = localStartLine; lineIdx < localEndLine && lineIdx < lines.length; lineIdx++) {
29826
+ const line = lines[lineIdx];
28768
29827
  const lineEl = renderLine(block, line, { ...context, section: "body" });
28769
29828
  paraWrapper.appendChild(lineEl);
28770
- });
29829
+ renderedHeight += line.lineHeight;
29830
+ }
29831
+ const renderedEntireBlock = localStartLine === 0 && localEndLine >= blockLineCount;
29832
+ if (renderedEntireBlock && blockMeasure.totalHeight && blockMeasure.totalHeight > renderedHeight) {
29833
+ renderedHeight = blockMeasure.totalHeight;
29834
+ }
28771
29835
  content.appendChild(paraWrapper);
28772
- blockY += blockMeasure.totalHeight;
29836
+ if (renderedHeight > 0) {
29837
+ paraWrapper.style.height = `${renderedHeight}px`;
29838
+ }
29839
+ cumulativeLineCount += blockLineCount;
29840
+ } else {
29841
+ cumulativeLineCount += 0;
28773
29842
  }
28774
29843
  }
28775
29844
  contentElement = content;
@@ -28790,7 +29859,10 @@ const renderTableRow = (deps) => {
28790
29859
  allRowHeights,
28791
29860
  context,
28792
29861
  renderLine,
28793
- applySdtDataset
29862
+ applySdtDataset,
29863
+ continuesFromPrev,
29864
+ continuesOnNext,
29865
+ partialRow
28794
29866
  } = deps;
28795
29867
  const calculateXPosition = (gridColumnStart) => {
28796
29868
  let x = 0;
@@ -28823,25 +29895,57 @@ const renderTableRow = (deps) => {
28823
29895
  const isLastRow = rowIndex === totalRows - 1;
28824
29896
  const isFirstCol = gridColIndex === 0;
28825
29897
  const isLastCol = gridColIndex === totalCols - 1;
29898
+ const treatAsFirstRow = isFirstRow || continuesFromPrev;
29899
+ const treatAsLastRow = isLastRow || continuesOnNext;
28826
29900
  resolvedBorders = {
28827
- // For top: use cell's if defined, otherwise use table's top for first row
28828
- top: cellBordersAttr.top ?? borderValueToSpec(isFirstRow ? tableBorders.top : tableBorders.insideH),
28829
- // For bottom: use cell's if defined, otherwise use table's bottom for last row only
28830
- bottom: cellBordersAttr.bottom ?? borderValueToSpec(isLastRow ? tableBorders.bottom : void 0),
29901
+ // For top: use cell's if defined, otherwise use table's top border for first row OR continuation
29902
+ top: cellBordersAttr.top ?? borderValueToSpec(treatAsFirstRow ? tableBorders.top : tableBorders.insideH),
29903
+ // For bottom: use cell's if defined, otherwise use table's bottom border for last row OR before continuation
29904
+ bottom: cellBordersAttr.bottom ?? borderValueToSpec(treatAsLastRow ? tableBorders.bottom : void 0),
28831
29905
  // For left: use cell's if defined, otherwise use table's left for first col
28832
29906
  left: cellBordersAttr.left ?? borderValueToSpec(isFirstCol ? tableBorders.left : tableBorders.insideV),
28833
29907
  // For right: use cell's if defined, otherwise use table's right for last col only
28834
29908
  right: cellBordersAttr.right ?? borderValueToSpec(isLastCol ? tableBorders.right : void 0)
28835
29909
  };
28836
29910
  } else if (hasExplicitBorders) {
28837
- resolvedBorders = cellBordersAttr;
29911
+ resolvedBorders = {
29912
+ top: cellBordersAttr.top,
29913
+ bottom: cellBordersAttr.bottom,
29914
+ left: cellBordersAttr.left,
29915
+ right: cellBordersAttr.right
29916
+ };
28838
29917
  } else if (tableBorders) {
28839
- resolvedBorders = resolveTableCellBorders(tableBorders, rowIndex, gridColIndex, totalRows, totalCols);
29918
+ const isFirstRow = rowIndex === 0;
29919
+ const isLastRow = rowIndex === totalRows - 1;
29920
+ const treatAsFirstRow = isFirstRow || continuesFromPrev;
29921
+ const treatAsLastRow = isLastRow || continuesOnNext;
29922
+ const baseBorders = resolveTableCellBorders(tableBorders, rowIndex, gridColIndex, totalRows, totalCols);
29923
+ if (baseBorders) {
29924
+ resolvedBorders = {
29925
+ // If this is a continuation (continuesFromPrev), use table's top border
29926
+ top: treatAsFirstRow ? borderValueToSpec(tableBorders.top) : baseBorders.top,
29927
+ // If this continues on next (continuesOnNext), use table's bottom border
29928
+ bottom: treatAsLastRow ? borderValueToSpec(tableBorders.bottom) : baseBorders.bottom,
29929
+ left: baseBorders.left,
29930
+ right: baseBorders.right
29931
+ };
29932
+ } else {
29933
+ resolvedBorders = void 0;
29934
+ }
28840
29935
  } else {
28841
29936
  resolvedBorders = void 0;
28842
29937
  }
28843
29938
  const rowSpan = cellMeasure.rowSpan ?? 1;
28844
- const cellHeight = rowSpan > 1 ? calculateRowspanHeight(rowIndex, rowSpan) : rowMeasure.height;
29939
+ let cellHeight;
29940
+ if (partialRow) {
29941
+ cellHeight = partialRow.partialHeight;
29942
+ } else if (rowSpan > 1) {
29943
+ cellHeight = calculateRowspanHeight(rowIndex, rowSpan);
29944
+ } else {
29945
+ cellHeight = rowMeasure.height;
29946
+ }
29947
+ const fromLine = partialRow?.fromLineByCell?.[cellIndex];
29948
+ const toLine = partialRow?.toLineByCell?.[cellIndex];
28845
29949
  const { cellElement, contentElement } = renderTableCell({
28846
29950
  doc: doc2,
28847
29951
  x,
@@ -28852,7 +29956,9 @@ const renderTableRow = (deps) => {
28852
29956
  borders: resolvedBorders,
28853
29957
  renderLine,
28854
29958
  context,
28855
- applySdtDataset
29959
+ applySdtDataset,
29960
+ fromLine,
29961
+ toLine
28856
29962
  });
28857
29963
  container.appendChild(cellElement);
28858
29964
  if (contentElement) {
@@ -28966,11 +30072,46 @@ const renderTableFragment = (deps) => {
28966
30072
  if (borderCollapse === "separate" && block.attrs?.cellSpacing) {
28967
30073
  container.style.borderSpacing = `${block.attrs.cellSpacing}px`;
28968
30074
  }
28969
- const allRowHeights = measure.rows.map((r2) => r2.height);
30075
+ const allRowHeights = measure.rows.map((r2, idx) => {
30076
+ if (fragment.partialRow && fragment.partialRow.rowIndex === idx) {
30077
+ return fragment.partialRow.partialHeight;
30078
+ }
30079
+ return r2?.height ?? 0;
30080
+ });
28970
30081
  let y = 0;
30082
+ if (fragment.repeatHeaderCount && fragment.repeatHeaderCount > 0) {
30083
+ for (let r2 = 0; r2 < fragment.repeatHeaderCount; r2 += 1) {
30084
+ const rowMeasure = measure.rows[r2];
30085
+ if (!rowMeasure) break;
30086
+ renderTableRow({
30087
+ doc: doc2,
30088
+ container,
30089
+ rowIndex: r2,
30090
+ y,
30091
+ rowMeasure,
30092
+ row: block.rows[r2],
30093
+ totalRows: block.rows.length,
30094
+ tableBorders,
30095
+ columnWidths: measure.columnWidths,
30096
+ allRowHeights,
30097
+ context,
30098
+ renderLine,
30099
+ applySdtDataset,
30100
+ // Headers are always rendered as-is (no border suppression)
30101
+ continuesFromPrev: false,
30102
+ continuesOnNext: false
30103
+ });
30104
+ y += rowMeasure.height;
30105
+ }
30106
+ }
28971
30107
  for (let r2 = fragment.fromRow; r2 < fragment.toRow; r2 += 1) {
28972
30108
  const rowMeasure = measure.rows[r2];
28973
30109
  if (!rowMeasure) break;
30110
+ const isFirstRenderedBodyRow = r2 === fragment.fromRow;
30111
+ const isLastRenderedBodyRow = r2 === fragment.toRow - 1;
30112
+ const isPartialRow = fragment.partialRow && fragment.partialRow.rowIndex === r2;
30113
+ const partialRowData = isPartialRow ? fragment.partialRow : void 0;
30114
+ const actualRowHeight = partialRowData ? partialRowData.partialHeight : rowMeasure.height;
28974
30115
  renderTableRow({
28975
30116
  doc: doc2,
28976
30117
  container,
@@ -28984,9 +30125,15 @@ const renderTableFragment = (deps) => {
28984
30125
  allRowHeights,
28985
30126
  context,
28986
30127
  renderLine,
28987
- applySdtDataset
30128
+ applySdtDataset,
30129
+ // Draw top border if table continues from previous fragment (MS Word behavior)
30130
+ continuesFromPrev: isFirstRenderedBodyRow && fragment.continuesFromPrev === true,
30131
+ // Draw bottom border if table continues on next fragment (MS Word behavior)
30132
+ continuesOnNext: isLastRenderedBodyRow && fragment.continuesOnNext === true,
30133
+ // Pass partial row data for mid-row splits
30134
+ partialRow: partialRowData
28988
30135
  });
28989
- y += rowMeasure.height;
30136
+ y += actualRowHeight;
28990
30137
  }
28991
30138
  return container;
28992
30139
  };
@@ -29081,6 +30228,7 @@ function assertFragmentPmPositions(fragment, context) {
29081
30228
  }
29082
30229
  }
29083
30230
  const LIST_MARKER_GAP$1 = 8;
30231
+ const DEFAULT_TAB_INTERVAL_PX$1 = 48;
29084
30232
  const COMMENT_EXTERNAL_COLOR = "#B1124B";
29085
30233
  const COMMENT_INTERNAL_COLOR = "#078383";
29086
30234
  const COMMENT_INACTIVE_ALPHA = "22";
@@ -29877,33 +31025,41 @@ const _DomPainter = class _DomPainter {
29877
31025
  const firstLineOffset = (paraIndent?.firstLine ?? 0) - (paraIndent?.hanging ?? 0);
29878
31026
  lines.forEach((line, index2) => {
29879
31027
  const lineEl = this.renderLine(block, line, context);
29880
- if (paraIndentLeft) {
31028
+ const isListFirstLine = index2 === 0 && !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker;
31029
+ if (paraIndentLeft && !isListFirstLine) {
29881
31030
  lineEl.style.paddingLeft = `${paraIndentLeft}px`;
29882
31031
  }
29883
31032
  if (paraIndentRight) {
29884
31033
  lineEl.style.paddingRight = `${paraIndentRight}px`;
29885
31034
  }
29886
- if (!fragment.continuesFromPrev && index2 === 0 && firstLineOffset) {
31035
+ if (!fragment.continuesFromPrev && index2 === 0 && firstLineOffset && !isListFirstLine) {
29887
31036
  lineEl.style.textIndent = `${firstLineOffset}px`;
29888
- } else if (firstLineOffset) {
31037
+ } else if (firstLineOffset && !isListFirstLine) {
29889
31038
  lineEl.style.textIndent = "0px";
29890
31039
  }
29891
- if (index2 === 0 && !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker) {
31040
+ if (isListFirstLine && wordLayout?.marker && fragment.markerWidth) {
31041
+ const markerStartPos = paraIndentLeft - (paraIndent?.hanging ?? 0);
31042
+ lineEl.style.paddingLeft = `${markerStartPos}px`;
29892
31043
  const markerContainer = this.doc.createElement("span");
29893
31044
  markerContainer.style.display = "inline-block";
29894
31045
  const markerEl = this.doc.createElement("span");
29895
31046
  markerEl.classList.add("superdoc-paragraph-marker");
29896
31047
  markerEl.textContent = wordLayout.marker.markerText ?? "";
29897
- markerEl.style.width = `${fragment.markerWidth}px`;
29898
- markerEl.style.textAlign = wordLayout.marker.justification ?? "right";
29899
- markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
29900
31048
  markerEl.style.pointerEvents = "none";
29901
- const indentLeft = paraIndentLeft;
29902
- const hanging = paraIndent?.hanging ?? 0;
29903
- const textStartX = indentLeft - hanging;
29904
- const markerLeftX = textStartX - fragment.markerWidth;
29905
- markerEl.style.position = "relative";
29906
- markerEl.style.left = `${markerLeftX}px`;
31049
+ const markerJustification = wordLayout.marker.justification ?? "left";
31050
+ if (markerJustification !== "left") {
31051
+ markerEl.style.width = `${fragment.markerWidth}px`;
31052
+ markerEl.style.textAlign = wordLayout.marker.justification ?? "right";
31053
+ markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
31054
+ }
31055
+ if (markerJustification === "left") {
31056
+ markerContainer.style.position = "relative";
31057
+ } else {
31058
+ const markerLeftX = markerStartPos - fragment.markerWidth;
31059
+ markerContainer.style.position = "absolute";
31060
+ markerContainer.style.left = `${markerLeftX}px`;
31061
+ markerContainer.style.top = "0";
31062
+ }
29907
31063
  markerEl.style.fontFamily = wordLayout.marker.run.fontFamily;
29908
31064
  markerEl.style.fontSize = `${wordLayout.marker.run.fontSize}px`;
29909
31065
  markerEl.style.fontWeight = wordLayout.marker.run.bold ? "bold" : "";
@@ -29920,12 +31076,25 @@ const _DomPainter = class _DomPainter {
29920
31076
  const tabEl = this.doc.createElement("span");
29921
31077
  tabEl.className = "superdoc-tab";
29922
31078
  tabEl.innerHTML = "&nbsp;";
29923
- const gutterWidth = typeof wordLayout.marker.gutterWidthPx === "number" && isFinite(wordLayout.marker.gutterWidthPx) && wordLayout.marker.gutterWidthPx > 0 ? wordLayout.marker.gutterWidthPx : LIST_MARKER_GAP$1;
31079
+ let tabWidth;
31080
+ const markerBoxWidth = fragment.markerWidth;
31081
+ const markerTextWidth = fragment.markerTextWidth != null && isFinite(fragment.markerTextWidth) && fragment.markerTextWidth >= 0 ? fragment.markerTextWidth : markerBoxWidth;
31082
+ if ((wordLayout.marker.justification ?? "left") === "left") {
31083
+ const currentPos = markerStartPos + markerTextWidth;
31084
+ const implicitTabStop = paraIndentLeft;
31085
+ tabWidth = implicitTabStop - currentPos;
31086
+ if (tabWidth < 1) {
31087
+ tabWidth = DEFAULT_TAB_INTERVAL_PX$1 - currentPos % DEFAULT_TAB_INTERVAL_PX$1;
31088
+ if (tabWidth === 0) tabWidth = DEFAULT_TAB_INTERVAL_PX$1;
31089
+ }
31090
+ } else {
31091
+ tabWidth = fragment.markerGutter != null && isFinite(fragment.markerGutter) ? fragment.markerGutter : typeof wordLayout.marker.gutterWidthPx === "number" && isFinite(wordLayout.marker.gutterWidthPx) && wordLayout.marker.gutterWidthPx > 0 ? wordLayout.marker.gutterWidthPx : LIST_MARKER_GAP$1;
31092
+ }
29924
31093
  tabEl.style.display = "inline-block";
29925
- tabEl.style.width = `${gutterWidth}px`;
29926
- markerContainer.appendChild(tabEl);
31094
+ tabEl.style.width = `${tabWidth}px`;
31095
+ lineEl.prepend(tabEl);
29927
31096
  } else if (suffix === "space") {
29928
- markerContainer.appendChild(this.doc.createTextNode(" "));
31097
+ lineEl.prepend(this.doc.createTextNode(" "));
29929
31098
  }
29930
31099
  lineEl.prepend(markerContainer);
29931
31100
  }
@@ -30774,6 +31943,12 @@ const _DomPainter = class _DomPainter {
30774
31943
  isLineBreakRun(run) {
30775
31944
  return run.kind === "lineBreak";
30776
31945
  }
31946
+ /**
31947
+ * Type guard to check if a run is a break run.
31948
+ */
31949
+ isBreakRun(run) {
31950
+ return run.kind === "break";
31951
+ }
30777
31952
  renderRun(run, context, trackedConfig) {
30778
31953
  if (this.isImageRun(run)) {
30779
31954
  return this.renderImageRun(run);
@@ -30781,7 +31956,10 @@ const _DomPainter = class _DomPainter {
30781
31956
  if (this.isLineBreakRun(run)) {
30782
31957
  return null;
30783
31958
  }
30784
- if (!run.text || !this.doc) {
31959
+ if (this.isBreakRun(run)) {
31960
+ return null;
31961
+ }
31962
+ if (!("text" in run) || !run.text || !this.doc) {
30785
31963
  return null;
30786
31964
  }
30787
31965
  const linkData = this.extractLinkData(run);
@@ -30922,6 +32100,12 @@ const _DomPainter = class _DomPainter {
30922
32100
  if (styleId) {
30923
32101
  el.setAttribute("styleid", styleId);
30924
32102
  }
32103
+ const alignment = block.attrs?.alignment;
32104
+ if (alignment === "center" || alignment === "right" || alignment === "justify") {
32105
+ el.style.textAlign = alignment === "justify" ? "justify" : alignment;
32106
+ } else {
32107
+ el.style.textAlign = "left";
32108
+ }
30925
32109
  const lineRange = computeLinePmRange(block, line);
30926
32110
  if (lineRange.pmStart != null) {
30927
32111
  el.dataset.pmStart = String(lineRange.pmStart);
@@ -31039,10 +32223,16 @@ const _DomPainter = class _DomPainter {
31039
32223
  if (this.isLineBreakRun(baseRun)) {
31040
32224
  continue;
31041
32225
  }
32226
+ if (this.isBreakRun(baseRun)) {
32227
+ continue;
32228
+ }
31042
32229
  const runSegments = segmentsByRun.get(runIndex);
31043
32230
  if (!runSegments || runSegments.length === 0) {
31044
32231
  continue;
31045
32232
  }
32233
+ if (!("text" in baseRun)) {
32234
+ continue;
32235
+ }
31046
32236
  const baseText = baseRun.text ?? "";
31047
32237
  const runPmStart = baseRun.pmStart ?? null;
31048
32238
  const fallbackPmEnd = runPmStart != null && baseRun.pmEnd == null ? runPmStart + baseText.length : baseRun.pmEnd ?? null;
@@ -31361,7 +32551,12 @@ const fragmentKey = (fragment) => {
31361
32551
  if (fragment.kind === "drawing") {
31362
32552
  return `drawing:${fragment.blockId}:${fragment.x}:${fragment.y}`;
31363
32553
  }
31364
- return `${fragment.kind}:${fragment.blockId}`;
32554
+ if (fragment.kind === "table") {
32555
+ const partialKey = fragment.partialRow ? `:${fragment.partialRow.fromLineByCell.join(",")}-${fragment.partialRow.toLineByCell.join(",")}` : "";
32556
+ return `table:${fragment.blockId}:${fragment.fromRow}:${fragment.toRow}${partialKey}`;
32557
+ }
32558
+ const _exhaustiveCheck = fragment;
32559
+ return _exhaustiveCheck;
31365
32560
  };
31366
32561
  const fragmentSignature = (fragment, lookup) => {
31367
32562
  const base2 = lookup.get(fragment.blockId)?.version ?? "missing";
@@ -31373,7 +32568,9 @@ const fragmentSignature = (fragment, lookup) => {
31373
32568
  fragment.pmStart ?? "",
31374
32569
  fragment.pmEnd ?? "",
31375
32570
  fragment.continuesFromPrev ? 1 : 0,
31376
- fragment.continuesOnNext ? 1 : 0
32571
+ fragment.continuesOnNext ? 1 : 0,
32572
+ fragment.markerWidth ?? ""
32573
+ // Include markerWidth to trigger re-render when list status changes
31377
32574
  ].join("|");
31378
32575
  }
31379
32576
  if (fragment.kind === "list-item") {
@@ -31403,6 +32600,20 @@ const fragmentSignature = (fragment, lookup) => {
31403
32600
  fragment.zIndex ?? ""
31404
32601
  ].join("|");
31405
32602
  }
32603
+ if (fragment.kind === "table") {
32604
+ const partialSig = fragment.partialRow ? `${fragment.partialRow.fromLineByCell.join(",")}-${fragment.partialRow.toLineByCell.join(",")}-${fragment.partialRow.partialHeight}` : "";
32605
+ return [
32606
+ base2,
32607
+ fragment.fromRow,
32608
+ fragment.toRow,
32609
+ fragment.width,
32610
+ fragment.height,
32611
+ fragment.continuesFromPrev ? 1 : 0,
32612
+ fragment.continuesOnNext ? 1 : 0,
32613
+ fragment.repeatHeaderCount ?? 0,
32614
+ partialSig
32615
+ ].join("|");
32616
+ }
31406
32617
  return base2;
31407
32618
  };
31408
32619
  const deriveBlockVersion = (block) => {
@@ -31548,7 +32759,7 @@ const deriveBlockVersion = (block) => {
31548
32759
  return block.id;
31549
32760
  };
31550
32761
  const applyRunStyles = (element, run, isLink = false) => {
31551
- if (run.kind === "tab" || run.kind === "image" || run.kind === "lineBreak") {
32762
+ if (run.kind === "tab" || run.kind === "image" || run.kind === "lineBreak" || run.kind === "break") {
31552
32763
  return;
31553
32764
  }
31554
32765
  element.style.fontFamily = run.fontFamily;
@@ -31682,6 +32893,17 @@ const sliceRunsForLine = (block, line) => {
31682
32893
  result.push(run);
31683
32894
  continue;
31684
32895
  }
32896
+ if (run.kind === "break") {
32897
+ result.push(run);
32898
+ continue;
32899
+ }
32900
+ if (run.kind === "tab") {
32901
+ result.push(run);
32902
+ continue;
32903
+ }
32904
+ if (!("text" in run)) {
32905
+ continue;
32906
+ }
31685
32907
  const text = run.text ?? "";
31686
32908
  const isFirstRun = runIndex === line.fromRun;
31687
32909
  const isLastRun = runIndex === line.toRun;
@@ -31695,20 +32917,14 @@ const sliceRunsForLine = (block, line) => {
31695
32917
  if (!slice2) continue;
31696
32918
  const pmSliceStart = runPmStart != null ? runPmStart + start2 : void 0;
31697
32919
  const pmSliceEnd = runPmStart != null ? runPmStart + end2 : fallbackPmEnd ?? void 0;
31698
- if (run.kind === "tab") {
31699
- if (slice2.includes(" ")) {
31700
- result.push(run);
31701
- }
31702
- } else {
31703
- const sliced = {
31704
- ...run,
31705
- text: slice2,
31706
- pmStart: pmSliceStart,
31707
- pmEnd: pmSliceEnd,
31708
- comments: run.comments ? [...run.comments] : void 0
31709
- };
31710
- result.push(sliced);
31711
- }
32920
+ const sliced = {
32921
+ ...run,
32922
+ text: slice2,
32923
+ pmStart: pmSliceStart,
32924
+ pmEnd: pmSliceEnd,
32925
+ comments: run.comments ? [...run.comments] : void 0
32926
+ };
32927
+ result.push(sliced);
31712
32928
  } else {
31713
32929
  result.push(run);
31714
32930
  }
@@ -31751,6 +32967,39 @@ const computeLinePmRange = (block, line) => {
31751
32967
  }
31752
32968
  continue;
31753
32969
  }
32970
+ if (run.kind === "break") {
32971
+ const runPmStart2 = run.pmStart ?? null;
32972
+ const runPmEnd = run.pmEnd ?? null;
32973
+ if (runPmStart2 == null || runPmEnd == null) {
32974
+ continue;
32975
+ }
32976
+ if (pmStart == null) {
32977
+ pmStart = runPmStart2;
32978
+ }
32979
+ pmEnd = runPmEnd;
32980
+ if (runIndex === line.toRun) {
32981
+ break;
32982
+ }
32983
+ continue;
32984
+ }
32985
+ if (run.kind === "tab") {
32986
+ const runPmStart2 = run.pmStart ?? null;
32987
+ const runPmEnd = run.pmEnd ?? null;
32988
+ if (runPmStart2 == null || runPmEnd == null) {
32989
+ continue;
32990
+ }
32991
+ if (pmStart == null) {
32992
+ pmStart = runPmStart2;
32993
+ }
32994
+ pmEnd = runPmEnd;
32995
+ if (runIndex === line.toRun) {
32996
+ break;
32997
+ }
32998
+ continue;
32999
+ }
33000
+ if (!("text" in run)) {
33001
+ continue;
33002
+ }
31754
33003
  const text = run.text ?? "";
31755
33004
  const runLength = text.length;
31756
33005
  const runPmStart = run.pmStart ?? null;
@@ -31792,6 +33041,12 @@ const resolveRunText = (run, context) => {
31792
33041
  if (run.kind === "lineBreak") {
31793
33042
  return "";
31794
33043
  }
33044
+ if (run.kind === "break") {
33045
+ return "";
33046
+ }
33047
+ if (!("text" in run)) {
33048
+ return "";
33049
+ }
31795
33050
  if (!runToken) {
31796
33051
  return run.text ?? "";
31797
33052
  }
@@ -31989,6 +33244,7 @@ async function measureBlock(block, constraints) {
31989
33244
  async function measureParagraphBlock(block, maxWidth) {
31990
33245
  const ctx2 = getCanvasContext();
31991
33246
  const wordLayout = block.attrs?.wordLayout;
33247
+ const WIDTH_FUDGE_PX = 0.5;
31992
33248
  const lines = [];
31993
33249
  const indent = block.attrs?.indent;
31994
33250
  const spacing = block.attrs?.spacing;
@@ -32083,8 +33339,67 @@ async function measureParagraphBlock(block, maxWidth) {
32083
33339
  lastAppliedTabAlign = { target, val };
32084
33340
  pendingTabAlignment = null;
32085
33341
  };
32086
- for (let runIndex = 0; runIndex < block.runs.length; runIndex++) {
32087
- const run = block.runs[runIndex];
33342
+ const runsToProcess = [];
33343
+ for (const run of block.runs) {
33344
+ if (run.text && typeof run.text === "string" && run.text.includes("\n")) {
33345
+ const textRun = run;
33346
+ const segments = textRun.text.split("\n");
33347
+ let cursor = textRun.pmStart ?? 0;
33348
+ segments.forEach((seg, idx) => {
33349
+ runsToProcess.push({
33350
+ ...textRun,
33351
+ text: seg,
33352
+ pmStart: cursor,
33353
+ pmEnd: cursor + seg.length
33354
+ });
33355
+ cursor += seg.length;
33356
+ if (idx !== segments.length - 1) {
33357
+ runsToProcess.push({
33358
+ kind: "break",
33359
+ breakType: "line",
33360
+ pmStart: cursor,
33361
+ pmEnd: cursor + 1,
33362
+ sdt: run.sdt
33363
+ });
33364
+ cursor += 1;
33365
+ }
33366
+ });
33367
+ } else {
33368
+ runsToProcess.push(run);
33369
+ }
33370
+ }
33371
+ for (let runIndex = 0; runIndex < runsToProcess.length; runIndex++) {
33372
+ const run = runsToProcess[runIndex];
33373
+ if (run.kind === "break") {
33374
+ if (currentLine) {
33375
+ const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
33376
+ const completedLine = { ...currentLine, ...metrics };
33377
+ addBarTabsToLine(completedLine);
33378
+ lines.push(completedLine);
33379
+ currentLine = null;
33380
+ } else {
33381
+ const textRunWithSize = block.runs.find(
33382
+ (r2) => r2.kind !== "tab" && r2.kind !== "lineBreak" && r2.kind !== "break" && !("src" in r2) && "fontSize" in r2
33383
+ );
33384
+ const fallbackSize = textRunWithSize?.fontSize ?? 12;
33385
+ const metrics = calculateTypographyMetrics(fallbackSize, spacing);
33386
+ const emptyLine = {
33387
+ fromRun: runIndex,
33388
+ fromChar: 0,
33389
+ toRun: runIndex,
33390
+ toChar: 0,
33391
+ width: 0,
33392
+ segments: [],
33393
+ ...metrics
33394
+ };
33395
+ addBarTabsToLine(emptyLine);
33396
+ lines.push(emptyLine);
33397
+ }
33398
+ tabStopCursor = 0;
33399
+ pendingTabAlignment = null;
33400
+ lastAppliedTabAlign = null;
33401
+ continue;
33402
+ }
32088
33403
  if (isLineBreakRun(run)) {
32089
33404
  if (currentLine) {
32090
33405
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
@@ -32235,6 +33550,9 @@ async function measureParagraphBlock(block, maxWidth) {
32235
33550
  }
32236
33551
  continue;
32237
33552
  }
33553
+ if (!("text" in run) || !("fontSize" in run)) {
33554
+ continue;
33555
+ }
32238
33556
  lastFontSize = run.fontSize;
32239
33557
  const { font } = buildFontString(run);
32240
33558
  const tabSegments = run.text.split(" ");
@@ -32274,18 +33592,18 @@ async function measureParagraphBlock(block, maxWidth) {
32274
33592
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
32275
33593
  };
32276
33594
  const ls = run.letterSpacing ?? 0;
32277
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth) {
33595
+ if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX) {
32278
33596
  currentLine.toChar = wordEndWithSpace;
32279
33597
  currentLine.width = roundValue(currentLine.width + spaceWidth + ls);
32280
33598
  charPosInRun = wordEndWithSpace;
32281
33599
  } else {
32282
- charPosInRun = wordEndNoSpace;
33600
+ charPosInRun = wordEndWithSpace;
32283
33601
  }
32284
33602
  continue;
32285
33603
  }
32286
33604
  const isTocEntry = block.attrs?.isTocEntry;
32287
33605
  const boundarySpacing = currentLine.width > 0 ? run.letterSpacing ?? 0 : 0;
32288
- if (currentLine.width + boundarySpacing + wordOnlyWidth > currentLine.maxWidth && currentLine.width > 0 && !isTocEntry) {
33606
+ if (currentLine.width + boundarySpacing + wordOnlyWidth > currentLine.maxWidth - WIDTH_FUDGE_PX && currentLine.width > 0 && !isTocEntry) {
32289
33607
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
32290
33608
  const completedLine = {
32291
33609
  ...currentLine,
@@ -32305,16 +33623,16 @@ async function measureParagraphBlock(block, maxWidth) {
32305
33623
  maxWidth: getEffectiveWidth(contentWidth),
32306
33624
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
32307
33625
  };
32308
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth) {
33626
+ if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX) {
32309
33627
  currentLine.toChar = wordEndWithSpace;
32310
33628
  currentLine.width = roundValue(currentLine.width + spaceWidth + (run.letterSpacing ?? 0));
32311
33629
  charPosInRun = wordEndWithSpace;
32312
33630
  } else {
32313
- charPosInRun = wordEndNoSpace;
33631
+ charPosInRun = wordEndWithSpace;
32314
33632
  }
32315
33633
  } else {
32316
33634
  currentLine.toRun = runIndex;
32317
- if (!isLastWord && currentLine.width + boundarySpacing + wordOnlyWidth + spaceWidth > currentLine.maxWidth) {
33635
+ if (!isLastWord && currentLine.width + boundarySpacing + wordOnlyWidth + spaceWidth > currentLine.maxWidth - WIDTH_FUDGE_PX) {
32318
33636
  currentLine.toChar = wordEndNoSpace;
32319
33637
  currentLine.width = roundValue(currentLine.width + boundarySpacing + wordOnlyWidth);
32320
33638
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run.fontSize);
@@ -32423,10 +33741,14 @@ async function measureParagraphBlock(block, maxWidth) {
32423
33741
  const { font: markerFont } = buildFontString(markerRun);
32424
33742
  const markerText = wordLayout.marker.markerText ?? "";
32425
33743
  const glyphWidth = markerText ? measureText(markerText, markerFont, ctx2) : 0;
33744
+ const gutter = typeof wordLayout.marker.gutterWidthPx === "number" && isFinite(wordLayout.marker.gutterWidthPx) && wordLayout.marker.gutterWidthPx >= 0 ? wordLayout.marker.gutterWidthPx : LIST_MARKER_GAP;
33745
+ const markerBoxWidth = Math.max(wordLayout.marker.markerBoxWidthPx ?? 0, glyphWidth + LIST_MARKER_GAP);
32426
33746
  markerInfo = {
32427
- markerWidth: Math.max(wordLayout.marker.markerBoxWidthPx ?? 0, glyphWidth + LIST_MARKER_GAP),
33747
+ markerWidth: markerBoxWidth,
32428
33748
  markerTextWidth: glyphWidth,
32429
- indentLeft: wordLayout.indentLeftPx ?? 0
33749
+ indentLeft: wordLayout.indentLeftPx ?? 0,
33750
+ // For tab sizing in the renderer: expose gutter for word-layout lists
33751
+ gutterWidth: gutter
32430
33752
  };
32431
33753
  }
32432
33754
  return {
@@ -32440,6 +33762,34 @@ async function measureParagraphBlock(block, maxWidth) {
32440
33762
  async function measureTableBlock(block, constraints) {
32441
33763
  const maxWidth = typeof constraints === "number" ? constraints : constraints.maxWidth;
32442
33764
  let columnWidths;
33765
+ const scaleColumnWidths = (widths, targetWidth) => {
33766
+ const totalWidth2 = widths.reduce((a, b) => a + b, 0);
33767
+ if (totalWidth2 <= targetWidth || widths.length === 0) return widths;
33768
+ const scale = targetWidth / totalWidth2;
33769
+ const scaled = widths.map((w) => Math.max(1, Math.round(w * scale)));
33770
+ const sum = scaled.reduce((a, b) => a + b, 0);
33771
+ if (sum !== targetWidth) {
33772
+ const adjust = (delta) => {
33773
+ let idx = 0;
33774
+ const direction = delta > 0 ? 1 : -1;
33775
+ delta = Math.abs(delta);
33776
+ while (delta > 0 && scaled.length > 0) {
33777
+ const i = idx % scaled.length;
33778
+ if (direction > 0) {
33779
+ scaled[i] += 1;
33780
+ delta -= 1;
33781
+ } else if (scaled[i] > 1) {
33782
+ scaled[i] -= 1;
33783
+ delta -= 1;
33784
+ }
33785
+ idx += 1;
33786
+ if (idx > scaled.length * 2 && delta > 0) break;
33787
+ }
33788
+ };
33789
+ adjust(targetWidth - sum);
33790
+ }
33791
+ return scaled;
33792
+ };
32443
33793
  const maxCellCount = Math.max(1, Math.max(...block.rows.map((r2) => r2.cells.length)));
32444
33794
  if (block.columnWidths && block.columnWidths.length > 0) {
32445
33795
  columnWidths = [...block.columnWidths];
@@ -32448,8 +33798,7 @@ async function measureTableBlock(block, constraints) {
32448
33798
  if (hasExplicitWidth || hasFixedLayout) {
32449
33799
  const totalWidth2 = columnWidths.reduce((a, b) => a + b, 0);
32450
33800
  if (totalWidth2 > maxWidth) {
32451
- const scale = maxWidth / totalWidth2;
32452
- columnWidths = columnWidths.map((w) => Math.max(1, Math.floor(w * scale)));
33801
+ columnWidths = scaleColumnWidths(columnWidths, maxWidth);
32453
33802
  }
32454
33803
  } else {
32455
33804
  if (columnWidths.length < maxCellCount) {
@@ -32463,8 +33812,7 @@ async function measureTableBlock(block, constraints) {
32463
33812
  }
32464
33813
  const totalWidth2 = columnWidths.reduce((a, b) => a + b, 0);
32465
33814
  if (totalWidth2 > maxWidth) {
32466
- const scale = maxWidth / totalWidth2;
32467
- columnWidths = columnWidths.map((w) => Math.max(1, Math.floor(w * scale)));
33815
+ columnWidths = scaleColumnWidths(columnWidths, maxWidth);
32468
33816
  }
32469
33817
  }
32470
33818
  } else {
@@ -32481,6 +33829,8 @@ async function measureTableBlock(block, constraints) {
32481
33829
  };
32482
33830
  const rowspanTracker = new Array(gridColumnCount).fill(0);
32483
33831
  const rows = [];
33832
+ const rowBaseHeights = new Array(block.rows.length).fill(0);
33833
+ const spanConstraints = [];
32484
33834
  for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex++) {
32485
33835
  const row = block.rows[rowIndex];
32486
33836
  const cellMeasures = [];
@@ -32527,6 +33877,11 @@ async function measureTableBlock(block, constraints) {
32527
33877
  colSpan: colspan,
32528
33878
  rowSpan: rowspan
32529
33879
  });
33880
+ if (rowspan === 1) {
33881
+ rowBaseHeights[rowIndex] = Math.max(rowBaseHeights[rowIndex], totalCellHeight);
33882
+ } else {
33883
+ spanConstraints.push({ startRow: rowIndex, rowSpan: rowspan, requiredHeight: totalCellHeight });
33884
+ }
32530
33885
  gridColIndex += colspan;
32531
33886
  }
32532
33887
  for (let col = gridColIndex; col < gridColumnCount; col++) {
@@ -32534,10 +33889,39 @@ async function measureTableBlock(block, constraints) {
32534
33889
  rowspanTracker[col]--;
32535
33890
  }
32536
33891
  }
32537
- const rowHeight = Math.max(0, ...cellMeasures.map((c) => c.height));
32538
- rows.push({ cells: cellMeasures, height: rowHeight });
33892
+ rows.push({ cells: cellMeasures, height: 0 });
33893
+ }
33894
+ const rowHeights = [...rowBaseHeights];
33895
+ for (const constraint of spanConstraints) {
33896
+ const { startRow, rowSpan, requiredHeight } = constraint;
33897
+ if (rowSpan <= 0) continue;
33898
+ let currentHeight = 0;
33899
+ for (let i = 0; i < rowSpan && startRow + i < rowHeights.length; i++) {
33900
+ currentHeight += rowHeights[startRow + i];
33901
+ }
33902
+ if (currentHeight < requiredHeight) {
33903
+ const spanLength = Math.min(rowSpan, rowHeights.length - startRow);
33904
+ const increment = spanLength > 0 ? (requiredHeight - currentHeight) / spanLength : 0;
33905
+ for (let i = 0; i < spanLength; i++) {
33906
+ rowHeights[startRow + i] += increment;
33907
+ }
33908
+ }
33909
+ }
33910
+ block.rows.forEach((row, index2) => {
33911
+ const spec = row.attrs?.rowHeight;
33912
+ if (spec?.value != null && Number.isFinite(spec.value)) {
33913
+ const rule = spec.rule ?? "atLeast";
33914
+ if (rule === "exact") {
33915
+ rowHeights[index2] = spec.value;
33916
+ } else {
33917
+ rowHeights[index2] = Math.max(rowHeights[index2], spec.value);
33918
+ }
33919
+ }
33920
+ });
33921
+ for (let i = 0; i < rows.length; i++) {
33922
+ rows[i].height = Math.max(0, rowHeights[i]);
32539
33923
  }
32540
- const totalHeight = rows.reduce((sum, r2) => sum + r2.height, 0);
33924
+ const totalHeight = rowHeights.reduce((sum, h) => sum + h, 0);
32541
33925
  const totalWidth = columnWidths.reduce((a, b) => a + b, 0);
32542
33926
  return {
32543
33927
  kind: "table",
@@ -32743,7 +34127,7 @@ const resolveLineHeight = (spacing, baseLineHeight) => {
32743
34127
  if (spacing.lineRule === "atLeast") {
32744
34128
  return Math.max(baseLineHeight, raw);
32745
34129
  }
32746
- return raw;
34130
+ return Math.max(baseLineHeight, raw);
32747
34131
  };
32748
34132
  const sanitizePositive = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : 0;
32749
34133
  const sanitizeDecimalSeparator = (value) => {
@@ -38978,6 +40362,17 @@ const structuredContentHelpers = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ O
38978
40362
  parseTagObject
38979
40363
  }, Symbol.toStringTag, { value: "Module" }));
38980
40364
  const STRUCTURED_CONTENT_NAMES = ["structuredContent", "structuredContentBlock"];
40365
+ const findFirstTextNode = (node) => {
40366
+ let firstTextNode = null;
40367
+ node.descendants((child) => {
40368
+ if (child.isText) {
40369
+ firstTextNode = child;
40370
+ return false;
40371
+ }
40372
+ return true;
40373
+ });
40374
+ return firstTextNode;
40375
+ };
38981
40376
  const StructuredContentCommands = Extension.create({
38982
40377
  name: "structuredContentCommands",
38983
40378
  addCommands() {
@@ -39118,7 +40513,7 @@ const StructuredContentCommands = Extension.create({
39118
40513
  * @param {string} id - Unique identifier of the field
39119
40514
  * @param {StructuredContentUpdate} options
39120
40515
  * @example
39121
- * editor.commands.updateStructuredContentById('123', { text: 'Jane Doe' });
40516
+ * editor.commands.updateStructuredContentById('123', { text: 'Jane Doe', keepTextNodeStyles: true });
39122
40517
  * editor.commands.updateStructuredContentById('123', {
39123
40518
  * json: { type: 'text', text: 'Jane Doe' },
39124
40519
  * });
@@ -39139,7 +40534,9 @@ const StructuredContentCommands = Extension.create({
39139
40534
  const posTo = pos + node.nodeSize;
39140
40535
  let content = null;
39141
40536
  if (options.text) {
39142
- content = schema.text(options.text);
40537
+ const firstTextNode = options.keepTextNodeStyles === true ? findFirstTextNode(node) : null;
40538
+ const textMarks = firstTextNode ? firstTextNode.marks : [];
40539
+ content = schema.text(options.text, textMarks);
39143
40540
  }
39144
40541
  if (options.html) {
39145
40542
  const html = htmlHandler(options.html, editor);
@@ -39153,6 +40550,13 @@ const StructuredContentCommands = Extension.create({
39153
40550
  content = node.content;
39154
40551
  }
39155
40552
  const updatedNode = node.type.create({ ...node.attrs, ...options.attrs }, content, node.marks);
40553
+ try {
40554
+ const nodeForValidation = editor.validateJSON(updatedNode.toJSON());
40555
+ nodeForValidation.check();
40556
+ } catch (error) {
40557
+ console.error("Invalid content.", "Passed value:", content, "Error:", error);
40558
+ return false;
40559
+ }
39156
40560
  tr.replaceWith(posFrom, posTo, updatedNode);
39157
40561
  }
39158
40562
  return true;
@@ -39237,7 +40641,7 @@ const StructuredContentCommands = Extension.create({
39237
40641
  * @param {StructuredContentUpdate} options
39238
40642
  * @example
39239
40643
  * // Update all fields in the customer-info group
39240
- * editor.commands.updateStructuredContentByGroup('customer-info', { text: 'Jane Doe' });
40644
+ * editor.commands.updateStructuredContentByGroup('customer-info', { text: 'Jane Doe', keepTextNodeStyles: true });
39241
40645
  *
39242
40646
  * // Update block content in a group
39243
40647
  * editor.commands.updateStructuredContentByGroup('terms-section', {
@@ -39251,13 +40655,14 @@ const StructuredContentCommands = Extension.create({
39251
40655
  }
39252
40656
  const { schema } = editor;
39253
40657
  if (dispatch) {
39254
- structuredContentTags.forEach((structuredContent) => {
40658
+ const updates = [];
40659
+ for (const structuredContent of structuredContentTags) {
39255
40660
  const { pos, node } = structuredContent;
39256
- const posFrom = tr.mapping.map(pos);
39257
- const posTo = tr.mapping.map(pos + node.nodeSize);
39258
40661
  let content = null;
39259
40662
  if (options.text) {
39260
- content = schema.text(options.text);
40663
+ const firstTextNode = options.keepTextNodeStyles === true ? findFirstTextNode(node) : null;
40664
+ const textMarks = firstTextNode ? firstTextNode.marks : [];
40665
+ content = schema.text(options.text, textMarks);
39261
40666
  }
39262
40667
  if (options.html) {
39263
40668
  const html = htmlHandler(options.html, editor);
@@ -39271,11 +40676,23 @@ const StructuredContentCommands = Extension.create({
39271
40676
  content = node.content;
39272
40677
  }
39273
40678
  const updatedNode = node.type.create({ ...node.attrs, ...options.attrs }, content, node.marks);
40679
+ try {
40680
+ const nodeForValidation = editor.validateJSON(updatedNode.toJSON());
40681
+ nodeForValidation.check();
40682
+ } catch (error) {
40683
+ console.error("Invalid content.", "Passed value:", content, "Error:", error);
40684
+ return false;
40685
+ }
40686
+ updates.push({ pos, node, updatedNode });
40687
+ }
40688
+ for (const { pos, node, updatedNode } of updates) {
40689
+ const posFrom = tr.mapping.map(pos);
40690
+ const posTo = tr.mapping.map(pos + node.nodeSize);
39274
40691
  const currentNode = tr.doc.nodeAt(posFrom);
39275
40692
  if (currentNode && node.eq(currentNode)) {
39276
40693
  tr.replaceWith(posFrom, posTo, updatedNode);
39277
40694
  }
39278
- });
40695
+ }
39279
40696
  }
39280
40697
  return true;
39281
40698
  },
@@ -39851,61 +41268,153 @@ const Text = Node$1.create({
39851
41268
  return {};
39852
41269
  }
39853
41270
  });
39854
- const splitRun = () => (props) => {
39855
- const { state, view, tr } = props;
39856
- const { $from, empty: empty2 } = state.selection;
39857
- if (!empty2) return false;
39858
- if ($from.parent.type.name !== "run") return false;
39859
- const handled = splitBlockPatch(state, (transaction) => {
39860
- view.dispatch(transaction);
39861
- });
39862
- if (handled) {
39863
- tr.setMeta("preventDispatch", true);
39864
- }
39865
- return handled;
39866
- };
39867
- function splitBlockPatch(state, dispatch) {
39868
- let { $from } = state.selection;
39869
- if (state.selection instanceof NodeSelection && state.selection.node.isBlock) {
39870
- if (!$from.parentOffset || !canSplit(state.doc, $from.pos)) return false;
39871
- if (dispatch) dispatch(state.tr.split($from.pos).scrollIntoView());
39872
- return true;
41271
+ const cleanupEmptyRunsPlugin = new Plugin({
41272
+ appendTransaction(trs, oldState, newState) {
41273
+ if (!trs.some((tr2) => tr2.docChanged)) return null;
41274
+ const { run, paragraph } = newState.schema.nodes;
41275
+ if (!run) return null;
41276
+ const ranges = [];
41277
+ trs.forEach((tr2) => {
41278
+ tr2.mapping.maps.forEach((map2) => {
41279
+ map2.forEach((oldStart, oldEnd, newStart, newEnd) => {
41280
+ if (newStart !== oldStart || oldEnd !== newEnd) ranges.push({ from: newStart, to: newEnd });
41281
+ });
41282
+ });
41283
+ });
41284
+ if (!ranges.length) return null;
41285
+ ranges.sort((a, b) => a.from - b.from);
41286
+ const merged = [];
41287
+ for (const r2 of ranges) {
41288
+ const from2 = Math.max(0, r2.from - 1);
41289
+ const to = Math.min(newState.doc.content.size, r2.to + 1);
41290
+ const last = merged[merged.length - 1];
41291
+ if (last && from2 <= last.to) last.to = Math.max(last.to, to);
41292
+ else merged.push({ from: from2, to });
41293
+ }
41294
+ const toDelete = [];
41295
+ merged.forEach(({ from: from2, to }) => {
41296
+ newState.doc.nodesBetween(from2, to, (node, pos, parent) => {
41297
+ if (node.type === run && node.content.size === 0 && parent?.type === paragraph) {
41298
+ toDelete.push({ from: pos, to: pos + node.nodeSize });
41299
+ }
41300
+ });
41301
+ });
41302
+ if (!toDelete.length) return null;
41303
+ const tr = newState.tr;
41304
+ toDelete.sort((a, b) => b.from - a.from).forEach(({ from: from2, to }) => tr.deleteRange(from2, to));
41305
+ return tr.docChanged ? tr : null;
39873
41306
  }
39874
- if (!$from.depth) return false;
39875
- let types = [];
39876
- let splitDepth, deflt, atEnd = false, atStart = false;
39877
- for (let d2 = $from.depth; ; d2--) {
39878
- let node = $from.node(d2);
39879
- if (node.isBlock) {
39880
- atEnd = $from.end(d2) == $from.pos + ($from.depth - d2);
39881
- atStart = $from.start(d2) == $from.pos - ($from.depth - d2);
39882
- deflt = defaultBlockAt$1($from.node(d2 - 1).contentMatchAt($from.indexAfter(d2 - 1)));
39883
- types.unshift(null);
39884
- splitDepth = d2;
39885
- break;
41307
+ });
41308
+ const mergeRanges$1 = (ranges, docSize) => {
41309
+ if (!ranges.length) return [];
41310
+ const sorted = ranges.map(({ from: from2, to }) => ({
41311
+ from: Math.max(0, from2),
41312
+ to: Math.min(docSize, to)
41313
+ })).filter(({ from: from2, to }) => from2 < to).sort((a, b) => a.from - b.from);
41314
+ const merged = [];
41315
+ for (const range of sorted) {
41316
+ const last = merged[merged.length - 1];
41317
+ if (last && range.from <= last.to) {
41318
+ last.to = Math.max(last.to, range.to);
39886
41319
  } else {
39887
- if (d2 == 1) return false;
39888
- types.unshift(null);
41320
+ merged.push({ ...range });
39889
41321
  }
39890
41322
  }
39891
- let tr = state.tr;
39892
- if (state.selection instanceof TextSelection || state.selection instanceof AllSelection) tr.deleteSelection();
39893
- let splitPos = tr.mapping.map($from.pos);
39894
- let can = canSplit(tr.doc, splitPos, types.length, types);
39895
- if (!can) {
39896
- types[0] = deflt ? { type: deflt } : null;
39897
- can = canSplit(tr.doc, splitPos, types.length, types);
39898
- }
39899
- if (!can) return false;
39900
- tr.split(splitPos, types.length, types);
39901
- if (!atEnd && atStart && $from.node(splitDepth).type != deflt) {
39902
- let first2 = tr.mapping.map($from.before(splitDepth)), $first = tr.doc.resolve(first2);
39903
- if (deflt && $from.node(splitDepth - 1).canReplaceWith($first.index(), $first.index() + 1, deflt))
39904
- tr.setNodeMarkup(tr.mapping.map($from.before(splitDepth)), deflt);
39905
- }
39906
- if (dispatch) dispatch(tr.scrollIntoView());
39907
- return true;
39908
- }
41323
+ return merged;
41324
+ };
41325
+ const collectChangedRanges = (trs, docSize) => {
41326
+ const ranges = [];
41327
+ trs.forEach((tr) => {
41328
+ if (!tr.docChanged) return;
41329
+ tr.mapping.maps.forEach((map2) => {
41330
+ map2.forEach((oldStart, oldEnd, newStart, newEnd) => {
41331
+ if (newStart !== oldStart || oldEnd !== newEnd) {
41332
+ ranges.push({ from: newStart, to: newEnd });
41333
+ }
41334
+ });
41335
+ });
41336
+ });
41337
+ return mergeRanges$1(ranges, docSize);
41338
+ };
41339
+ const mapRangesThroughTransactions = (ranges, transactions, docSize) => {
41340
+ let mapped = ranges;
41341
+ transactions.forEach((tr) => {
41342
+ mapped = mapped.map(({ from: from2, to }) => {
41343
+ const mappedFrom = tr.mapping.map(from2, -1);
41344
+ const mappedTo = tr.mapping.map(to, 1);
41345
+ if (mappedFrom >= mappedTo) return null;
41346
+ return { from: mappedFrom, to: mappedTo };
41347
+ }).filter(Boolean);
41348
+ });
41349
+ return mergeRanges$1(mapped, docSize);
41350
+ };
41351
+ const buildWrapTransaction = (state, ranges, runType) => {
41352
+ if (!ranges.length) return null;
41353
+ const replacements = [];
41354
+ ranges.forEach(({ from: from2, to }) => {
41355
+ state.doc.nodesBetween(from2, to, (node, pos, parent, index2) => {
41356
+ if (!node.isText || !parent || parent.type === runType) return;
41357
+ const match = parent.contentMatchAt ? parent.contentMatchAt(index2) : null;
41358
+ if (match && !match.matchType(runType)) return;
41359
+ if (!match && !parent.type.contentMatch.matchType(runType)) return;
41360
+ const runProperties = decodeRPrFromMarks(node.marks);
41361
+ const runNode = runType.create({ runProperties }, node);
41362
+ replacements.push({ from: pos, to: pos + node.nodeSize, runNode });
41363
+ });
41364
+ });
41365
+ if (!replacements.length) return null;
41366
+ const tr = state.tr;
41367
+ replacements.sort((a, b) => b.from - a.from).forEach(({ from: from2, to, runNode }) => tr.replaceWith(from2, to, runNode));
41368
+ return tr.docChanged ? tr : null;
41369
+ };
41370
+ const wrapTextInRunsPlugin = () => {
41371
+ let view = null;
41372
+ let pendingRanges = [];
41373
+ const flush = () => {
41374
+ if (!view) return;
41375
+ const runType = view.state.schema.nodes.run;
41376
+ if (!runType) {
41377
+ pendingRanges = [];
41378
+ return;
41379
+ }
41380
+ const tr = buildWrapTransaction(view.state, pendingRanges, runType);
41381
+ pendingRanges = [];
41382
+ if (tr) {
41383
+ view.dispatch(tr);
41384
+ }
41385
+ };
41386
+ const onCompositionEnd = () => {
41387
+ if (typeof globalThis === "undefined") return;
41388
+ globalThis.queueMicrotask(flush);
41389
+ };
41390
+ return new Plugin({
41391
+ view(editorView) {
41392
+ view = editorView;
41393
+ editorView.dom.addEventListener("compositionend", onCompositionEnd);
41394
+ return {
41395
+ destroy() {
41396
+ editorView.dom.removeEventListener("compositionend", onCompositionEnd);
41397
+ view = null;
41398
+ pendingRanges = [];
41399
+ }
41400
+ };
41401
+ },
41402
+ appendTransaction(transactions, _oldState, newState) {
41403
+ const docSize = newState.doc.content.size;
41404
+ const runType = newState.schema.nodes.run;
41405
+ if (!runType) return null;
41406
+ pendingRanges = mapRangesThroughTransactions(pendingRanges, transactions, docSize);
41407
+ const changedRanges = collectChangedRanges(transactions, docSize);
41408
+ pendingRanges = mergeRanges$1([...pendingRanges, ...changedRanges], docSize);
41409
+ if (view?.composing) {
41410
+ return null;
41411
+ }
41412
+ const tr = buildWrapTransaction(newState, pendingRanges, runType);
41413
+ pendingRanges = [];
41414
+ return tr;
41415
+ }
41416
+ });
41417
+ };
39909
41418
  const Run = OxmlNode.create({
39910
41419
  name: "run",
39911
41420
  oXmlName: "w:r",
@@ -39948,7 +41457,8 @@ const Run = OxmlNode.create({
39948
41457
  // @ts-expect-error - Command signatures will be fixed in TS migration
39949
41458
  addCommands() {
39950
41459
  return {
39951
- splitRun
41460
+ splitRunToParagraph,
41461
+ splitRunAtCursor
39952
41462
  };
39953
41463
  },
39954
41464
  parseDOM() {
@@ -39957,6 +41467,9 @@ const Run = OxmlNode.create({
39957
41467
  renderDOM({ htmlAttributes }) {
39958
41468
  const base2 = Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes);
39959
41469
  return ["span", base2, 0];
41470
+ },
41471
+ addPmPlugins() {
41472
+ return [wrapTextInRunsPlugin(), cleanupEmptyRunsPlugin];
39960
41473
  }
39961
41474
  });
39962
41475
  const restartNumbering = ({ editor, tr, state, dispatch }) => {
@@ -40768,20 +42281,15 @@ function createNumberingPlugin(editor) {
40768
42281
  } else {
40769
42282
  markerText = docxNumberingHelpers.normalizeLvlTextChar(lvlText);
40770
42283
  }
40771
- if (JSON.stringify(node.attrs.listRendering) !== JSON.stringify({
42284
+ const newListRendering = {
40772
42285
  markerText,
40773
42286
  suffix,
40774
42287
  justification,
40775
42288
  path,
40776
42289
  numberingType: listNumberingType
40777
- })) {
40778
- tr.setNodeAttribute(pos, "listRendering", {
40779
- markerText,
40780
- suffix,
40781
- justification,
40782
- path,
40783
- numberingType: listNumberingType
40784
- });
42290
+ };
42291
+ if (JSON.stringify(node.attrs.listRendering) !== JSON.stringify(newListRendering)) {
42292
+ tr.setNodeAttribute(pos, "listRendering", newListRendering);
40785
42293
  }
40786
42294
  return false;
40787
42295
  });
@@ -41082,7 +42590,7 @@ const Paragraph = OxmlNode.create({
41082
42590
  return null;
41083
42591
  }
41084
42592
  const { tr } = state;
41085
- tr.delete(range.from, range.to);
42593
+ tr.delete(range.from, range.to).setSelection(TextSelection.create(tr.doc, range.from));
41086
42594
  ListHelpers.createNewList({
41087
42595
  listType: type,
41088
42596
  tr,
@@ -44512,7 +46020,10 @@ const Table = Node$1.create({
44512
46020
  insertTable: ({ rows = 3, cols = 3, withHeaderRow = false } = {}) => ({ tr, dispatch, editor }) => {
44513
46021
  const node = createTable(editor.schema, rows, cols, withHeaderRow);
44514
46022
  if (dispatch) {
44515
- const offset2 = tr.selection.from + 1;
46023
+ let offset2 = tr.selection.$from.end() + 1;
46024
+ if (tr.selection.$from.parent?.type?.name === "run") {
46025
+ offset2 = tr.selection.$from.after(tr.selection.$from.depth - 1);
46026
+ }
44516
46027
  tr.replaceSelectionWith(node).scrollIntoView().setSelection(TextSelection.near(tr.doc.resolve(offset2)));
44517
46028
  }
44518
46029
  return true;