superdoc 1.0.0-beta.16 → 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-93eWvs8z.cjs → PdfViewer-BIlJaTm7.cjs} +1 -1
  2. package/dist/chunks/{PdfViewer-ODeuH1gb.es.js → PdfViewer-cvzMUtBh.es.js} +1 -1
  3. package/dist/chunks/{index-DW5_UKLM.es.js → index-CrIfBvBN.es.js} +3 -3
  4. package/dist/chunks/{index-RquHXtgI.cjs → index-DDx90Dl3.cjs} +3 -3
  5. package/dist/chunks/{index-DexFffM7-XZD_g6eY.cjs → index-VCeRjVPO-DjkejB6t.cjs} +1 -1
  6. package/dist/chunks/{index-DexFffM7-Cbdy0Zy6.es.js → index-VCeRjVPO-FBgR9qxX.es.js} +1 -1
  7. package/dist/chunks/{super-editor.es-Dg5uoFkw.es.js → super-editor.es-00SpI-wK.es.js} +690 -146
  8. package/dist/chunks/{super-editor.es-BLKWkx5G.cjs → super-editor.es-Mlj7AGyt.cjs} +690 -146
  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-C_R_BK8X.js → converter-B9zUZjYT.js} +71 -34
  12. package/dist/super-editor/chunks/{docx-zipper-BvQAYmi1.js → docx-zipper-r5KdE_SA.js} +1 -1
  13. package/dist/super-editor/chunks/{editor-DFFvalb1.js → editor-D2k2BwSG.js} +524 -105
  14. package/dist/super-editor/chunks/{index-DexFffM7.js → index-VCeRjVPO.js} +1 -1
  15. package/dist/super-editor/chunks/{toolbar-DLPfegtw.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 +692 -148
  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-C_R_BK8X.js";
16
- import { D as DocxZipper } from "./docx-zipper-BvQAYmi1.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.16";
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-DexFffM7.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.16");
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");
@@ -23140,6 +23380,9 @@ function layoutParagraphBlock(ctx2, anchors) {
23140
23380
  };
23141
23381
  if (measure.marker) {
23142
23382
  fragment.markerWidth = measure.marker.markerWidth;
23383
+ if (measure.marker.markerTextWidth != null) {
23384
+ fragment.markerTextWidth = measure.marker.markerTextWidth;
23385
+ }
23143
23386
  }
23144
23387
  state.page.fragments.push(fragment);
23145
23388
  state.trailingSpacing = 0;
@@ -23241,6 +23484,12 @@ function layoutParagraphBlock(ctx2, anchors) {
23241
23484
  };
23242
23485
  if (measure.marker && fromLine === 0) {
23243
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
+ }
23244
23493
  }
23245
23494
  if (fromLine > 0) fragment.continuesFromPrev = true;
23246
23495
  if (slice2.toLine < lines.length) fragment.continuesOnNext = true;
@@ -24952,7 +25201,22 @@ const hashRuns = (block) => {
24952
25201
  }
24953
25202
  return `${text}:${marks}${trackedKey}`;
24954
25203
  }).join("|");
24955
- 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}`;
24956
25220
  };
24957
25221
  const createStats = () => ({
24958
25222
  hits: 0,
@@ -29964,6 +30228,7 @@ function assertFragmentPmPositions(fragment, context) {
29964
30228
  }
29965
30229
  }
29966
30230
  const LIST_MARKER_GAP$1 = 8;
30231
+ const DEFAULT_TAB_INTERVAL_PX$1 = 48;
29967
30232
  const COMMENT_EXTERNAL_COLOR = "#B1124B";
29968
30233
  const COMMENT_INTERNAL_COLOR = "#078383";
29969
30234
  const COMMENT_INACTIVE_ALPHA = "22";
@@ -30760,33 +31025,41 @@ const _DomPainter = class _DomPainter {
30760
31025
  const firstLineOffset = (paraIndent?.firstLine ?? 0) - (paraIndent?.hanging ?? 0);
30761
31026
  lines.forEach((line, index2) => {
30762
31027
  const lineEl = this.renderLine(block, line, context);
30763
- if (paraIndentLeft) {
31028
+ const isListFirstLine = index2 === 0 && !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker;
31029
+ if (paraIndentLeft && !isListFirstLine) {
30764
31030
  lineEl.style.paddingLeft = `${paraIndentLeft}px`;
30765
31031
  }
30766
31032
  if (paraIndentRight) {
30767
31033
  lineEl.style.paddingRight = `${paraIndentRight}px`;
30768
31034
  }
30769
- if (!fragment.continuesFromPrev && index2 === 0 && firstLineOffset) {
31035
+ if (!fragment.continuesFromPrev && index2 === 0 && firstLineOffset && !isListFirstLine) {
30770
31036
  lineEl.style.textIndent = `${firstLineOffset}px`;
30771
- } else if (firstLineOffset) {
31037
+ } else if (firstLineOffset && !isListFirstLine) {
30772
31038
  lineEl.style.textIndent = "0px";
30773
31039
  }
30774
- 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`;
30775
31043
  const markerContainer = this.doc.createElement("span");
30776
31044
  markerContainer.style.display = "inline-block";
30777
31045
  const markerEl = this.doc.createElement("span");
30778
31046
  markerEl.classList.add("superdoc-paragraph-marker");
30779
31047
  markerEl.textContent = wordLayout.marker.markerText ?? "";
30780
- markerEl.style.width = `${fragment.markerWidth}px`;
30781
- markerEl.style.textAlign = wordLayout.marker.justification ?? "right";
30782
- markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
30783
31048
  markerEl.style.pointerEvents = "none";
30784
- const indentLeft = paraIndentLeft;
30785
- const hanging = paraIndent?.hanging ?? 0;
30786
- const textStartX = indentLeft - hanging;
30787
- const markerLeftX = textStartX - fragment.markerWidth;
30788
- markerEl.style.position = "relative";
30789
- 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
+ }
30790
31063
  markerEl.style.fontFamily = wordLayout.marker.run.fontFamily;
30791
31064
  markerEl.style.fontSize = `${wordLayout.marker.run.fontSize}px`;
30792
31065
  markerEl.style.fontWeight = wordLayout.marker.run.bold ? "bold" : "";
@@ -30803,12 +31076,25 @@ const _DomPainter = class _DomPainter {
30803
31076
  const tabEl = this.doc.createElement("span");
30804
31077
  tabEl.className = "superdoc-tab";
30805
31078
  tabEl.innerHTML = "&nbsp;";
30806
- 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
+ }
30807
31093
  tabEl.style.display = "inline-block";
30808
- tabEl.style.width = `${gutterWidth}px`;
30809
- markerContainer.appendChild(tabEl);
31094
+ tabEl.style.width = `${tabWidth}px`;
31095
+ lineEl.prepend(tabEl);
30810
31096
  } else if (suffix === "space") {
30811
- markerContainer.appendChild(this.doc.createTextNode(" "));
31097
+ lineEl.prepend(this.doc.createTextNode(" "));
30812
31098
  }
30813
31099
  lineEl.prepend(markerContainer);
30814
31100
  }
@@ -32282,7 +32568,9 @@ const fragmentSignature = (fragment, lookup) => {
32282
32568
  fragment.pmStart ?? "",
32283
32569
  fragment.pmEnd ?? "",
32284
32570
  fragment.continuesFromPrev ? 1 : 0,
32285
- fragment.continuesOnNext ? 1 : 0
32571
+ fragment.continuesOnNext ? 1 : 0,
32572
+ fragment.markerWidth ?? ""
32573
+ // Include markerWidth to trigger re-render when list status changes
32286
32574
  ].join("|");
32287
32575
  }
32288
32576
  if (fragment.kind === "list-item") {
@@ -33453,10 +33741,14 @@ async function measureParagraphBlock(block, maxWidth) {
33453
33741
  const { font: markerFont } = buildFontString(markerRun);
33454
33742
  const markerText = wordLayout.marker.markerText ?? "";
33455
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);
33456
33746
  markerInfo = {
33457
- markerWidth: Math.max(wordLayout.marker.markerBoxWidthPx ?? 0, glyphWidth + LIST_MARKER_GAP),
33747
+ markerWidth: markerBoxWidth,
33458
33748
  markerTextWidth: glyphWidth,
33459
- 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
33460
33752
  };
33461
33753
  }
33462
33754
  return {
@@ -40070,6 +40362,17 @@ const structuredContentHelpers = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ O
40070
40362
  parseTagObject
40071
40363
  }, Symbol.toStringTag, { value: "Module" }));
40072
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
+ };
40073
40376
  const StructuredContentCommands = Extension.create({
40074
40377
  name: "structuredContentCommands",
40075
40378
  addCommands() {
@@ -40210,7 +40513,7 @@ const StructuredContentCommands = Extension.create({
40210
40513
  * @param {string} id - Unique identifier of the field
40211
40514
  * @param {StructuredContentUpdate} options
40212
40515
  * @example
40213
- * editor.commands.updateStructuredContentById('123', { text: 'Jane Doe' });
40516
+ * editor.commands.updateStructuredContentById('123', { text: 'Jane Doe', keepTextNodeStyles: true });
40214
40517
  * editor.commands.updateStructuredContentById('123', {
40215
40518
  * json: { type: 'text', text: 'Jane Doe' },
40216
40519
  * });
@@ -40231,7 +40534,9 @@ const StructuredContentCommands = Extension.create({
40231
40534
  const posTo = pos + node.nodeSize;
40232
40535
  let content = null;
40233
40536
  if (options.text) {
40234
- 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);
40235
40540
  }
40236
40541
  if (options.html) {
40237
40542
  const html = htmlHandler(options.html, editor);
@@ -40245,6 +40550,13 @@ const StructuredContentCommands = Extension.create({
40245
40550
  content = node.content;
40246
40551
  }
40247
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
+ }
40248
40560
  tr.replaceWith(posFrom, posTo, updatedNode);
40249
40561
  }
40250
40562
  return true;
@@ -40329,7 +40641,7 @@ const StructuredContentCommands = Extension.create({
40329
40641
  * @param {StructuredContentUpdate} options
40330
40642
  * @example
40331
40643
  * // Update all fields in the customer-info group
40332
- * editor.commands.updateStructuredContentByGroup('customer-info', { text: 'Jane Doe' });
40644
+ * editor.commands.updateStructuredContentByGroup('customer-info', { text: 'Jane Doe', keepTextNodeStyles: true });
40333
40645
  *
40334
40646
  * // Update block content in a group
40335
40647
  * editor.commands.updateStructuredContentByGroup('terms-section', {
@@ -40343,13 +40655,14 @@ const StructuredContentCommands = Extension.create({
40343
40655
  }
40344
40656
  const { schema } = editor;
40345
40657
  if (dispatch) {
40346
- structuredContentTags.forEach((structuredContent) => {
40658
+ const updates = [];
40659
+ for (const structuredContent of structuredContentTags) {
40347
40660
  const { pos, node } = structuredContent;
40348
- const posFrom = tr.mapping.map(pos);
40349
- const posTo = tr.mapping.map(pos + node.nodeSize);
40350
40661
  let content = null;
40351
40662
  if (options.text) {
40352
- 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);
40353
40666
  }
40354
40667
  if (options.html) {
40355
40668
  const html = htmlHandler(options.html, editor);
@@ -40363,11 +40676,23 @@ const StructuredContentCommands = Extension.create({
40363
40676
  content = node.content;
40364
40677
  }
40365
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);
40366
40691
  const currentNode = tr.doc.nodeAt(posFrom);
40367
40692
  if (currentNode && node.eq(currentNode)) {
40368
40693
  tr.replaceWith(posFrom, posTo, updatedNode);
40369
40694
  }
40370
- });
40695
+ }
40371
40696
  }
40372
40697
  return true;
40373
40698
  },
@@ -40943,61 +41268,153 @@ const Text = Node$1.create({
40943
41268
  return {};
40944
41269
  }
40945
41270
  });
40946
- const splitRun = () => (props) => {
40947
- const { state, view, tr } = props;
40948
- const { $from, empty: empty2 } = state.selection;
40949
- if (!empty2) return false;
40950
- if ($from.parent.type.name !== "run") return false;
40951
- const handled = splitBlockPatch(state, (transaction) => {
40952
- view.dispatch(transaction);
40953
- });
40954
- if (handled) {
40955
- tr.setMeta("preventDispatch", true);
40956
- }
40957
- return handled;
40958
- };
40959
- function splitBlockPatch(state, dispatch) {
40960
- let { $from } = state.selection;
40961
- if (state.selection instanceof NodeSelection && state.selection.node.isBlock) {
40962
- if (!$from.parentOffset || !canSplit(state.doc, $from.pos)) return false;
40963
- if (dispatch) dispatch(state.tr.split($from.pos).scrollIntoView());
40964
- 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;
40965
41306
  }
40966
- if (!$from.depth) return false;
40967
- let types = [];
40968
- let splitDepth, deflt, atEnd = false, atStart = false;
40969
- for (let d2 = $from.depth; ; d2--) {
40970
- let node = $from.node(d2);
40971
- if (node.isBlock) {
40972
- atEnd = $from.end(d2) == $from.pos + ($from.depth - d2);
40973
- atStart = $from.start(d2) == $from.pos - ($from.depth - d2);
40974
- deflt = defaultBlockAt$1($from.node(d2 - 1).contentMatchAt($from.indexAfter(d2 - 1)));
40975
- types.unshift(null);
40976
- splitDepth = d2;
40977
- 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);
40978
41319
  } else {
40979
- if (d2 == 1) return false;
40980
- types.unshift(null);
41320
+ merged.push({ ...range });
40981
41321
  }
40982
41322
  }
40983
- let tr = state.tr;
40984
- if (state.selection instanceof TextSelection || state.selection instanceof AllSelection) tr.deleteSelection();
40985
- let splitPos = tr.mapping.map($from.pos);
40986
- let can = canSplit(tr.doc, splitPos, types.length, types);
40987
- if (!can) {
40988
- types[0] = deflt ? { type: deflt } : null;
40989
- can = canSplit(tr.doc, splitPos, types.length, types);
40990
- }
40991
- if (!can) return false;
40992
- tr.split(splitPos, types.length, types);
40993
- if (!atEnd && atStart && $from.node(splitDepth).type != deflt) {
40994
- let first2 = tr.mapping.map($from.before(splitDepth)), $first = tr.doc.resolve(first2);
40995
- if (deflt && $from.node(splitDepth - 1).canReplaceWith($first.index(), $first.index() + 1, deflt))
40996
- tr.setNodeMarkup(tr.mapping.map($from.before(splitDepth)), deflt);
40997
- }
40998
- if (dispatch) dispatch(tr.scrollIntoView());
40999
- return true;
41000
- }
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
+ };
41001
41418
  const Run = OxmlNode.create({
41002
41419
  name: "run",
41003
41420
  oXmlName: "w:r",
@@ -41040,7 +41457,8 @@ const Run = OxmlNode.create({
41040
41457
  // @ts-expect-error - Command signatures will be fixed in TS migration
41041
41458
  addCommands() {
41042
41459
  return {
41043
- splitRun
41460
+ splitRunToParagraph,
41461
+ splitRunAtCursor
41044
41462
  };
41045
41463
  },
41046
41464
  parseDOM() {
@@ -41049,6 +41467,9 @@ const Run = OxmlNode.create({
41049
41467
  renderDOM({ htmlAttributes }) {
41050
41468
  const base2 = Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes);
41051
41469
  return ["span", base2, 0];
41470
+ },
41471
+ addPmPlugins() {
41472
+ return [wrapTextInRunsPlugin(), cleanupEmptyRunsPlugin];
41052
41473
  }
41053
41474
  });
41054
41475
  const restartNumbering = ({ editor, tr, state, dispatch }) => {
@@ -41860,20 +42281,15 @@ function createNumberingPlugin(editor) {
41860
42281
  } else {
41861
42282
  markerText = docxNumberingHelpers.normalizeLvlTextChar(lvlText);
41862
42283
  }
41863
- if (JSON.stringify(node.attrs.listRendering) !== JSON.stringify({
42284
+ const newListRendering = {
41864
42285
  markerText,
41865
42286
  suffix,
41866
42287
  justification,
41867
42288
  path,
41868
42289
  numberingType: listNumberingType
41869
- })) {
41870
- tr.setNodeAttribute(pos, "listRendering", {
41871
- markerText,
41872
- suffix,
41873
- justification,
41874
- path,
41875
- numberingType: listNumberingType
41876
- });
42290
+ };
42291
+ if (JSON.stringify(node.attrs.listRendering) !== JSON.stringify(newListRendering)) {
42292
+ tr.setNodeAttribute(pos, "listRendering", newListRendering);
41877
42293
  }
41878
42294
  return false;
41879
42295
  });
@@ -42174,7 +42590,7 @@ const Paragraph = OxmlNode.create({
42174
42590
  return null;
42175
42591
  }
42176
42592
  const { tr } = state;
42177
- tr.delete(range.from, range.to);
42593
+ tr.delete(range.from, range.to).setSelection(TextSelection.create(tr.doc, range.from));
42178
42594
  ListHelpers.createNewList({
42179
42595
  listType: type,
42180
42596
  tr,
@@ -45604,7 +46020,10 @@ const Table = Node$1.create({
45604
46020
  insertTable: ({ rows = 3, cols = 3, withHeaderRow = false } = {}) => ({ tr, dispatch, editor }) => {
45605
46021
  const node = createTable(editor.schema, rows, cols, withHeaderRow);
45606
46022
  if (dispatch) {
45607
- 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
+ }
45608
46027
  tr.replaceSelectionWith(node).scrollIntoView().setSelection(TextSelection.near(tr.doc.resolve(offset2)));
45609
46028
  }
45610
46029
  return true;