@portabletext/editor 8.1.1 → 8.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +3 -3
  2. package/lib/{behavior.types.action-C0XDEQnB.d.ts → behavior.types.action-DbwK30_J.d.ts} +52 -25
  3. package/lib/behavior.types.action-DbwK30_J.d.ts.map +1 -0
  4. package/lib/behaviors/index.d.ts +1 -1
  5. package/lib/{get-container-D2pN5Npr.js → get-container-CXdmRdiX.js} +3 -3
  6. package/lib/{get-container-D2pN5Npr.js.map → get-container-CXdmRdiX.js.map} +1 -1
  7. package/lib/{get-parent-DgaKcy8-.js → get-parent-BLzi7eLr.js} +39 -14
  8. package/lib/get-parent-BLzi7eLr.js.map +1 -0
  9. package/lib/{get-path-sub-schema-Dd0QYZ0m.js → get-path-sub-schema-DsN1qF_l.js} +9 -5
  10. package/lib/get-path-sub-schema-DsN1qF_l.js.map +1 -0
  11. package/lib/index.d.ts +1 -1
  12. package/lib/index.js +421 -396
  13. package/lib/index.js.map +1 -1
  14. package/lib/plugins/index.d.ts +1 -1
  15. package/lib/{selector.is-selecting-entire-blocks-BFhnnkHf.js → selector.is-selecting-entire-blocks-BHVYIXbI.js} +8 -5
  16. package/lib/selector.is-selecting-entire-blocks-BHVYIXbI.js.map +1 -0
  17. package/lib/selectors/index.d.ts +1 -1
  18. package/lib/selectors/index.js +4 -4
  19. package/lib/traversal/index.d.ts +9 -6
  20. package/lib/traversal/index.d.ts.map +1 -1
  21. package/lib/traversal/index.js +3 -3
  22. package/lib/{util.is-equal-selections-BdK98okY.js → util.is-equal-selections-sCQib0IC.js} +2 -2
  23. package/lib/{util.is-equal-selections-BdK98okY.js.map → util.is-equal-selections-sCQib0IC.js.map} +1 -1
  24. package/lib/{util.slice-blocks-_ElaB53f.js → util.slice-blocks-B-iKFEG7.js} +43 -56
  25. package/lib/util.slice-blocks-B-iKFEG7.js.map +1 -0
  26. package/lib/utils/index.d.ts +1 -1
  27. package/lib/utils/index.js +4 -8
  28. package/lib/utils/index.js.map +1 -1
  29. package/package.json +2 -3
  30. package/lib/behavior.types.action-C0XDEQnB.d.ts.map +0 -1
  31. package/lib/get-parent-DgaKcy8-.js.map +0 -1
  32. package/lib/get-path-sub-schema-Dd0QYZ0m.js.map +0 -1
  33. package/lib/selector.is-selecting-entire-blocks-BFhnnkHf.js.map +0 -1
  34. package/lib/util.slice-blocks-_ElaB53f.js.map +0 -1
package/lib/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import { a as getChildren, d as isKeyedSegment, i as resolveNode, n as parentPath, o as getNodeChildren, r as getNode, t as getParent, u as serializePath } from "./get-parent-DgaKcy8-.js";
2
- import { C as getAncestors, S as hasNode, _ as comparePoints, a as isInline, b as isEditableContainer, c as isSpanNode, d as resolveChildEntryIndex, f as isAncestorPath, g as isAfterPoint, h as isBackwardRange, i as getEnclosingBlock, l as getSibling, m as rangeEdges, n as getEnclosingContainer, o as getBlock, p as isTextBlockNode, s as isBlock, t as getPathSubSchema, u as getNodes, v as comparePaths, x as resolveContainerAt, y as isObject } from "./get-path-sub-schema-Dd0QYZ0m.js";
3
- import { _ as getAncestor, a as getTextBlock, c as pathContains, d as isRange, f as isPoint, g as isLeafObject, h as getLeaf, i as getFirstChild, l as getSpan, m as isPath, n as getUnionSchema, o as rangeIntersects, p as isObject$1, r as getLastChild, s as isBeforePoint, t as getContainer, u as getText } from "./get-container-D2pN5Npr.js";
4
- import { a as parseBlocks, b as childAtTextOffset, c as parseSpan, d as getSelectionEndPoint, f as isSelectionCollapsed, g as isEqualSelectionPoints, h as getBlockKeyFromSelectionPoint, i as parseBlock, l as defaultKeyGenerator, m as getBlockEndPoint, n as isListBlock, o as parseInlineObject, p as getBlockStartPoint, r as parseAnnotation, s as parseMarkDefs, u as getSelectionStartPoint, v as blockOffsetToSpanSelectionPoint, x as textOffsetOfChild } from "./util.slice-blocks-_ElaB53f.js";
5
- import { A as getSelectionEndPoint$1, B as getFocusBlock, C as getSelectedTextBlocks, D as getPreviousSpan, F as getSelectionEndBlock, G as rangesOverlap, H as getFocusInlineObject, I as getFragment, L as getSelectedValue, M as isSelectionCollapsed$1, N as isOverlappingSelection, O as getSelectionStartPoint$1, P as getSelectionStartBlock, R as getRootAcceptedTypes, S as getActiveDecorators, T as getMarkState, U as getFocusChild, V as getFocusSpan, a as isActiveListItem, b as getActiveAnnotations, c as getSelectionEndChild, d as getLastBlock, f as getFocusListBlock, i as isActiveStyle, j as isSelectionExpanded, k as getNextSpan, l as getPreviousBlock, m as getCaretWordSelection, n as isAtTheStartOfBlock, o as isActiveDecorator, p as getFocusBlockObject, r as isAtTheEndOfBlock, s as getSelectionStartChild, t as isSelectingEntireBlocks, u as getNextBlock, w as getActiveAnnotationsMarks, x as isActiveAnnotation, z as getFocusTextBlock } from "./selector.is-selecting-entire-blocks-BFhnnkHf.js";
6
- import { n as isEmptyTextBlock, r as getTextBlockText, t as isEqualSelections } from "./util.is-equal-selections-BdK98okY.js";
1
+ import { a as getChildren, d as nodeSegment, f as serializePath, i as resolveNode, n as parentPath, o as getNodeChildren, p as isKeyedSegment, r as getNode, t as getParent, u as hasUsableKey } from "./get-parent-BLzi7eLr.js";
2
+ import { C as getAncestors, S as hasNode, _ as comparePoints, a as isInline, b as isEditableContainer, c as isSpanNode, d as resolveChildEntryIndex, f as isAncestorPath, g as isAfterPoint, h as isBackwardRange, i as getEnclosingBlock, l as getSibling, m as rangeEdges, n as getEnclosingContainer, o as getBlock, p as isTextBlockNode, s as isBlock, t as getPathSubSchema, u as getNodes, v as comparePaths, x as resolveContainerAt, y as isObject } from "./get-path-sub-schema-DsN1qF_l.js";
3
+ import { _ as getAncestor, a as getTextBlock, c as pathContains, d as isRange, f as isPoint, g as isLeafObject, h as getLeaf, i as getFirstChild, l as getSpan, m as isPath, n as getUnionSchema, o as rangeIntersects, p as isObject$1, r as getLastChild, s as isBeforePoint, t as getContainer, u as getText } from "./get-container-CXdmRdiX.js";
4
+ import { a as parseMarkDefs, c as getSelectionStartPoint, d as getBlockStartPoint, f as getBlockEndPoint, g as blockOffsetToSpanSelectionPoint, i as parseInlineObject, l as getSelectionEndPoint, m as isEqualSelectionPoints, n as parseAnnotation, o as parseSpan, p as getBlockKeyFromSelectionPoint, r as parseBlock, s as defaultKeyGenerator, u as isSelectionCollapsed, v as childAtTextOffset, y as textOffsetOfChild } from "./util.slice-blocks-B-iKFEG7.js";
5
+ import { A as getSelectionEndPoint$1, B as getFocusTextBlock, C as getSelectedTextBlocks, D as getPreviousSpan, F as getSelectionStartBlock, H as getFocusSpan, I as getSelectionEndBlock, K as rangesOverlap, L as getFragment, M as isSelectionExpanded, N as isSelectionCollapsed$1, O as getSelectionStartPoint$1, P as isOverlappingSelection, R as getSelectedValue, S as getActiveDecorators, T as getMarkState, U as getFocusInlineObject, V as getFocusBlock, W as getFocusChild, a as isActiveListItem, b as getActiveAnnotations, c as getSelectionEndChild, d as getLastBlock, f as getFocusListBlock, i as isActiveStyle, j as isListBlock, k as getNextSpan, l as getPreviousBlock, m as getCaretWordSelection, n as isAtTheStartOfBlock, o as isActiveDecorator, p as getFocusBlockObject, r as isAtTheEndOfBlock, s as getSelectionStartChild, t as isSelectingEntireBlocks, u as getNextBlock, w as getActiveAnnotationsMarks, x as isActiveAnnotation, z as getRootAcceptedTypes } from "./selector.is-selecting-entire-blocks-BHVYIXbI.js";
6
+ import { n as isEmptyTextBlock, r as getTextBlockText, t as isEqualSelections } from "./util.is-equal-selections-sCQib0IC.js";
7
7
  import { a as raise$1, i as forward, n as effect, t as defineBehavior } from "./behavior.types.behavior-BxSLb73I.js";
8
8
  import { n as EditorContext$1, t as useEditor } from "./use-editor-CwNeVwVC.js";
9
9
  import { c } from "react/compiler-runtime";
@@ -465,17 +465,19 @@ const IS_IOS = typeof navigator < "u" && typeof window < "u" && /iPad|iPhone|iPo
465
465
  },
466
466
  toEditorSelection: (editor, domRange, options) => {
467
467
  let { exactMatch, suppressThrow } = options, el = isDOMSelection(domRange) ? domRange.anchorNode : domRange.startContainer, anchorNode = null, anchorOffset = 0, focusNode = null, focusOffset = 0, isCollapsed = !1;
468
- if (el) if (isDOMSelection(domRange)) {
469
- if (IS_FIREFOX && domRange.rangeCount > 1) {
470
- focusNode = domRange.focusNode;
471
- let firstRange = domRange.getRangeAt(0), lastRange = domRange.getRangeAt(domRange.rangeCount - 1);
472
- if (focusNode instanceof HTMLTableRowElement && firstRange.startContainer instanceof HTMLTableRowElement && lastRange.startContainer instanceof HTMLTableRowElement) {
473
- let getLastChildren = (element) => element.childElementCount > 0 ? getLastChildren(element.children[0]) : element, firstNodeRow = firstRange.startContainer, lastNodeRow = lastRange.startContainer, firstNode = getLastChildren(firstNodeRow.children[firstRange.startOffset]), lastNode = getLastChildren(lastNodeRow.children[lastRange.startOffset]);
474
- focusOffset = 0, anchorNode = lastNode.childNodes.length > 0 ? lastNode.childNodes[0] ?? null : lastNode, focusNode = firstNode.childNodes.length > 0 ? firstNode.childNodes[0] ?? null : firstNode, anchorOffset = lastNode instanceof HTMLElement ? lastNode.innerHTML.length : 0;
475
- } else firstRange.startContainer === focusNode ? (anchorNode = lastRange.endContainer, anchorOffset = lastRange.endOffset, focusOffset = firstRange.startOffset) : (anchorNode = firstRange.startContainer, anchorOffset = firstRange.endOffset, focusOffset = lastRange.startOffset);
476
- } else anchorNode = domRange.anchorNode, anchorOffset = domRange.anchorOffset, focusNode = domRange.focusNode, focusOffset = domRange.focusOffset;
477
- isCollapsed = IS_CHROME && hasShadowRoot(anchorNode) || IS_FIREFOX ? domRange.anchorNode === domRange.focusNode && domRange.anchorOffset === domRange.focusOffset : domRange.isCollapsed;
478
- } else anchorNode = domRange.startContainer, anchorOffset = domRange.startOffset, focusNode = domRange.endContainer, focusOffset = domRange.endOffset, isCollapsed = domRange.collapsed;
468
+ if (el) {
469
+ if (isDOMSelection(domRange)) {
470
+ if (IS_FIREFOX && domRange.rangeCount > 1) {
471
+ focusNode = domRange.focusNode;
472
+ let firstRange = domRange.getRangeAt(0), lastRange = domRange.getRangeAt(domRange.rangeCount - 1);
473
+ if (focusNode instanceof HTMLTableRowElement && firstRange.startContainer instanceof HTMLTableRowElement && lastRange.startContainer instanceof HTMLTableRowElement) {
474
+ let getLastChildren = (element) => element.childElementCount > 0 ? getLastChildren(element.children[0]) : element, firstNodeRow = firstRange.startContainer, lastNodeRow = lastRange.startContainer, firstNode = getLastChildren(firstNodeRow.children[firstRange.startOffset]), lastNode = getLastChildren(lastNodeRow.children[lastRange.startOffset]);
475
+ focusOffset = 0, anchorNode = lastNode.childNodes.length > 0 ? lastNode.childNodes[0] ?? null : lastNode, focusNode = firstNode.childNodes.length > 0 ? firstNode.childNodes[0] ?? null : firstNode, anchorOffset = lastNode instanceof HTMLElement ? lastNode.innerHTML.length : 0;
476
+ } else firstRange.startContainer === focusNode ? (anchorNode = lastRange.endContainer, anchorOffset = lastRange.endOffset, focusOffset = firstRange.startOffset) : (anchorNode = firstRange.startContainer, anchorOffset = firstRange.endOffset, focusOffset = lastRange.startOffset);
477
+ } else anchorNode = domRange.anchorNode, anchorOffset = domRange.anchorOffset, focusNode = domRange.focusNode, focusOffset = domRange.focusOffset;
478
+ isCollapsed = IS_CHROME && hasShadowRoot(anchorNode) || IS_FIREFOX ? domRange.anchorNode === domRange.focusNode && domRange.anchorOffset === domRange.focusOffset : domRange.isCollapsed;
479
+ } else anchorNode = domRange.startContainer, anchorOffset = domRange.startOffset, focusNode = domRange.endContainer, focusOffset = domRange.endOffset, isCollapsed = domRange.collapsed;
480
+ }
479
481
  if (anchorNode == null || focusNode == null || anchorOffset == null || focusOffset == null) {
480
482
  if (suppressThrow) return null;
481
483
  throw Error(`Cannot map DOM range to an editor selection: ${domRange}`);
@@ -746,6 +748,36 @@ function move(editor, options = {}) {
746
748
  }
747
749
  editor.setSelection(props);
748
750
  }
751
+ /**
752
+ * Reduces the frame stack to an `OperationOrigin` by fixed precedence
753
+ * (undo > redo > normalization > remote > local), regardless of nesting
754
+ * order. Normalization outranks remote so a fix that runs while replaying
755
+ * a remote patch is attributed to the fix, not laundered into looking like
756
+ * an ordinary remote write; `hasRemoteFrame` is the precedence-blind read
757
+ * for callers that need the externally-triggered fact regardless of
758
+ * whether a fix ran on top of it.
759
+ */
760
+ function getOrigin(frames) {
761
+ return frames.some((frame) => frame.kind === "undo") ? "undo" : frames.some((frame) => frame.kind === "redo") ? "redo" : frames.some((frame) => frame.kind === "normalization") ? "normalization" : frames.some((frame) => frame.kind === "remote") ? "remote" : "local";
762
+ }
763
+ /**
764
+ * True while the frame stack carries a `remote` frame at any depth: the
765
+ * editor is applying content that arrived from outside (remote `patches`
766
+ * or value sync), possibly nested inside a normalization fix.
767
+ * `normalize-node`'s readers gate optional fix-ups on it to leave adopted
768
+ * content alone; `apply-operation` skips inverse population; the sync
769
+ * machine treats it as busy.
770
+ */
771
+ function hasRemoteFrame(frames) {
772
+ return frames.some((frame) => frame.kind === "remote");
773
+ }
774
+ /**
775
+ * Precedence-blind: true whenever a `normalization` frame is on the stack,
776
+ * even when an `undo` or `redo` frame outranks it in `getOrigin`.
777
+ */
778
+ function isInNormalization(frames) {
779
+ return frames.some((frame) => frame.kind === "normalization");
780
+ }
749
781
  function subscribeToOperations(editor, listener, options) {
750
782
  let phase = options?.phase ?? "after";
751
783
  return editor.operationListeners[phase] = [...editor.operationListeners[phase], listener], () => {
@@ -761,20 +793,16 @@ function subscribeToOperations(editor, listener, options) {
761
793
  * the apply.
762
794
  */
763
795
  function createOperationEvent(editor, operation) {
764
- let isNormalizingNode = !!editor.isNormalizingNode, isProcessingRemoteChanges = !!editor.isProcessingRemoteChanges, isUndoing = !!editor.isUndoing, isRedoing = !!editor.isRedoing;
765
796
  return {
766
797
  operation,
767
798
  beforeValue: editor.snapshot.context.value,
768
799
  beforeSelection: editor.snapshot.context.selection,
769
800
  operationsInProgress: editor.operations.length > 0,
770
- isNormalizingNode,
771
801
  isPatching: !!editor.isPatching,
772
- isProcessingRemoteChanges,
773
- isUndoing,
774
- isRedoing,
775
802
  withHistory: !!editor.withHistory,
776
803
  undoStepId: editor.undoStepId,
777
- origin: isProcessingRemoteChanges ? "remote" : isUndoing ? "undo" : isRedoing ? "redo" : isNormalizingNode ? "normalization" : "local"
804
+ origin: getOrigin(editor.applyContext),
805
+ context: Object.freeze([...editor.applyContext])
778
806
  };
779
807
  }
780
808
  function emitOperationEvent(listeners, event) {
@@ -2863,12 +2891,14 @@ const RestoreDOM = IS_ANDROID ? RestoreDOMComponent : ({ children }) => /* @__PU
2863
2891
  exactMatch: !1,
2864
2892
  suppressThrow: !0
2865
2893
  });
2866
- if (range) if (!editor.composing && !androidInputManager?.hasPendingChanges() && !androidInputManager?.isFlushing()) {
2867
- if (editor.select(range), domSelection.isCollapsed && anchorNode && anchorNode.nodeType === Node.ELEMENT_NODE) try {
2868
- let canonicalRange = DOMEditor.toDOMRange(editor, range);
2869
- domSelection.setBaseAndExtent(canonicalRange.startContainer, canonicalRange.startOffset, canonicalRange.startContainer, canonicalRange.startOffset);
2870
- } catch {}
2871
- } else androidInputManager?.handleUserSelect(range);
2894
+ if (range) {
2895
+ if (!editor.composing && !androidInputManager?.hasPendingChanges() && !androidInputManager?.isFlushing()) {
2896
+ if (editor.select(range), domSelection.isCollapsed && anchorNode && anchorNode.nodeType === Node.ELEMENT_NODE) try {
2897
+ let canonicalRange = DOMEditor.toDOMRange(editor, range);
2898
+ domSelection.setBaseAndExtent(canonicalRange.startContainer, canonicalRange.startOffset, canonicalRange.startContainer, canonicalRange.startOffset);
2899
+ } catch {}
2900
+ } else androidInputManager?.handleUserSelect(range);
2901
+ }
2872
2902
  }
2873
2903
  readOnly && (!anchorNodeSelectable || !focusNodeInEditor) && deselect(editor);
2874
2904
  }
@@ -4201,7 +4231,7 @@ const engineOperationCallback = ({ input, sendBack }) => subscribeToOperations(i
4201
4231
  event.operation.type !== "set.selection" && sendBack({
4202
4232
  type: "engine operation",
4203
4233
  operation: event.operation,
4204
- origin: event.origin
4234
+ origin: hasRemoteFrame(event.context) ? "remote" : "local"
4205
4235
  });
4206
4236
  }, { phase: "before" });
4207
4237
  function mergeRangeDecoration(leaf, decoration) {
@@ -4264,7 +4294,7 @@ const rangeDecorationsMachine = setup({
4264
4294
  decoratedRange.rangeDecoration.onMoved?.({
4265
4295
  newSelection: null,
4266
4296
  rangeDecoration: decoratedRange.rangeDecoration,
4267
- origin: event.origin === "remote" ? "remote" : "local"
4297
+ origin: event.origin
4268
4298
  });
4269
4299
  continue;
4270
4300
  }
@@ -4272,7 +4302,7 @@ const rangeDecorationsMachine = setup({
4272
4302
  (newRange && newRange !== currentSelection || newRange === null && currentSelection) && decoratedRange.rangeDecoration.onMoved?.({
4273
4303
  newSelection: newRange,
4274
4304
  rangeDecoration: decoratedRange.rangeDecoration,
4275
- origin: event.origin === "remote" ? "remote" : "local"
4305
+ origin: event.origin
4276
4306
  }), newRange !== null && rangeDecorationState.push({
4277
4307
  ...newRange || currentSelection,
4278
4308
  rangeDecoration: {
@@ -5465,16 +5495,7 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5465
5495
  type: "behavior event",
5466
5496
  behaviorEvent: {
5467
5497
  type: "insert.blocks",
5468
- blocks: parseBlocks({
5469
- keyGenerator: editorEngine.snapshot.context.keyGenerator,
5470
- schema: editorEngine.snapshot.context.schema,
5471
- blocks: result_1.insert,
5472
- options: {
5473
- normalize: !1,
5474
- removeUnusedMarkDefs: !0,
5475
- validateFields: !1
5476
- }
5477
- }),
5498
+ blocks: result_1.insert,
5478
5499
  placement: "auto"
5479
5500
  },
5480
5501
  editor: editorEngine
@@ -5644,11 +5665,7 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5644
5665
  }, $[105] = editorActor, $[106] = editorEngine, $[107] = onDragStart, $[108] = readOnly, $[109] = t28) : t28 = $[109];
5645
5666
  let handleDragStart = t28, t29;
5646
5667
  $[110] !== editorActor || $[111] !== editorEngine || $[112] !== onDrag ? (t29 = (event_9) => {
5647
- if (onDrag?.(event_9), !(event_9.isDefaultPrevented() || event_9.isPropagationStopped()) && getEventPosition({
5648
- editorActor,
5649
- editorEngine,
5650
- event: event_9.nativeEvent
5651
- })) return editorActor.send({
5668
+ if (onDrag?.(event_9), !(event_9.isDefaultPrevented() || event_9.isPropagationStopped()) && !(editorActor.getSnapshot().matches({ setup: "setting up" }) || !DOMEditor.hasTarget(editorEngine, event_9.target))) return editorActor.send({
5652
5669
  type: "behavior event",
5653
5670
  behaviorEvent: {
5654
5671
  type: "drag.drag",
@@ -5671,17 +5688,17 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5671
5688
  let handleDragEnd = t30, t31;
5672
5689
  $[118] !== editorActor || $[119] !== editorEngine || $[120] !== onDragEnter ? (t31 = (event_11) => {
5673
5690
  if (onDragEnter?.(event_11), event_11.isDefaultPrevented() || event_11.isPropagationStopped()) return;
5674
- let position_6 = getEventPosition({
5691
+ let position_5 = getEventPosition({
5675
5692
  editorActor,
5676
5693
  editorEngine,
5677
5694
  event: event_11.nativeEvent
5678
5695
  });
5679
- if (position_6) return editorActor.send({
5696
+ if (position_5) return editorActor.send({
5680
5697
  type: "behavior event",
5681
5698
  behaviorEvent: {
5682
5699
  type: "drag.dragenter",
5683
5700
  originEvent: { dataTransfer: event_11.dataTransfer },
5684
- position: position_6
5701
+ position: position_5
5685
5702
  },
5686
5703
  editor: editorEngine
5687
5704
  }), !0;
@@ -5689,18 +5706,18 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5689
5706
  let handleDragEnter = t31, t32;
5690
5707
  $[122] !== editorActor || $[123] !== editorEngine || $[124] !== onDragOver ? (t32 = (event_12) => {
5691
5708
  if (onDragOver?.(event_12), event_12.isDefaultPrevented() || event_12.isPropagationStopped()) return;
5692
- let position_7 = getEventPosition({
5709
+ let position_6 = getEventPosition({
5693
5710
  editorActor,
5694
5711
  editorEngine,
5695
5712
  event: event_12.nativeEvent
5696
5713
  });
5697
- if (position_7) return editorActor.send({
5714
+ if (position_6) return editorActor.send({
5698
5715
  type: "behavior event",
5699
5716
  behaviorEvent: {
5700
5717
  type: "drag.dragover",
5701
5718
  originEvent: { dataTransfer: event_12.dataTransfer },
5702
5719
  dragOrigin: editorActor.getSnapshot().context.internalDrag?.origin,
5703
- position: position_7
5720
+ position: position_6
5704
5721
  },
5705
5722
  editor: editorEngine,
5706
5723
  nativeEvent: event_12
@@ -5709,12 +5726,12 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5709
5726
  let handleDragOver = t32, t33;
5710
5727
  $[126] !== editorActor || $[127] !== editorEngine || $[128] !== onDrop ? (t33 = (event_13) => {
5711
5728
  if (onDrop?.(event_13), event_13.isDefaultPrevented() || event_13.isPropagationStopped()) return;
5712
- let position_8 = getEventPosition({
5729
+ let position_7 = getEventPosition({
5713
5730
  editorActor,
5714
5731
  editorEngine,
5715
5732
  event: event_13.nativeEvent
5716
5733
  });
5717
- if (!position_8) {
5734
+ if (!position_7) {
5718
5735
  console.warn("Could not find position for drop event");
5719
5736
  return;
5720
5737
  }
@@ -5724,7 +5741,7 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5724
5741
  type: "drag.drop",
5725
5742
  originEvent: { dataTransfer: event_13.dataTransfer },
5726
5743
  dragOrigin: editorActor.getSnapshot().context.internalDrag?.origin,
5727
- position: position_8
5744
+ position: position_7
5728
5745
  },
5729
5746
  editor: editorEngine,
5730
5747
  nativeEvent: event_13
@@ -5732,11 +5749,7 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5732
5749
  }, $[126] = editorActor, $[127] = editorEngine, $[128] = onDrop, $[129] = t33) : t33 = $[129];
5733
5750
  let handleDrop = t33, t34;
5734
5751
  $[130] !== editorActor || $[131] !== editorEngine || $[132] !== onDragLeave ? (t34 = (event_14) => {
5735
- if (onDragLeave?.(event_14), !(event_14.isDefaultPrevented() || event_14.isPropagationStopped()) && getEventPosition({
5736
- editorActor,
5737
- editorEngine,
5738
- event: event_14.nativeEvent
5739
- })) return editorActor.send({
5752
+ if (onDragLeave?.(event_14), !(event_14.isDefaultPrevented() || event_14.isPropagationStopped()) && !(editorActor.getSnapshot().matches({ setup: "setting up" }) || !DOMEditor.hasTarget(editorEngine, event_14.target))) return editorActor.send({
5740
5753
  type: "behavior event",
5741
5754
  behaviorEvent: {
5742
5755
  type: "drag.dragleave",
@@ -5919,11 +5932,7 @@ const converterJson = defineConverter({
5919
5932
  let parsedBlock = parseBlock({
5920
5933
  keyGenerator: snapshot.context.keyGenerator,
5921
5934
  block,
5922
- options: {
5923
- normalize: !1,
5924
- removeUnusedMarkDefs: !0,
5925
- validateFields: !1
5926
- },
5935
+ profile: "lenient",
5927
5936
  schema: snapshot.context.schema
5928
5937
  });
5929
5938
  return parsedBlock ? [parsedBlock] : [];
@@ -5971,11 +5980,7 @@ const converterJson = defineConverter({
5971
5980
  let parsedBlock = parseBlock({
5972
5981
  keyGenerator: snapshot.context.keyGenerator,
5973
5982
  block,
5974
- options: {
5975
- normalize: !1,
5976
- removeUnusedMarkDefs: !0,
5977
- validateFields: !1
5978
- },
5983
+ profile: "lenient",
5979
5984
  schema: snapshot.context.schema
5980
5985
  });
5981
5986
  return parsedBlock ? [parsedBlock] : [];
@@ -6011,11 +6016,7 @@ const converterJson = defineConverter({
6011
6016
  let parsedBlock = parseBlock({
6012
6017
  keyGenerator: snapshot.context.keyGenerator,
6013
6018
  block,
6014
- options: {
6015
- normalize: !1,
6016
- removeUnusedMarkDefs: !0,
6017
- validateFields: !1
6018
- },
6019
+ profile: "lenient",
6019
6020
  schema: snapshot.context.schema
6020
6021
  });
6021
6022
  return parsedBlock ? [parsedBlock] : [];
@@ -6316,7 +6317,7 @@ function createBehaviorApiPlugin(editorActor) {
6316
6317
  return function behaviorApiPlugin(editor) {
6317
6318
  let { select, setSelection } = editor;
6318
6319
  return editor.select = (location) => {
6319
- if (editor.isNormalizingNode || editor.isPerformingBehaviorOperation) {
6320
+ if (isInNormalization(editor.applyContext) || editor.isPerformingBehaviorOperation) {
6320
6321
  select(location);
6321
6322
  return;
6322
6323
  }
@@ -6337,7 +6338,7 @@ function createBehaviorApiPlugin(editorActor) {
6337
6338
  editor
6338
6339
  });
6339
6340
  }, editor.setSelection = (partialRange) => {
6340
- if (editor.isNormalizingNode || editor.isPerformingBehaviorOperation) {
6341
+ if (isInNormalization(editor.applyContext) || editor.isPerformingBehaviorOperation) {
6341
6342
  setSelection(partialRange);
6342
6343
  return;
6343
6344
  }
@@ -6482,8 +6483,8 @@ function getDirtyPaths(context, op) {
6482
6483
  let levels = [[]];
6483
6484
  if (Array.isArray(op.value)) for (let i = 0; i < op.value.length; i++) {
6484
6485
  let child = op.value[i];
6485
- if (typeof child != "object" || !child || !("_key" in child) || typeof child._key != "string") continue;
6486
- let childNode = child, childPath = [{ _key: childNode._key }];
6486
+ if (typeof child != "object" || !child) continue;
6487
+ let childNode = child, childPath = [nodeSegment(childNode, i)];
6487
6488
  levels.push(childPath), collectDescendantPaths(context, childNode, childPath, levels, context.containers.get(childNode._type));
6488
6489
  }
6489
6490
  return levels;
@@ -6507,11 +6508,11 @@ function getDirtyPaths(context, op) {
6507
6508
  let parentRegistration = resolveContainerAt(context.containers, context.value, nodePath), seed = parentRegistration && "field" in parentRegistration ? parentRegistration : void 0;
6508
6509
  for (let i = 0; i < op.value.length; i++) {
6509
6510
  let child = op.value[i];
6510
- if (typeof child != "object" || !child || !("_key" in child) || typeof child._key != "string") continue;
6511
+ if (typeof child != "object" || !child) continue;
6511
6512
  let childNode = child, childPath = [
6512
6513
  ...nodePath,
6513
6514
  propertyName,
6514
- { _key: childNode._key }
6515
+ nodeSegment(childNode, i)
6515
6516
  ];
6516
6517
  levels.push(childPath), collectDescendantPaths(context, childNode, childPath, levels, seed);
6517
6518
  }
@@ -6587,7 +6588,14 @@ function normalize(editor, options = {}) {
6587
6588
  let entry = getNode(editor.snapshot, dirtyPath);
6588
6589
  if (!entry) continue;
6589
6590
  let entryNode = entry.node;
6590
- isTextBlock({ schema: editor.snapshot.context.schema }, entryNode) && entryNode.children.length === 0 && (editor.isNormalizingNode = !0, editor.normalizeNode([entry.node, entry.path], { operation }), editor.isNormalizingNode = !1);
6591
+ if (isTextBlock({ schema: editor.snapshot.context.schema }, entryNode) && entryNode.children.length === 0) {
6592
+ editor.applyContext.push(Object.freeze({ kind: "normalization" }));
6593
+ try {
6594
+ editor.normalizeNode([entry.node, entry.path], { operation });
6595
+ } finally {
6596
+ editor.applyContext.pop();
6597
+ }
6598
+ }
6591
6599
  }
6592
6600
  let dirtyPaths = getDirtyPaths(editor), initialDirtyPathsLength = dirtyPaths.length, iteration = 0;
6593
6601
  for (; dirtyPaths.length !== 0;) {
@@ -6598,10 +6606,23 @@ function normalize(editor, options = {}) {
6598
6606
  operation
6599
6607
  })) return;
6600
6608
  let dirtyPath = popDirtyPath(editor);
6601
- if (dirtyPath.length === 0) editor.isNormalizingNode = !0, editor.normalizeNode([editor, dirtyPath], { operation }), editor.isNormalizingNode = !1;
6602
- else if (hasNode(editor.snapshot, dirtyPath)) {
6609
+ if (dirtyPath.length === 0) {
6610
+ editor.applyContext.push(Object.freeze({ kind: "normalization" }));
6611
+ try {
6612
+ editor.normalizeNode([editor, dirtyPath], { operation });
6613
+ } finally {
6614
+ editor.applyContext.pop();
6615
+ }
6616
+ } else if (hasNode(editor.snapshot, dirtyPath)) {
6603
6617
  let entry = getNode(editor.snapshot, dirtyPath);
6604
- entry && (editor.isNormalizingNode = !0, editor.normalizeNode([entry.node, entry.path], { operation }), editor.isNormalizingNode = !1);
6618
+ if (entry) {
6619
+ editor.applyContext.push(Object.freeze({ kind: "normalization" }));
6620
+ try {
6621
+ editor.normalizeNode([entry.node, entry.path], { operation });
6622
+ } finally {
6623
+ editor.applyContext.pop();
6624
+ }
6625
+ }
6605
6626
  }
6606
6627
  iteration++, dirtyPaths = getDirtyPaths(editor);
6607
6628
  }
@@ -6770,74 +6791,42 @@ function replaceChildren(xs, index, removeCount, ...newValues) {
6770
6791
  let result = xs.slice();
6771
6792
  return result.splice(index, removeCount, ...newValues), result;
6772
6793
  }
6773
- const removeChildren = replaceChildren;
6774
- /**
6775
- * Find the index of a node in an array by its _key.
6776
- */
6777
- function findIndexByKey(children, key) {
6778
- return children.findIndex((child) => child._key === key);
6779
- }
6780
- /**
6781
- * Extract the keyed segments from a path (skipping field name strings).
6782
- */
6783
- function getKeyedSegments(path) {
6784
- return path.filter(isKeyedSegment);
6785
- }
6786
- /**
6787
- * Replace a descendant with a new node, replacing all ancestors
6788
- */
6789
- const modifyDescendant = (editor, path, f) => {
6794
+ const removeChildren = replaceChildren, modifyDescendant = (editor, path, f) => {
6790
6795
  if (path.length === 0) return;
6791
6796
  let context = {
6792
6797
  schema: editor.snapshot.context.schema,
6793
6798
  containers: editor.snapshot.context.containers
6794
6799
  }, nodeEntry = getNode(editor.snapshot, path);
6795
6800
  if (!nodeEntry) return;
6796
- let node = nodeEntry.node, modifiedNode = f(node), keyedSegments = getKeyedSegments(nodeEntry.path), numericIndices = /* @__PURE__ */ new Map();
6797
- {
6798
- let keyedIdx = 0;
6799
- for (let segment of path) typeof segment == "number" ? (numericIndices.set(keyedIdx, segment), keyedIdx++) : isKeyedSegment(segment) && keyedIdx++;
6800
- }
6801
- let fieldNames = [];
6802
- {
6803
- let currentNode = { value: editor.snapshot.context.value }, currentParent;
6804
- for (let i = 0; i < keyedSegments.length; i++) {
6805
- let result = getNodeChildren(context, currentNode, currentParent);
6806
- if (!result) return;
6807
- fieldNames.push(result.fieldName);
6808
- let numericIndex = numericIndices.get(i), child = numericIndex === void 0 ? result.children.find((c) => c._key === keyedSegments[i]._key) : result.children[numericIndex];
6809
- if (!child) return;
6810
- currentNode = child, currentParent = result.parent;
6811
- }
6812
- }
6813
- for (let level = keyedSegments.length - 2; level >= 0; level--) {
6814
- let childKey = keyedSegments[level + 1]._key, fieldName = fieldNames[level + 1], ancestorPathEnd = -1, keyedCount = 0;
6815
- for (let pi = 0; pi < path.length; pi++) if (typeof path[pi] != "string") {
6816
- if (keyedCount === level) {
6817
- ancestorPathEnd = pi + 1;
6818
- break;
6819
- }
6820
- keyedCount++;
6821
- }
6822
- let ancestorPath = ancestorPathEnd > 0 ? path.slice(0, ancestorPathEnd) : [], ancestorEntry = getNode(editor.snapshot, ancestorPath);
6823
- if (!ancestorEntry) return;
6824
- let ancestorNode = ancestorEntry.node, ancestorRecord = ancestorNode, currentChildren = Array.isArray(ancestorRecord[fieldName]) ? ancestorRecord[fieldName] : [], originalNumericIndex = numericIndices.get(level + 1), childIndex = originalNumericIndex === void 0 ? findIndexByKey(currentChildren, childKey) : originalNumericIndex;
6825
- if (childIndex === -1) return;
6801
+ let resolvedNodeSegments = nodeEntry.path.filter((segment) => typeof segment != "string"), inputNodeSegments = path.filter((segment) => typeof segment != "string"), levels = [], currentNode = { value: editor.snapshot.context.value }, currentParent;
6802
+ for (let i = 0; i < resolvedNodeSegments.length; i++) {
6803
+ let result = getNodeChildren(context, currentNode, currentParent);
6804
+ if (!result) return;
6805
+ let inputSegment = inputNodeSegments[i], resolvedSegment = resolvedNodeSegments[i], index;
6806
+ if (typeof inputSegment == "number") index = inputSegment;
6807
+ else if (typeof resolvedSegment == "number") index = resolvedSegment;
6808
+ else if (isKeyedSegment(resolvedSegment)) index = result.children.findIndex((child) => child._key === resolvedSegment._key);
6809
+ else return;
6810
+ let child = result.children[index];
6811
+ if (!child) return;
6812
+ levels.push({
6813
+ parentNode: currentNode,
6814
+ fieldName: result.fieldName,
6815
+ children: result.children,
6816
+ index
6817
+ }), currentNode = child, currentParent = result.parent;
6818
+ }
6819
+ let deepestLevel = levels.length - 1;
6820
+ if (deepestLevel < 0) return;
6821
+ let modifiedNode = f(currentNode);
6822
+ for (let level = deepestLevel; level >= 1; level--) {
6823
+ let { parentNode, fieldName, children, index } = levels[level];
6826
6824
  modifiedNode = {
6827
- ...ancestorNode,
6828
- [fieldName]: replaceChildren(currentChildren, childIndex, 1, modifiedNode)
6825
+ ...parentNode,
6826
+ [fieldName]: replaceChildren(children, index, 1, modifiedNode)
6829
6827
  };
6830
6828
  }
6831
- let rootIndex, rootNumericIndex = numericIndices.get(0);
6832
- if (rootNumericIndex !== void 0) rootIndex = rootNumericIndex;
6833
- else if (keyedSegments.length > 0) {
6834
- let rootSegment = keyedSegments[0], mapIndex = editor.blockIndexMap.get(serializePath([rootSegment]));
6835
- rootIndex = mapIndex === void 0 ? findIndexByKey(editor.snapshot.context.value, rootSegment._key) : mapIndex;
6836
- } else {
6837
- let firstSegment = path[0];
6838
- rootIndex = typeof firstSegment == "number" ? firstSegment : -1;
6839
- }
6840
- rootIndex === -1 || rootIndex >= editor.snapshot.context.value.length || (editor.snapshot.context.value = replaceChildren(editor.snapshot.context.value, rootIndex, 1, modifiedNode));
6829
+ editor.snapshot.context.value = replaceChildren(editor.snapshot.context.value, levels[0].index, 1, modifiedNode);
6841
6830
  }, modifyChildren = (editor, path, f) => {
6842
6831
  if (path.length === 0) editor.snapshot.context.value = f(editor.snapshot.context.value);
6843
6832
  else {
@@ -6871,7 +6860,7 @@ function applyOperation(editor, op) {
6871
6860
  break;
6872
6861
  }
6873
6862
  modifyChildren(editor, parentPath(path), (children) => {
6874
- !editor.isProcessingRemoteChanges && !editor.isUndoing && !editor.isRedoing && node._key !== void 0 && children.some((sibling) => sibling._key === node._key) && (node = {
6863
+ !editor.applyContext.some((frame) => frame.kind === "remote" || frame.kind === "undo" || frame.kind === "redo") && node._key !== void 0 && children.some((sibling) => sibling._key === node._key) && (node = {
6875
6864
  ...node,
6876
6865
  _key: editor.snapshot.context.keyGenerator()
6877
6866
  }, op.node = node);
@@ -6883,7 +6872,7 @@ function applyOperation(editor, op) {
6883
6872
  } else if (typeof lastSegment == "number") index = op.position === "after" ? lastSegment + 1 : lastSegment;
6884
6873
  else throw Error(`Cannot apply an "insert" operation at path [${path}] because the last segment is a field name.`);
6885
6874
  if (index > children.length) throw Error(`Cannot apply an "insert" operation at path [${path}] because the destination is past the end of the node.`);
6886
- return !op.inverse && !editor.isProcessingRemoteChanges && (op.inverse = {
6875
+ return !op.inverse && !hasRemoteFrame(editor.applyContext) && (op.inverse = {
6887
6876
  type: "unset",
6888
6877
  path: node._key === void 0 ? path : replaceLastSegment(path, { _key: node._key })
6889
6878
  }), insertChildren(children, index, node);
@@ -6916,7 +6905,7 @@ function applyOperation(editor, op) {
6916
6905
  }
6917
6906
  case "set": {
6918
6907
  let { path, value } = op;
6919
- if (!op.inverse && !editor.isProcessingRemoteChanges) {
6908
+ if (!op.inverse && !hasRemoteFrame(editor.applyContext)) {
6920
6909
  let previousValue = getValue(editor.snapshot.context.value, path), inversePath = path[path.length - 1] === "_key" && typeof value == "string" && isKeyedSegment(path[path.length - 2]) ? [
6921
6910
  ...path.slice(0, -2),
6922
6911
  { _key: value },
@@ -6945,14 +6934,15 @@ function applyOperation(editor, op) {
6945
6934
  typeof value == "object" && value && !Array.isArray(value) && modifyDescendant(editor, setNodePath, () => value), transformSelection = !0;
6946
6935
  break;
6947
6936
  }
6948
- if (getNode(editor.snapshot, setNodePath)) if (setPropertyPath.length === 1) {
6949
- let propertyName = setPropertyPath[0];
6950
- modifyDescendant(editor, setNodePath, (node) => ({
6951
- ...node,
6952
- [propertyName]: value
6953
- }));
6954
- } else modifyDescendant(editor, setNodePath, (node) => deepSet(node, setPropertyPath, value));
6955
- else {
6937
+ if (getNode(editor.snapshot, setNodePath)) {
6938
+ if (setPropertyPath.length === 1) {
6939
+ let propertyName = setPropertyPath[0];
6940
+ modifyDescendant(editor, setNodePath, (node) => ({
6941
+ ...node,
6942
+ [propertyName]: value
6943
+ }));
6944
+ } else modifyDescendant(editor, setNodePath, (node) => deepSet(node, setPropertyPath, value));
6945
+ } else {
6956
6946
  let blockSegment = findBlockSegment(path);
6957
6947
  if (!blockSegment) break;
6958
6948
  let blockIndex = resolveBlockIndex(editor, blockSegment);
@@ -6968,7 +6958,7 @@ function applyOperation(editor, op) {
6968
6958
  case "unset": {
6969
6959
  let { path } = op;
6970
6960
  if (path.length === 0) {
6971
- !op.inverse && !editor.isProcessingRemoteChanges && (op.inverse = {
6961
+ !op.inverse && !hasRemoteFrame(editor.applyContext) && (op.inverse = {
6972
6962
  type: "set",
6973
6963
  path,
6974
6964
  value: editor.snapshot.context.value
@@ -6977,7 +6967,7 @@ function applyOperation(editor, op) {
6977
6967
  }
6978
6968
  let lastSegment = path[path.length - 1];
6979
6969
  if ((isKeyedSegment(lastSegment) || typeof lastSegment == "number") && !targetsStructuralChildren(editor, path)) {
6980
- if (!op.inverse && !editor.isProcessingRemoteChanges) {
6970
+ if (!op.inverse && !hasRemoteFrame(editor.applyContext)) {
6981
6971
  let arrayValue = getValue(editor.snapshot.context.value, path.slice(0, -1));
6982
6972
  Array.isArray(arrayValue) && (op.inverse = {
6983
6973
  type: "set",
@@ -7013,7 +7003,7 @@ function applyOperation(editor, op) {
7013
7003
  modifyChildren(editor, parentPath(path), (children) => {
7014
7004
  let index;
7015
7005
  if (index = isKeyedSegment(lastSegment) ? resolveChildIndex$1(editor.blockIndexMap, path.slice(0, -1), lastSegment, children) : lastSegment, index === -1 || index >= children.length) throw Error(`Cannot apply an "unset" (node removal) operation at path [${path}] because the node was not found.`);
7016
- if (!op.inverse && !editor.isProcessingRemoteChanges) {
7006
+ if (!op.inverse && !hasRemoteFrame(editor.applyContext)) {
7017
7007
  let previousSibling = index > 0 ? children[index - 1] : void 0;
7018
7008
  op.inverse = previousSibling?._key ? {
7019
7009
  type: "insert",
@@ -7033,7 +7023,7 @@ function applyOperation(editor, op) {
7033
7023
  }
7034
7024
  let { nodePath: unsetNodePath, propertyPath: unsetPropertyPath } = splitNodePath(path);
7035
7025
  if (unsetPropertyPath.length === 0 || unsetNodePath.length === 0) break;
7036
- if (!op.inverse && !editor.isProcessingRemoteChanges) {
7026
+ if (!op.inverse && !hasRemoteFrame(editor.applyContext)) {
7037
7027
  let previousValue = getValue(editor.snapshot.context.value, path);
7038
7028
  if (previousValue === void 0) break;
7039
7029
  op.inverse = {
@@ -7042,14 +7032,15 @@ function applyOperation(editor, op) {
7042
7032
  value: previousValue
7043
7033
  };
7044
7034
  }
7045
- if (getNode(editor.snapshot, unsetNodePath)) if (unsetPropertyPath.length === 1) {
7046
- let propertyName = unsetPropertyPath[0];
7047
- modifyDescendant(editor, unsetNodePath, (node) => {
7048
- let newNode = { ...node };
7049
- return delete newNode[propertyName], newNode;
7050
- });
7051
- } else modifyDescendant(editor, unsetNodePath, (node) => deepUnset(node, unsetPropertyPath));
7052
- else {
7035
+ if (getNode(editor.snapshot, unsetNodePath)) {
7036
+ if (unsetPropertyPath.length === 1) {
7037
+ let propertyName = unsetPropertyPath[0];
7038
+ modifyDescendant(editor, unsetNodePath, (node) => {
7039
+ let newNode = { ...node };
7040
+ return delete newNode[propertyName], newNode;
7041
+ });
7042
+ } else modifyDescendant(editor, unsetNodePath, (node) => deepUnset(node, unsetPropertyPath));
7043
+ } else {
7053
7044
  let blockSegment = findBlockSegment(path);
7054
7045
  if (!blockSegment) break;
7055
7046
  let blockIndex = resolveBlockIndex(editor, blockSegment);
@@ -7163,18 +7154,21 @@ function resolveChildIndex$1(blockIndexMap, parentSegments, segment, children) {
7163
7154
  return index !== void 0 && children[index]?._key === segment._key ? index : children.findIndex((child) => child._key === segment._key);
7164
7155
  }
7165
7156
  /**
7166
- * Extract the block key from the first segment of a path.
7157
+ * Extract the root block reference from the first segment of a path:
7158
+ * keyed, or a numeric index for a node normalization has not keyed yet.
7167
7159
  */
7168
7160
  function findBlockSegment(path) {
7169
7161
  let firstSegment = path[0];
7170
- if (isKeyedSegment(firstSegment)) return firstSegment;
7162
+ if (isKeyedSegment(firstSegment) || typeof firstSegment == "number") return firstSegment;
7171
7163
  }
7172
7164
  /**
7173
7165
  * Resolve a root block's index via `blockIndexMap`, falling back to a
7174
7166
  * linear scan when the map misses or disagrees with the tree.
7175
7167
  */
7176
7168
  function resolveBlockIndex(editor, segment) {
7177
- let value = editor.snapshot.context.value, index = editor.blockIndexMap.get(serializePath([segment]));
7169
+ let value = editor.snapshot.context.value;
7170
+ if (typeof segment == "number") return segment < value.length ? segment : -1;
7171
+ let index = editor.blockIndexMap.get(serializePath([segment]));
7178
7172
  return index !== void 0 && value[index]?._key === segment._key ? index : value.findIndex((block) => block._key === segment._key);
7179
7173
  }
7180
7174
  /**
@@ -7253,30 +7247,37 @@ const apply$1 = (editor, op) => {
7253
7247
  for (let ref of editor.pathRefs) PathRef.transform(ref, op);
7254
7248
  for (let ref of editor.pointRefs) PointRef.transform(ref, op);
7255
7249
  for (let ref of editor.rangeRefs) transformRangeRef(ref, op, editor.snapshot.context);
7256
- if (applyOperation(editor, op), updateDirtyPaths(editor, getDirtyPaths(editor.snapshot.context, op)), editor.operations.push(op), normalize(editor, { operation: op }), op.type === "set.selection") if (op.properties && op.newProperties && op.properties.anchor && op.properties.focus && op.newProperties.anchor && op.newProperties.focus) {
7257
- let previousSelectionIsCollapsed = isCollapsedRange({
7258
- anchor: op.properties.anchor,
7259
- focus: op.properties.focus
7260
- }), newSelectionIsCollapsed = isCollapsedRange({
7261
- anchor: op.newProperties.anchor,
7262
- focus: op.newProperties.focus
7263
- });
7264
- if (previousSelectionIsCollapsed && newSelectionIsCollapsed) {
7265
- let focusSpan = getSpan(editor.snapshot, op.properties.focus.path)?.node, newFocusSpan = getSpan(editor.snapshot, op.newProperties.focus.path)?.node, sameParent = pathEquals(parentPath(op.properties.focus.path), parentPath(op.newProperties.focus.path)), movedToNextSpan = !1, movedToPreviousSpan = !1;
7266
- if (sameParent && focusSpan && newFocusSpan) {
7267
- let nextSibling = getSibling(editor.snapshot, op.properties.focus.path, { direction: "next" }), previousSibling = getSibling(editor.snapshot, op.properties.focus.path, { direction: "previous" });
7268
- movedToNextSpan = nextSibling !== void 0 && pathEquals(nextSibling.path, op.newProperties.focus.path) && focusSpan.text.length === op.properties.focus.offset && op.newProperties.focus.offset === 0, movedToPreviousSpan = previousSibling !== void 0 && pathEquals(previousSibling.path, op.newProperties.focus.path) && op.properties.focus.offset === 0 && newFocusSpan.text.length === op.newProperties.focus.offset;
7250
+ if (applyOperation(editor, op), updateDirtyPaths(editor, getDirtyPaths(editor.snapshot.context, op)), editor.operations.push(op), normalize(editor, { operation: op }), op.type === "set.selection") {
7251
+ if (op.properties && op.newProperties && op.properties.anchor && op.properties.focus && op.newProperties.anchor && op.newProperties.focus) {
7252
+ let previousSelectionIsCollapsed = isCollapsedRange({
7253
+ anchor: op.properties.anchor,
7254
+ focus: op.properties.focus
7255
+ }), newSelectionIsCollapsed = isCollapsedRange({
7256
+ anchor: op.newProperties.anchor,
7257
+ focus: op.newProperties.focus
7258
+ });
7259
+ if (previousSelectionIsCollapsed && newSelectionIsCollapsed) {
7260
+ let focusSpan = getSpan(editor.snapshot, op.properties.focus.path)?.node, newFocusSpan = getSpan(editor.snapshot, op.newProperties.focus.path)?.node, sameParent = pathEquals(parentPath(op.properties.focus.path), parentPath(op.newProperties.focus.path)), movedToNextSpan = !1, movedToPreviousSpan = !1;
7261
+ if (sameParent && focusSpan && newFocusSpan) {
7262
+ let nextSibling = getSibling(editor.snapshot, op.properties.focus.path, { direction: "next" }), previousSibling = getSibling(editor.snapshot, op.properties.focus.path, { direction: "previous" });
7263
+ movedToNextSpan = nextSibling !== void 0 && pathEquals(nextSibling.path, op.newProperties.focus.path) && focusSpan.text.length === op.properties.focus.offset && op.newProperties.focus.offset === 0, movedToPreviousSpan = previousSibling !== void 0 && pathEquals(previousSibling.path, op.newProperties.focus.path) && op.properties.focus.offset === 0 && newFocusSpan.text.length === op.newProperties.focus.offset;
7264
+ }
7265
+ !movedToNextSpan && !movedToPreviousSpan && (editor.snapshot.decoratorState = {});
7269
7266
  }
7270
- !movedToNextSpan && !movedToPreviousSpan && (editor.snapshot.decoratorState = {});
7271
- }
7272
- } else editor.snapshot.decoratorState = {};
7267
+ } else editor.snapshot.decoratorState = {};
7268
+ }
7273
7269
  editor.flushing || (editor.flushing = !0, Promise.resolve().then(() => {
7274
7270
  editor.flushing = !1, editor.onChange({ operation: op }), editor.operations = [];
7275
7271
  })), operationEvent && emitOperationEvent(editor.operationListeners.after, operationEvent);
7276
7272
  };
7277
7273
  function withoutPatching(editor, fn) {
7278
7274
  let prev = editor.isPatching;
7279
- editor.isPatching = !1, fn(), editor.isPatching = prev;
7275
+ editor.isPatching = !1;
7276
+ try {
7277
+ fn();
7278
+ } finally {
7279
+ editor.isPatching = prev;
7280
+ }
7280
7281
  }
7281
7282
  function isEnd(editor, point, at) {
7282
7283
  return pointEquals(point, end(editor, at));
@@ -7677,30 +7678,32 @@ function applyNodeProperties(editor, props, path) {
7677
7678
  let nodeRecord = result.entry.node, propsRecord = props, keys = Object.keys(propsRecord), keyIndex = keys.indexOf("_key");
7678
7679
  keyIndex !== -1 && (keys.splice(keyIndex, 1), keys.unshift("_key"));
7679
7680
  let currentPath = path;
7680
- for (let key of keys) if (propsRecord[key] !== nodeRecord[key]) if (propsRecord[key] != null) {
7681
- let hadProperty = nodeRecord.hasOwnProperty(key), lastSegment = currentPath[currentPath.length - 1], renamedPath = key === "_key" && typeof propsRecord[key] == "string" && isKeyedSegment(lastSegment) ? [...currentPath.slice(0, -1), { _key: propsRecord[key] }] : void 0, inversePath = renamedPath ? [...renamedPath, key] : [...currentPath, key];
7682
- editor.apply({
7683
- type: "set",
7681
+ for (let key of keys) if (propsRecord[key] !== nodeRecord[key]) {
7682
+ if (propsRecord[key] != null) {
7683
+ let hadProperty = nodeRecord.hasOwnProperty(key), lastSegment = currentPath[currentPath.length - 1], renamedPath = key === "_key" && typeof propsRecord[key] == "string" && isKeyedSegment(lastSegment) ? [...currentPath.slice(0, -1), { _key: propsRecord[key] }] : void 0, inversePath = renamedPath ? [...renamedPath, key] : [...currentPath, key];
7684
+ editor.apply({
7685
+ type: "set",
7686
+ path: [...currentPath, key],
7687
+ value: propsRecord[key],
7688
+ inverse: hadProperty ? {
7689
+ type: "set",
7690
+ path: inversePath,
7691
+ value: nodeRecord[key]
7692
+ } : {
7693
+ type: "unset",
7694
+ path: inversePath
7695
+ }
7696
+ }), renamedPath && (currentPath = renamedPath);
7697
+ } else nodeRecord.hasOwnProperty(key) && editor.apply({
7698
+ type: "unset",
7684
7699
  path: [...currentPath, key],
7685
- value: propsRecord[key],
7686
- inverse: hadProperty ? {
7700
+ inverse: {
7687
7701
  type: "set",
7688
- path: inversePath,
7702
+ path: [...currentPath, key],
7689
7703
  value: nodeRecord[key]
7690
- } : {
7691
- type: "unset",
7692
- path: inversePath
7693
7704
  }
7694
- }), renamedPath && (currentPath = renamedPath);
7695
- } else nodeRecord.hasOwnProperty(key) && editor.apply({
7696
- type: "unset",
7697
- path: [...currentPath, key],
7698
- inverse: {
7699
- type: "set",
7700
- path: [...currentPath, key],
7701
- value: nodeRecord[key]
7702
- }
7703
- });
7705
+ });
7706
+ }
7704
7707
  }
7705
7708
  /**
7706
7709
  * Create a placeholder text block -- the empty initial block used when the
@@ -7819,7 +7822,7 @@ function richDescentToParent(input, path) {
7819
7822
  * 3. **Global fallback with position-validity.** Falls back to the
7820
7823
  * top-level rich `containers` map keyed by `_type`. Activates only
7821
7824
  * when schema-at-position permits the registered `arrayField`
7822
- * (for containers) or simply declares `_type` (for leaves).
7825
+ * (for containers) or declares `_type` (for leaves).
7823
7826
  * Registration is type-keyed; activation is position-gated.
7824
7827
  */
7825
7828
  function resolveContainerByPath(input, path, node) {
@@ -7854,7 +7857,7 @@ const normalizeNode = (editor, entry) => {
7854
7857
  /**
7855
7858
  * Merge spans with same set of .marks
7856
7859
  */
7857
- if (!editor.isProcessingRemoteChanges && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
7860
+ if (!hasRemoteFrame(editor.applyContext) && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
7858
7861
  let children = getChildren(editor.snapshot, path);
7859
7862
  for (let i = 0; i < children.length - 1; i++) {
7860
7863
  let { node: child } = children[i], { node: nextNode, path: nextChildPath } = children[i + 1];
@@ -7889,35 +7892,15 @@ const normalizeNode = (editor, entry) => {
7889
7892
  });
7890
7893
  return;
7891
7894
  }
7892
- if (nodeRecord._key === void 0 && path.length > 0) {
7895
+ if (!hasUsableKey(nodeRecord._key) && path.length > 0) {
7893
7896
  let newKey = editor.snapshot.context.keyGenerator();
7894
- debug.normalization("Setting missing key on node");
7895
- let numericPath = [], currentNode;
7896
- for (let segment of path) {
7897
- if (typeof segment == "string") {
7898
- currentNode && numericPath.push(segment);
7899
- continue;
7900
- }
7901
- let siblings = currentNode ? currentNode[numericPath[numericPath.length - 1]] ?? [] : editor.snapshot.context.value;
7902
- if (isKeyedSegment(segment) && segment._key !== void 0) numericPath.push(segment), currentNode = Array.prototype.find.call(siblings, (child) => child._key === segment._key);
7903
- else {
7904
- let index = typeof segment == "number" ? segment : -1;
7905
- if (index === -1) {
7906
- for (let i = 0; i < siblings.length; i++) if (siblings[i]._key === void 0) {
7907
- index = i;
7908
- break;
7909
- }
7910
- }
7911
- index !== -1 && (numericPath.push(index), currentNode = siblings[index]);
7912
- }
7913
- }
7914
- editor.apply({
7897
+ debug.normalization("Setting missing key on node"), editor.apply({
7915
7898
  type: "set",
7916
- path: [...numericPath, "_key"],
7899
+ path: [...path, "_key"],
7917
7900
  value: newKey,
7918
7901
  inverse: {
7919
7902
  type: "unset",
7920
- path: [...numericPath, "_key"]
7903
+ path: [...path, "_key"]
7921
7904
  }
7922
7905
  });
7923
7906
  return;
@@ -7959,14 +7942,14 @@ const normalizeNode = (editor, entry) => {
7959
7942
  /**
7960
7943
  * Add missing .markDefs to text block nodes
7961
7944
  */
7962
- if (!editor.isProcessingRemoteChanges && isTextBlockNode({ schema: editor.snapshot.context.schema }, node) && !Array.isArray(node.markDefs)) {
7945
+ if (!hasRemoteFrame(editor.applyContext) && isTextBlockNode({ schema: editor.snapshot.context.schema }, node) && !Array.isArray(node.markDefs)) {
7963
7946
  debug.normalization("adding .markDefs to block node"), applyNodeProperties(editor, { markDefs: [] }, path);
7964
7947
  return;
7965
7948
  }
7966
7949
  /**
7967
7950
  * Add missing .style to text block nodes
7968
7951
  */
7969
- if (!editor.isProcessingRemoteChanges && isTextBlockNode({ schema: editor.snapshot.context.schema }, node) && node.style === void 0) {
7952
+ if (!hasRemoteFrame(editor.applyContext) && isTextBlockNode({ schema: editor.snapshot.context.schema }, node) && node.style === void 0) {
7970
7953
  let defaultStyle = getPathSubSchema(editor.snapshot, path).styles.at(0)?.name;
7971
7954
  if (defaultStyle) {
7972
7955
  debug.normalization("adding .style to block node"), applyNodeProperties(editor, { style: defaultStyle }, path);
@@ -7991,14 +7974,14 @@ const normalizeNode = (editor, entry) => {
7991
7974
  /**
7992
7975
  * Add missing .marks to span nodes
7993
7976
  */
7994
- if (!editor.isProcessingRemoteChanges && isSpan({ schema: editor.snapshot.context.schema }, node) && !Array.isArray(node.marks)) {
7977
+ if (!hasRemoteFrame(editor.applyContext) && isSpan({ schema: editor.snapshot.context.schema }, node) && !Array.isArray(node.marks)) {
7995
7978
  debug.normalization("Adding .marks to span node"), applyNodeProperties(editor, { marks: [] }, path);
7996
7979
  return;
7997
7980
  }
7998
7981
  /**
7999
7982
  * Remove annotations from empty spans
8000
7983
  */
8001
- if (!editor.isProcessingRemoteChanges && isSpan({ schema: editor.snapshot.context.schema }, node)) {
7984
+ if (!hasRemoteFrame(editor.applyContext) && isSpan({ schema: editor.snapshot.context.schema }, node)) {
8002
7985
  let blockPath = parentPath(path), blockEntry = getTextBlock(editor.snapshot, blockPath);
8003
7986
  if (!blockEntry) return;
8004
7987
  let annotations = node.marks?.filter((mark) => blockEntry.node.markDefs?.some((markDef) => markDef._key === mark));
@@ -8010,7 +7993,7 @@ const normalizeNode = (editor, entry) => {
8010
7993
  /**
8011
7994
  * Remove duplicate markDefs
8012
7995
  */
8013
- if (!editor.isProcessingRemoteChanges && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
7996
+ if (!hasRemoteFrame(editor.applyContext) && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
8014
7997
  let markDefs = node.markDefs ?? [], markDefKeys = /* @__PURE__ */ new Set(), newMarkDefs = [];
8015
7998
  for (let markDef of markDefs) markDefKeys.has(markDef._key) || (markDefKeys.add(markDef._key), newMarkDefs.push(markDef));
8016
7999
  if (markDefs.length !== newMarkDefs.length) {
@@ -8021,7 +8004,7 @@ const normalizeNode = (editor, entry) => {
8021
8004
  /**
8022
8005
  * Remove markDefs not in use
8023
8006
  */
8024
- if (!editor.isProcessingRemoteChanges && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
8007
+ if (!hasRemoteFrame(editor.applyContext) && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
8025
8008
  let newMarkDefs = (node.markDefs || []).filter((def) => node.children.find((child) => isSpan({ schema: editor.snapshot.context.schema }, child) && Array.isArray(child.marks) && child.marks.includes(def._key)));
8026
8009
  if (node.markDefs && !isEqualMarkDefs(newMarkDefs, node.markDefs)) {
8027
8010
  debug.normalization("removing markDef not in use"), applyNodeProperties(editor, { markDefs: newMarkDefs }, path);
@@ -8163,7 +8146,7 @@ const normalizeNode = (editor, entry) => {
8163
8146
  { _key: child._key }
8164
8147
  ];
8165
8148
  if (isSpan({ schema: editor.snapshot.context.schema }, child)) {
8166
- if (prev != null && isSpan({ schema: editor.snapshot.context.schema }, prev) && !editor.isProcessingRemoteChanges) {
8149
+ if (prev != null && isSpan({ schema: editor.snapshot.context.schema }, prev) && !hasRemoteFrame(editor.applyContext)) {
8167
8150
  if (child.text === "") {
8168
8151
  editor.apply({
8169
8152
  type: "unset",
@@ -8257,6 +8240,7 @@ const shouldNormalize = (_editor, { iteration, initialDirtyPathsLength }) => {
8257
8240
  }, createEditor = () => {
8258
8241
  let e = {
8259
8242
  [EDITOR_BRAND]: !0,
8243
+ applyContext: [],
8260
8244
  operations: [],
8261
8245
  operationListeners: {
8262
8246
  before: [],
@@ -8350,13 +8334,25 @@ function collectDescendantIndexes(context, node, nodePath, parent, blockIndexMap
8350
8334
  blockIndexMap.has(childKey) || blockIndexMap.set(childKey, i), collectDescendantIndexes(context, child, childPath, result.parent, blockIndexMap);
8351
8335
  }
8352
8336
  }
8353
- function withRemoteChanges(editor, fn) {
8354
- let prev = editor.isProcessingRemoteChanges;
8355
- editor.isProcessingRemoteChanges = !0, fn(), editor.isProcessingRemoteChanges = prev;
8337
+ function withRemoteChanges(editor, source, fn) {
8338
+ editor.applyContext.push(Object.freeze({
8339
+ kind: "remote",
8340
+ source
8341
+ }));
8342
+ try {
8343
+ fn();
8344
+ } finally {
8345
+ editor.applyContext.pop();
8346
+ }
8356
8347
  }
8357
8348
  function pluginWithoutHistory(editor, fn) {
8358
8349
  let prev = editor.withHistory;
8359
- editor.withHistory = !1, fn(), editor.withHistory = prev;
8350
+ editor.withHistory = !1;
8351
+ try {
8352
+ fn();
8353
+ } finally {
8354
+ editor.withHistory = prev;
8355
+ }
8360
8356
  }
8361
8357
  function cloneDiff(diff2) {
8362
8358
  let [type, patch] = diff2;
@@ -8759,8 +8755,10 @@ function bitap(text, pattern, loc, opts = {}) {
8759
8755
  let charMatch = s[text.charAt(j - 1)];
8760
8756
  if (d === 0 ? rd[j] = (rd[j + 1] << 1 | 1) & charMatch : rd[j] = (rd[j + 1] << 1 | 1) & charMatch | (lastRd[j + 1] | lastRd[j]) << 1 | 1 | lastRd[j + 1], rd[j] & matchmask) {
8761
8757
  let score = getBitapScore(d, j - 1);
8762
- if (score <= scoreThreshold) if (scoreThreshold = score, bestLoc = j - 1, bestLoc > loc) start = Math.max(1, 2 * loc - bestLoc);
8763
- else break;
8758
+ if (score <= scoreThreshold) {
8759
+ if (scoreThreshold = score, bestLoc = j - 1, bestLoc > loc) start = Math.max(1, 2 * loc - bestLoc);
8760
+ else break;
8761
+ }
8764
8762
  }
8765
8763
  }
8766
8764
  if (getBitapScore(d + 1, loc) > scoreThreshold) break;
@@ -9125,7 +9123,7 @@ function setupRemotePatches({ editorActor, subscriptions, editor }) {
9125
9123
  let patches = bufferedPatches;
9126
9124
  bufferedPatches = [];
9127
9125
  let changed = !1;
9128
- withRemoteChanges(editor, () => {
9126
+ withRemoteChanges(editor, "patches", () => {
9129
9127
  withoutNormalizing(editor, () => {
9130
9128
  withoutPatching(editor, () => {
9131
9129
  pluginWithoutHistory(editor, () => {
@@ -9150,10 +9148,10 @@ function setupRemotePatches({ editorActor, subscriptions, editor }) {
9150
9148
  };
9151
9149
  });
9152
9150
  }
9153
- function createUndoSteps({ steps, op, currentUndoStepId, previousUndoStepId, operationsInProgress, isNormalizingNode, selectionBeforeApply }) {
9151
+ function createUndoSteps({ steps, op, currentUndoStepId, previousUndoStepId, operationsInProgress, isInNormalization, selectionBeforeApply }) {
9154
9152
  let lastStep = steps.at(-1);
9155
9153
  if (!lastStep) return createNewStep(steps, op, selectionBeforeApply);
9156
- if (operationsInProgress) return currentUndoStepId === previousUndoStepId || isNormalizingNode ? mergeIntoLastStep(steps, lastStep, op) : createNewStep(steps, op, selectionBeforeApply);
9154
+ if (operationsInProgress) return currentUndoStepId === previousUndoStepId || isInNormalization ? mergeIntoLastStep(steps, lastStep, op) : createNewStep(steps, op, selectionBeforeApply);
9157
9155
  if (op.type === "set.selection" && currentUndoStepId === void 0 && previousUndoStepId !== void 0 || op.type === "set.selection" && currentUndoStepId !== void 0 && previousUndoStepId !== void 0 && previousUndoStepId !== currentUndoStepId) return mergeIntoLastStep(steps, lastStep, op);
9158
9156
  if (currentUndoStepId === void 0 && previousUndoStepId === void 0) {
9159
9157
  if (op.type === "set.selection") return mergeIntoLastStep(steps, lastStep, op);
@@ -9213,7 +9211,7 @@ function subscribeHistory({ editorActor, subscriptions, editor }) {
9213
9211
  subscription.unsubscribe();
9214
9212
  };
9215
9213
  }), subscribeToOperations(editor, (event) => {
9216
- if (editorActor.getSnapshot().matches({ "edit mode": "read only" }) || event.isProcessingRemoteChanges || event.isUndoing || event.isRedoing) return;
9214
+ if (editorActor.getSnapshot().matches({ "edit mode": "read only" }) || hasRemoteFrame(event.context) || event.origin === "undo" || event.origin === "redo") return;
9217
9215
  let currentUndoStepId = event.undoStepId;
9218
9216
  if (!event.withHistory) {
9219
9217
  previousUndoStepId = currentUndoStepId;
@@ -9230,7 +9228,7 @@ function subscribeHistory({ editorActor, subscriptions, editor }) {
9230
9228
  currentUndoStepId,
9231
9229
  previousUndoStepId,
9232
9230
  operationsInProgress: event.operationsInProgress,
9233
- isNormalizingNode: event.isNormalizingNode,
9231
+ isInNormalization: isInNormalization(event.context),
9234
9232
  selectionBeforeApply: event.beforeSelection
9235
9233
  }); editor.history.undos.length > 1e3;) editor.history.undos.shift();
9236
9234
  previousUndoStepId = currentUndoStepId;
@@ -9260,7 +9258,7 @@ function insertNodePatch(operation) {
9260
9258
  function subscribePatchGeneration({ editorActor, editor }) {
9261
9259
  return subscribeToOperations(editor, (event) => {
9262
9260
  if (!event.isPatching) return;
9263
- let operation = event.operation, previousValue = event.beforeValue, patches = [], { initialValue, schema } = editorActor.getSnapshot().context, editorWasEmpty = previousValue.length === 1 && isEqualToEmptyEditor(initialValue, previousValue, schema) && !isEqualValues({ schema }, editor.lastSyncedValue, previousValue), editorIsEmpty = editor.snapshot.context.value.length === 1 && isEqualToEmptyEditor(initialValue, editor.snapshot.context.value, schema) && !isEqualValues({ schema }, editor.lastSyncedValue, editor.snapshot.context.value);
9261
+ let operation = event.operation, previousValue = event.beforeValue, patches = [], { initialValue, schema } = editorActor.getSnapshot().context, editorWasEmpty = previousValue.length === 1 && isEqualToEmptyEditor(initialValue, previousValue, schema) && (editor.valueUnsetEmitted || !isEqualValues({ schema }, editor.lastSyncedValue, previousValue)), editorIsEmpty = editor.snapshot.context.value.length === 1 && isEqualToEmptyEditor(initialValue, editor.snapshot.context.value, schema) && !isEqualValues({ schema }, editor.lastSyncedValue, editor.snapshot.context.value);
9264
9262
  switch (editorWasEmpty && !editorIsEmpty && operation.type !== "set.selection" && patches.push(insert(previousValue, "before", [0])), operation.type) {
9265
9263
  case "insert.text":
9266
9264
  patches = [...patches, ...textPatch(editor.snapshot, operation, previousValue)];
@@ -9280,7 +9278,7 @@ function subscribePatchGeneration({ editorActor, editor }) {
9280
9278
  "set",
9281
9279
  "unset",
9282
9280
  "remove.text"
9283
- ].includes(operation.type) && (patches = [...patches, unset([])]), editorWasEmpty && patches.length > 0 && (patches = [setIfMissing([], []), ...patches]), patches.length > 0) for (let patch of patches) editorActor.send({
9281
+ ].includes(operation.type) && (patches = [...patches, unset([])], editor.valueUnsetEmitted = !0), editorWasEmpty && patches.length > 0 && (patches = [setIfMissing([], []), ...patches], editor.valueUnsetEmitted = !1, isEqualValues({ schema }, editor.lastSyncedValue, previousValue) && (editor.lastSyncedValue = void 0)), patches.length > 0) for (let patch of patches) editorActor.send({
9284
9282
  type: "internal.patch",
9285
9283
  patch: {
9286
9284
  ...patch,
@@ -9670,7 +9668,7 @@ function invalidateVerifiedGroups(groups, operation) {
9670
9668
  */
9671
9669
  function subscribeUpdateValue(context, editor) {
9672
9670
  let unsubscribeNormalizationLog = debug.normalization.enabled ? subscribeToOperations(editor, (event) => {
9673
- event.isNormalizingNode && debug.normalization(`((engine operation))\n${safeStringify(event.operation, 2)}`);
9671
+ isInNormalization(event.context) && debug.normalization(`((engine operation))\n${safeStringify(event.operation, 2)}`);
9674
9672
  }, { phase: "before" }) : void 0, unsubscribeIndexMaps = subscribeToOperations(editor, (event) => {
9675
9673
  let operation = event.operation;
9676
9674
  operation.type !== "set.selection" && operation.type !== "insert.text" && operation.type !== "remove.text" && (transformBlockIndexMap(editor.blockIndexMap, operation, event.beforeValue, editor.snapshot.context.value, {
@@ -9708,7 +9706,7 @@ function createEditorEngine(config) {
9708
9706
  }, editor.containers = /* @__PURE__ */ new Map(), editor.annotations = /* @__PURE__ */ new Map(), editor.blockObjects = /* @__PURE__ */ new Map(), editor.decorators = /* @__PURE__ */ new Map(), editor.inlineObjects = /* @__PURE__ */ new Map(), editor.spans = /* @__PURE__ */ new Map(), editor.textBlocks = /* @__PURE__ */ new Map(), editor.decoratedRanges = [], editor.blockIndexMap = blockIndexMap, editor.history = {
9709
9707
  undos: [],
9710
9708
  redos: []
9711
- }, editor.selectorChannelsPending = { registrations: !1 }, editor.verifiedUniqueChildGroups = /* @__PURE__ */ new Set(), editor.remotePatches = [], editor.undoStepId = void 0, editor.isDeferringMutations = !1, editor.lastSyncedValue = void 0, editor.isNormalizingNode = !1, editor.isPatching = !0, editor.isPerformingBehaviorOperation = !1, editor.isProcessingRemoteChanges = !1, editor.isRedoing = !1, editor.isUndoing = !1, editor.withHistory = !0;
9709
+ }, editor.selectorChannelsPending = { registrations: !1 }, editor.verifiedUniqueChildGroups = /* @__PURE__ */ new Set(), editor.remotePatches = [], editor.undoStepId = void 0, editor.isDeferringMutations = !1, editor.lastSyncedValue = void 0, editor.valueUnsetEmitted = !1, editor.isPatching = !0, editor.isPerformingBehaviorOperation = !1, editor.withHistory = !0;
9712
9710
  let editorEngine = plugins(withDOM(editor), { editorActor: config.editorActor });
9713
9711
  return subscribeUpdateValue(context, editorEngine), subscribePatchGeneration({
9714
9712
  editorActor: config.editorActor,
@@ -10387,9 +10385,9 @@ function isBlockLike(value) {
10387
10385
  * drag origin in a way that would make the drop a no-op.
10388
10386
  *
10389
10387
  * Two expanded selections that only touch at a single endpoint are not treated
10390
- * as a self-drop the drop position covers an adjacent block (typical when
10388
+ * as a self-drop: the drop position covers an adjacent block (typical when
10391
10389
  * dragging a block-object onto the next block via the expanded fallback in
10392
- * `getEventPosition`), and the user genuinely wants the drop to happen.
10390
+ * `getEventPosition`), so the drop should go through.
10393
10391
  *
10394
10392
  * Chrome drags emit a collapsed selection pointing AT the dragged container.
10395
10393
  * A drop position whose path descends into that container is dropping the
@@ -11034,7 +11032,7 @@ const coreListBehaviors = {
11034
11032
  let adjustLevel = !0, listStartBlockFound = !1;
11035
11033
  return [raise$1({
11036
11034
  ...event,
11037
- blocks: event.blocks.map((block) => (block._key === insertedListBlock._key && (listStartBlockFound = !0), adjustLevel ? listStartBlockFound && adjustLevel && isListBlock(snapshot.context, block) ? {
11035
+ blocks: event.blocks.map((block) => (block === insertedListBlock && (listStartBlockFound = !0), adjustLevel ? listStartBlockFound && adjustLevel && isListBlock(snapshot.context, block) ? {
11038
11036
  ...block,
11039
11037
  level: Math.min(10, Math.max(1, block.level + levelDifference))
11040
11038
  } : (listStartBlockFound && (adjustLevel = !1), block) : block))
@@ -11062,7 +11060,7 @@ const coreListBehaviors = {
11062
11060
  let adjustListItem = !0, listStartBlockFound = !1;
11063
11061
  return [raise$1({
11064
11062
  ...event,
11065
- blocks: event.blocks.map((block) => (block._key === insertedListBlock._key && (listStartBlockFound = !0), adjustListItem ? listStartBlockFound && adjustListItem && isListBlock(snapshot.context, block) ? {
11063
+ blocks: event.blocks.map((block) => (block === insertedListBlock && (listStartBlockFound = !0), adjustListItem ? listStartBlockFound && adjustListItem && isListBlock(snapshot.context, block) ? {
11066
11064
  ...block,
11067
11065
  listItem: block.level === insertedListBlock.level ? listItem : block.listItem
11068
11066
  } : (listStartBlockFound && (adjustListItem = !1), block) : block))
@@ -11162,7 +11160,12 @@ function createEditorSnapshot({ converters, editor, keyGenerator, readOnly, sche
11162
11160
  }
11163
11161
  function withPerformingBehaviorOperation(editor, fn) {
11164
11162
  let prev = editor.isPerformingBehaviorOperation;
11165
- editor.isPerformingBehaviorOperation = !0, fn(), editor.isPerformingBehaviorOperation = prev;
11163
+ editor.isPerformingBehaviorOperation = !0;
11164
+ try {
11165
+ fn();
11166
+ } finally {
11167
+ editor.isPerformingBehaviorOperation = prev;
11168
+ }
11166
11169
  }
11167
11170
  function withoutNormalizingConditional(editor, predicate, fn) {
11168
11171
  predicate() ? withoutNormalizing(editor, fn) : fn();
@@ -11176,7 +11179,7 @@ const addAnnotationOperationImplementation = ({ snapshot, operation }) => {
11176
11179
  },
11177
11180
  schema: annotationSchema,
11178
11181
  keyGenerator: context.keyGenerator,
11179
- options: { validateFields: !0 }
11182
+ profile: "strict"
11180
11183
  });
11181
11184
  if (!parsedAnnotation) throw Error(`Failed to parse annotation ${safeStringify(operation.annotation)}`);
11182
11185
  if (!effectiveSelection || isCollapsedRange(effectiveSelection)) return;
@@ -11222,59 +11225,65 @@ function isBeforePath(path, another, root) {
11222
11225
  }
11223
11226
  const removeAnnotationOperationImplementation = ({ snapshot, operation }) => {
11224
11227
  let editor = operation.editor, at = operation.at ? resolveSelection(operation.editor, operation.at) : null, effectiveSelection = at ?? editor.snapshot.context.selection;
11225
- if (effectiveSelection) if (isCollapsedRange(effectiveSelection)) {
11226
- let blockEntry = getParent(snapshot, effectiveSelection.focus.path, { match: (node) => isTextBlock({ schema: editor.snapshot.context.schema }, node) });
11227
- if (!blockEntry) return;
11228
- let { node: block, path: blockPath } = blockEntry, potentialAnnotations = (block.markDefs ?? []).filter((markDef) => markDef._type === operation.annotation.name), selectedChildEntry = getNode(editor.snapshot, effectiveSelection.focus.path);
11229
- if (!selectedChildEntry) return;
11230
- let { node: selectedChild, path: selectedChildPath } = selectedChildEntry;
11231
- if (!isSpan({ schema: editor.snapshot.context.schema }, selectedChild)) return;
11232
- let annotationToRemove = selectedChild.marks?.find((mark) => potentialAnnotations.some((markDef) => markDef._key === mark));
11233
- if (!annotationToRemove) return;
11234
- let previousSpansWithSameAnnotation = [], reversedChildren = getChildren(editor.snapshot, blockPath);
11235
- for (let index = reversedChildren.length - 1; index >= 0; index--) {
11236
- let entry = reversedChildren[index];
11237
- if (!entry) continue;
11238
- let { node: child, path: childPath } = entry;
11239
- if (isSpan({ schema: editor.snapshot.context.schema }, child) && isBeforePath(childPath, selectedChildPath, editor.snapshot.context)) if (child.marks?.includes(annotationToRemove)) previousSpansWithSameAnnotation.push([child, childPath]);
11240
- else break;
11241
- }
11242
- let nextSpansWithSameAnnotation = [];
11243
- for (let { node: child, path: childPath } of getChildren(editor.snapshot, blockPath)) if (isSpan({ schema: editor.snapshot.context.schema }, child) && isAfterPath(childPath, selectedChildPath, editor.snapshot.context)) if (child.marks?.includes(annotationToRemove)) nextSpansWithSameAnnotation.push([child, childPath]);
11244
- else break;
11245
- for (let [child, childPath] of [
11246
- ...previousSpansWithSameAnnotation,
11247
- [selectedChild, selectedChildPath],
11248
- ...nextSpansWithSameAnnotation
11249
- ]) applyNodeProperties(editor, { marks: child.marks?.filter((mark) => mark !== annotationToRemove) }, childPath);
11250
- } else {
11251
- let ref = at ? rangeRef(editor, at, { affinity: "inward" }) : null;
11252
- withoutNormalizing(editor, () => {
11253
- let splitRange = at ?? editor.snapshot.context.selection;
11254
- if (splitRange && isRange(splitRange)) {
11255
- let splitLeaf = getNode(editor.snapshot, splitRange.anchor.path)?.node;
11256
- if (!(splitLeaf && isCollapsedRange(splitRange) && isSpan({ schema: editor.snapshot.context.schema }, splitLeaf) && splitLeaf.text.length > 0)) {
11257
- let splitRangeRef = rangeRef(editor, splitRange, { affinity: "inward" }), [splitStart, splitEnd] = rangeEdges(splitRange, editor.snapshot.context);
11258
- (!isEnd(editor, splitEnd, splitEnd.path) || !isEdge(editor, splitEnd, splitEnd.path)) && applySplitNode(editor, splitEnd.path, splitEnd.offset), (!isStart(editor, splitStart, splitStart.path) || !isEdge(editor, splitStart, splitStart.path)) && applySplitNode(editor, splitStart.path, splitStart.offset);
11259
- let updatedSplitRange = splitRangeRef.unref();
11260
- !at && updatedSplitRange && applySelect(editor, updatedSplitRange);
11228
+ if (effectiveSelection) {
11229
+ if (isCollapsedRange(effectiveSelection)) {
11230
+ let blockEntry = getParent(snapshot, effectiveSelection.focus.path, { match: (node) => isTextBlock({ schema: editor.snapshot.context.schema }, node) });
11231
+ if (!blockEntry) return;
11232
+ let { node: block, path: blockPath } = blockEntry, potentialAnnotations = (block.markDefs ?? []).filter((markDef) => markDef._type === operation.annotation.name), selectedChildEntry = getNode(editor.snapshot, effectiveSelection.focus.path);
11233
+ if (!selectedChildEntry) return;
11234
+ let { node: selectedChild, path: selectedChildPath } = selectedChildEntry;
11235
+ if (!isSpan({ schema: editor.snapshot.context.schema }, selectedChild)) return;
11236
+ let annotationToRemove = selectedChild.marks?.find((mark) => potentialAnnotations.some((markDef) => markDef._key === mark));
11237
+ if (!annotationToRemove) return;
11238
+ let previousSpansWithSameAnnotation = [], reversedChildren = getChildren(editor.snapshot, blockPath);
11239
+ for (let index = reversedChildren.length - 1; index >= 0; index--) {
11240
+ let entry = reversedChildren[index];
11241
+ if (!entry) continue;
11242
+ let { node: child, path: childPath } = entry;
11243
+ if (isSpan({ schema: editor.snapshot.context.schema }, child) && isBeforePath(childPath, selectedChildPath, editor.snapshot.context)) {
11244
+ if (child.marks?.includes(annotationToRemove)) previousSpansWithSameAnnotation.push([child, childPath]);
11245
+ else break;
11261
11246
  }
11262
11247
  }
11263
- let blocks = Array.from(getNodes(editor.snapshot, {
11264
- from: rangeStart(effectiveSelection, editor.snapshot.context).path,
11265
- to: rangeEnd(effectiveSelection, editor.snapshot.context).path,
11266
- match: (node) => isTextBlock({ schema: editor.snapshot.context.schema }, node)
11267
- })), selectionRange = ref?.current ?? editor.snapshot.context.selection;
11268
- for (let { node: block, path: blockPath } of blocks) {
11269
- if (!isTextBlock({ schema: editor.snapshot.context.schema }, block)) continue;
11270
- let children = getChildren(editor.snapshot, blockPath);
11271
- for (let { node: child, path: childPath } of children) {
11272
- if (!isSpan({ schema: editor.snapshot.context.schema }, child) || !selectionRange || !rangeIntersects(editor.snapshot, selectionRange, childPath)) continue;
11273
- let markDefs = block.markDefs ?? [], marks = child.marks ?? [], marksWithoutAnnotation = marks.filter((mark) => markDefs.find((markDef) => markDef._key === mark)?._type !== operation.annotation.name);
11274
- marksWithoutAnnotation.length !== marks.length && applyNodeProperties(editor, { marks: marksWithoutAnnotation }, childPath);
11275
- }
11248
+ let nextSpansWithSameAnnotation = [];
11249
+ for (let { node: child, path: childPath } of getChildren(editor.snapshot, blockPath)) if (isSpan({ schema: editor.snapshot.context.schema }, child) && isAfterPath(childPath, selectedChildPath, editor.snapshot.context)) {
11250
+ if (child.marks?.includes(annotationToRemove)) nextSpansWithSameAnnotation.push([child, childPath]);
11251
+ else break;
11276
11252
  }
11277
- }), ref?.unref();
11253
+ for (let [child, childPath] of [
11254
+ ...previousSpansWithSameAnnotation,
11255
+ [selectedChild, selectedChildPath],
11256
+ ...nextSpansWithSameAnnotation
11257
+ ]) applyNodeProperties(editor, { marks: child.marks?.filter((mark) => mark !== annotationToRemove) }, childPath);
11258
+ } else {
11259
+ let ref = at ? rangeRef(editor, at, { affinity: "inward" }) : null;
11260
+ withoutNormalizing(editor, () => {
11261
+ let splitRange = at ?? editor.snapshot.context.selection;
11262
+ if (splitRange && isRange(splitRange)) {
11263
+ let splitLeaf = getNode(editor.snapshot, splitRange.anchor.path)?.node;
11264
+ if (!(splitLeaf && isCollapsedRange(splitRange) && isSpan({ schema: editor.snapshot.context.schema }, splitLeaf) && splitLeaf.text.length > 0)) {
11265
+ let splitRangeRef = rangeRef(editor, splitRange, { affinity: "inward" }), [splitStart, splitEnd] = rangeEdges(splitRange, editor.snapshot.context);
11266
+ (!isEnd(editor, splitEnd, splitEnd.path) || !isEdge(editor, splitEnd, splitEnd.path)) && applySplitNode(editor, splitEnd.path, splitEnd.offset), (!isStart(editor, splitStart, splitStart.path) || !isEdge(editor, splitStart, splitStart.path)) && applySplitNode(editor, splitStart.path, splitStart.offset);
11267
+ let updatedSplitRange = splitRangeRef.unref();
11268
+ !at && updatedSplitRange && applySelect(editor, updatedSplitRange);
11269
+ }
11270
+ }
11271
+ let blocks = Array.from(getNodes(editor.snapshot, {
11272
+ from: rangeStart(effectiveSelection, editor.snapshot.context).path,
11273
+ to: rangeEnd(effectiveSelection, editor.snapshot.context).path,
11274
+ match: (node) => isTextBlock({ schema: editor.snapshot.context.schema }, node)
11275
+ })), selectionRange = ref?.current ?? editor.snapshot.context.selection;
11276
+ for (let { node: block, path: blockPath } of blocks) {
11277
+ if (!isTextBlock({ schema: editor.snapshot.context.schema }, block)) continue;
11278
+ let children = getChildren(editor.snapshot, blockPath);
11279
+ for (let { node: child, path: childPath } of children) {
11280
+ if (!isSpan({ schema: editor.snapshot.context.schema }, child) || !selectionRange || !rangeIntersects(editor.snapshot, selectionRange, childPath)) continue;
11281
+ let markDefs = block.markDefs ?? [], marks = child.marks ?? [], marksWithoutAnnotation = marks.filter((mark) => markDefs.find((markDef) => markDef._key === mark)?._type !== operation.annotation.name);
11282
+ marksWithoutAnnotation.length !== marks.length && applyNodeProperties(editor, { marks: marksWithoutAnnotation }, childPath);
11283
+ }
11284
+ }
11285
+ }), ref?.unref();
11286
+ }
11278
11287
  }
11279
11288
  };
11280
11289
  /**
@@ -11326,7 +11335,7 @@ const blockSetOperationImplementation = ({ snapshot, operation }) => {
11326
11335
  let { markDefs } = parseMarkDefs({
11327
11336
  keyGenerator: context.keyGenerator,
11328
11337
  markDefs: operation.props[key],
11329
- options: { validateFields: !0 },
11338
+ profile: "strict",
11330
11339
  schema: getPathSubSchema(snapshot, blockEntry.path)
11331
11340
  });
11332
11341
  filteredProps[key] = markDefs;
@@ -12350,8 +12359,12 @@ const deleteOperationImplementation = ({ operation }) => {
12350
12359
  });
12351
12360
  };
12352
12361
  function pluginRedoing(editor, fn) {
12353
- let prev = editor.isRedoing;
12354
- editor.isRedoing = !0, fn(), editor.isRedoing = prev;
12362
+ editor.applyContext.push(Object.freeze({ kind: "redo" }));
12363
+ try {
12364
+ fn();
12365
+ } finally {
12366
+ editor.applyContext.pop();
12367
+ }
12355
12368
  }
12356
12369
  /**
12357
12370
  * This will adjust the operation paths and offsets according to the
@@ -12421,7 +12434,7 @@ const historyRedoOperationImplementation = ({ operation }) => {
12421
12434
  console.error(`Could not perform 'history.redo' operation: ${err instanceof Error ? err.message : err}`), editor.remotePatches.splice(0, editor.remotePatches.length), applyDeselect(editor), editor.history = {
12422
12435
  undos: [],
12423
12436
  redos: []
12424
- }, editor.withHistory = !0, editor.isRedoing = !1, editor.onChange();
12437
+ }, editor.onChange();
12425
12438
  return;
12426
12439
  }
12427
12440
  editor.history.undos.push(step), editor.history.redos.pop();
@@ -12429,8 +12442,12 @@ const historyRedoOperationImplementation = ({ operation }) => {
12429
12442
  }
12430
12443
  };
12431
12444
  function pluginUndoing(editor, fn) {
12432
- let prev = editor.isUndoing;
12433
- editor.isUndoing = !0, fn(), editor.isUndoing = prev;
12445
+ editor.applyContext.push(Object.freeze({ kind: "undo" }));
12446
+ try {
12447
+ fn();
12448
+ } finally {
12449
+ editor.applyContext.pop();
12450
+ }
12434
12451
  }
12435
12452
  function inverseOperation(op) {
12436
12453
  switch (op.type) {
@@ -12526,7 +12543,7 @@ const historyUndoOperationImplementation = ({ operation }) => {
12526
12543
  console.error(`Could not perform 'history.undo' operation: ${err instanceof Error ? err.message : err}`), editor.remotePatches.splice(0, editor.remotePatches.length), applyDeselect(editor), editor.history = {
12527
12544
  undos: [],
12528
12545
  redos: []
12529
- }, editor.withHistory = !0, editor.isUndoing = !1, editor.onChange();
12546
+ }, editor.onChange();
12530
12547
  return;
12531
12548
  }
12532
12549
  editor.history.redos.push(step), editor.history.undos.pop();
@@ -12543,11 +12560,7 @@ const historyUndoOperationImplementation = ({ operation }) => {
12543
12560
  let { context } = snapshot, editor = operation.editor, resolved = operation.at ? resolveSelection(editor, operation.at) : resolveSelection(editor, editor.snapshot.context.selection), at = resolved && operation.at && operation.placement !== "auto" ? operation.at : resolved, destinationPath = at ? operation.placement === "before" ? rangeStart(at, editor.snapshot.context).path : rangeEnd(at, editor.snapshot.context).path : editor.snapshot.context.value.length > 0 ? end(editor, []).path : void 0, schema = destinationPath ? getPathSubSchema(snapshot, destinationPath) : context.schema, parsedBlock = parseBlock({
12544
12561
  block: operation.block,
12545
12562
  keyGenerator: context.keyGenerator,
12546
- options: {
12547
- normalize: !0,
12548
- removeUnusedMarkDefs: !0,
12549
- validateFields: !0
12550
- },
12563
+ profile: "strict",
12551
12564
  schema
12552
12565
  });
12553
12566
  if (!parsedBlock) return;
@@ -12947,13 +12960,11 @@ const insertChildOperationImplementation = ({ snapshot, operation }) => {
12947
12960
  ...focusBlockEntry.path,
12948
12961
  "children",
12949
12962
  focusChildSegment
12950
- ], markDefs = focusBlock.markDefs ?? [], markDefKeyMap = /* @__PURE__ */ new Map();
12951
- for (let markDef of markDefs) markDefKeyMap.set(markDef._key, markDef._key);
12952
- let schema = getPathSubSchema(snapshot, focusBlockEntry.path), span = parseSpan({
12963
+ ], markDefs = focusBlock.markDefs ?? [], markDefKeys = new Set(markDefs.map((markDef) => markDef._key)), schema = getPathSubSchema(snapshot, focusBlockEntry.path), span = parseSpan({
12953
12964
  span: operation.child,
12954
12965
  keyGenerator: context.keyGenerator,
12955
- markDefKeyMap,
12956
- options: { validateFields: !0 },
12966
+ markDefKeys,
12967
+ profile: "strict",
12957
12968
  schema
12958
12969
  });
12959
12970
  if (span) {
@@ -12974,7 +12985,7 @@ const insertChildOperationImplementation = ({ snapshot, operation }) => {
12974
12985
  let inlineObject = parseInlineObject({
12975
12986
  inlineObject: operation.child,
12976
12987
  keyGenerator: context.keyGenerator,
12977
- options: { validateFields: !0 },
12988
+ profile: "strict",
12978
12989
  schema
12979
12990
  });
12980
12991
  if (inlineObject) {
@@ -13014,12 +13025,13 @@ const insertChildOperationImplementation = ({ snapshot, operation }) => {
13014
13025
  let node = nodeEntry.node;
13015
13026
  if (isLeafObject(editor.snapshot, node, nodeEntry.path)) {
13016
13027
  let nextSibling = getSibling(editor.snapshot, nodeEntry.path, { direction: "next" });
13017
- if (nextSibling) if (getSpan(editor.snapshot, nextSibling.path)) path = nextSibling.path, offset = 0, applySelect(editor, {
13018
- path,
13019
- offset
13020
- });
13021
- else return;
13022
- else return;
13028
+ if (nextSibling) {
13029
+ if (getSpan(editor.snapshot, nextSibling.path)) path = nextSibling.path, offset = 0, applySelect(editor, {
13030
+ path,
13031
+ offset
13032
+ });
13033
+ else return;
13034
+ } else return;
13023
13035
  }
13024
13036
  operation.text.length > 0 && editor.apply({
13025
13037
  type: "insert.text",
@@ -13066,7 +13078,14 @@ const moveBackwardOperationImplementation = ({ operation }) => {
13066
13078
  if (newSelection) {
13067
13079
  let anchorContainer = getContainer(operation.editor.snapshot, newSelection.anchor.path), focusContainer = getContainer(operation.editor.snapshot, newSelection.focus.path), containers = anchorContainer ? [anchorContainer] : [];
13068
13080
  focusContainer && focusContainer.node !== anchorContainer?.node && containers.push(focusContainer), containers.length > 0 && (withoutNormalizing(operation.editor, () => {
13069
- for (let entry of containers) operation.editor.isNormalizingNode = !0, operation.editor.normalizeNode([entry.node, entry.path]), operation.editor.isNormalizingNode = !1;
13081
+ for (let entry of containers) {
13082
+ operation.editor.applyContext.push(Object.freeze({ kind: "normalization" }));
13083
+ try {
13084
+ operation.editor.normalizeNode([entry.node, entry.path]);
13085
+ } finally {
13086
+ operation.editor.applyContext.pop();
13087
+ }
13088
+ }
13070
13089
  }), newSelection = resolveSelection(operation.editor, operation.at));
13071
13090
  }
13072
13091
  newSelection ? applySelect(operation.editor, newSelection) : applyDeselect(operation.editor), operation.editor.focused && operation.editor.snapshot.context.readOnly && (operation.editor.focused = !1);
@@ -14444,11 +14463,7 @@ const abstractInsertBehaviors = [
14444
14463
  endPoint: blockEndPoint
14445
14464
  }),
14446
14465
  keyGenerator: snapshot.context.keyGenerator,
14447
- options: {
14448
- normalize: !1,
14449
- removeUnusedMarkDefs: !0,
14450
- validateFields: !1
14451
- },
14466
+ profile: "lenient",
14452
14467
  schema: getPathSubSchema(snapshot, focusTextBlock.path)
14453
14468
  });
14454
14469
  return newTextBlock ? {
@@ -15264,7 +15279,7 @@ const editorMachine = setup({
15264
15279
  },
15265
15280
  guards: {
15266
15281
  "engine is busy": ({ context }) => context.editorEngine ? context.editorEngine.operations.length > 0 : !1,
15267
- "engine is normalizing node": ({ context }) => context.editorEngine ? context.editorEngine.isNormalizingNode : !1
15282
+ "engine is normalizing node": ({ context }) => context.editorEngine ? isInNormalization(context.editorEngine.applyContext) : !1
15268
15283
  }
15269
15284
  }).createMachine({
15270
15285
  id: "editor",
@@ -15976,7 +15991,7 @@ const syncValueCallback = ({ sendBack, input }) => {
15976
15991
  "clear pending value": assign({ pendingValue: void 0 }),
15977
15992
  "assign previous value": assign({ previousValue: ({ event }) => (assertEvent(event, "done syncing"), event.value) }),
15978
15993
  "record synced value on engine": ({ context, event }) => {
15979
- assertEvent(event, "done syncing"), context.editorEngine.lastSyncedValue = event.value;
15994
+ assertEvent(event, "done syncing"), event.changed && (context.editorEngine.lastSyncedValue = event.value);
15980
15995
  },
15981
15996
  "emit done syncing value": emit({ type: "done syncing value" }),
15982
15997
  "emit syncing value": emit({ type: "syncing value" })
@@ -15984,11 +15999,11 @@ const syncValueCallback = ({ sendBack, input }) => {
15984
15999
  guards: {
15985
16000
  "initial value synced": ({ context }) => context.initialValueSynced,
15986
16001
  "is busy": ({ context }) => {
15987
- let isBusy = context.editorEngine.isDeferringMutations || context.editorEngine.isProcessingRemoteChanges;
16002
+ let isBusy = context.editorEngine.isDeferringMutations || hasRemoteFrame(context.editorEngine.applyContext);
15988
16003
  return debug.syncValue(safeStringify({
15989
16004
  isBusy,
15990
16005
  isDeferringMutations: context.editorEngine.isDeferringMutations,
15991
- isProcessingRemoteChanges: context.editorEngine.isProcessingRemoteChanges
16006
+ hasRemoteFrame: hasRemoteFrame(context.editorEngine.applyContext)
15992
16007
  })), isBusy;
15993
16008
  },
15994
16009
  "is empty value": ({ event }) => event.type === "update value" && event.value === void 0,
@@ -16138,59 +16153,67 @@ const syncValueCallback = ({ sendBack, input }) => {
16138
16153
  }
16139
16154
  });
16140
16155
  async function updateValue({ context, sendBack, editorEngine, streamBlocks, value }) {
16141
- let doneSyncing = !1, isChanged = !1, isValid = !0, hadSelection = !!editorEngine.snapshot.context.selection;
16156
+ let doneSyncing = !1, isChanged = !1, isValid = !0, hadSelection = !!editorEngine.snapshot.context.selection, remoteSource = streamBlocks ? "initial-sync" : "update-value";
16142
16157
  if ((!value || value.length === 0) && (clearEditor({
16143
16158
  editorEngine,
16144
- doneSyncing
16145
- }), isChanged = !0), value && value.length > 0) if (streamBlocks) await new Promise((resolve) => {
16146
- if (doneSyncing) {
16147
- resolve();
16148
- return;
16149
- }
16150
- isChanged = removeExtraBlocks({
16151
- editorEngine,
16152
- value
16159
+ doneSyncing,
16160
+ remoteSource
16161
+ }), isChanged = !0), value && value.length > 0) {
16162
+ if (streamBlocks) await new Promise((resolve) => {
16163
+ if (doneSyncing) {
16164
+ resolve();
16165
+ return;
16166
+ }
16167
+ isChanged = removeExtraBlocks({
16168
+ editorEngine,
16169
+ value,
16170
+ remoteSource
16171
+ });
16172
+ let processBlocks = async () => {
16173
+ for await (let [currentBlock, currentBlockIndex] of getStreamedBlocks({ value })) {
16174
+ let { blockChanged, blockValid } = syncBlock({
16175
+ context,
16176
+ sendBack,
16177
+ block: currentBlock,
16178
+ index: currentBlockIndex,
16179
+ editorEngine,
16180
+ value,
16181
+ remoteSource
16182
+ });
16183
+ if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !isValid) break;
16184
+ }
16185
+ resolve();
16186
+ };
16187
+ processBlocks();
16153
16188
  });
16154
- let processBlocks = async () => {
16155
- for await (let [currentBlock, currentBlockIndex] of getStreamedBlocks({ value })) {
16189
+ else {
16190
+ if (doneSyncing) return;
16191
+ isChanged = removeExtraBlocks({
16192
+ editorEngine,
16193
+ value,
16194
+ remoteSource
16195
+ });
16196
+ let index = 0;
16197
+ for (let block of value) {
16156
16198
  let { blockChanged, blockValid } = syncBlock({
16157
16199
  context,
16158
16200
  sendBack,
16159
- block: currentBlock,
16160
- index: currentBlockIndex,
16201
+ block,
16202
+ index,
16161
16203
  editorEngine,
16162
- value
16204
+ value,
16205
+ remoteSource
16163
16206
  });
16164
- if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !isValid) break;
16207
+ if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !blockValid) break;
16208
+ index++;
16165
16209
  }
16166
- resolve();
16167
- };
16168
- processBlocks();
16169
- });
16170
- else {
16171
- if (doneSyncing) return;
16172
- isChanged = removeExtraBlocks({
16173
- editorEngine,
16174
- value
16175
- });
16176
- let index = 0;
16177
- for (let block of value) {
16178
- let { blockChanged, blockValid } = syncBlock({
16179
- context,
16180
- sendBack,
16181
- block,
16182
- index,
16183
- editorEngine,
16184
- value
16185
- });
16186
- if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !blockValid) break;
16187
- index++;
16188
16210
  }
16189
16211
  }
16190
16212
  if (!isValid) {
16191
16213
  debug.syncValue("Invalid value, returning"), doneSyncing = !0, sendBack({
16192
16214
  type: "done syncing",
16193
- value
16215
+ value,
16216
+ changed: isChanged
16194
16217
  });
16195
16218
  return;
16196
16219
  }
@@ -16205,7 +16228,8 @@ async function updateValue({ context, sendBack, editorEngine, streamBlocks, valu
16205
16228
  value
16206
16229
  }), doneSyncing = !0, sendBack({
16207
16230
  type: "done syncing",
16208
- value
16231
+ value,
16232
+ changed: isChanged
16209
16233
  });
16210
16234
  return;
16211
16235
  }
@@ -16216,7 +16240,8 @@ async function updateValue({ context, sendBack, editorEngine, streamBlocks, valu
16216
16240
  } else debug.syncValue("remote value and local value are equal, no need to sync");
16217
16241
  doneSyncing = !0, sendBack({
16218
16242
  type: "done syncing",
16219
- value
16243
+ value,
16244
+ changed: isChanged
16220
16245
  });
16221
16246
  }
16222
16247
  async function* getStreamedBlocks({ value }) {
@@ -16226,8 +16251,8 @@ async function* getStreamedBlocks({ value }) {
16226
16251
  /**
16227
16252
  * Unsets every block; normalization then inserts the empty placeholder block.
16228
16253
  */
16229
- function clearEditor({ editorEngine, doneSyncing }) {
16230
- withRemoteChanges(editorEngine, () => {
16254
+ function clearEditor({ editorEngine, doneSyncing, remoteSource }) {
16255
+ withRemoteChanges(editorEngine, remoteSource, () => {
16231
16256
  withoutNormalizing(editorEngine, () => {
16232
16257
  pluginWithoutHistory(editorEngine, () => {
16233
16258
  withoutPatching(editorEngine, () => {
@@ -16249,9 +16274,9 @@ function clearEditor({ editorEngine, doneSyncing }) {
16249
16274
  * Compare the length of the value and the length of the editor's children, and
16250
16275
  * remove blocks that have become superfluous
16251
16276
  */
16252
- function removeExtraBlocks({ editorEngine, value }) {
16277
+ function removeExtraBlocks({ editorEngine, value, remoteSource }) {
16253
16278
  let isChanged = !1;
16254
- return withRemoteChanges(editorEngine, () => {
16279
+ return withRemoteChanges(editorEngine, remoteSource, () => {
16255
16280
  withoutNormalizing(editorEngine, () => {
16256
16281
  withoutPatching(editorEngine, () => {
16257
16282
  let childrenLength = editorEngine.snapshot.context.value.length;
@@ -16269,13 +16294,13 @@ function removeExtraBlocks({ editorEngine, value }) {
16269
16294
  });
16270
16295
  }), isChanged;
16271
16296
  }
16272
- function syncBlock({ context, sendBack, block, index, editorEngine, value }) {
16297
+ function syncBlock({ context, sendBack, block, index, editorEngine, value, remoteSource }) {
16273
16298
  let oldEngineBlock = editorEngine.snapshot.context.value.at(index), oldBlock = editorEngine.snapshot.context.value.at(index);
16274
16299
  if (!oldEngineBlock || !oldBlock) {
16275
16300
  let validation = validateValue([block], context.schema, context.keyGenerator);
16276
16301
  if (debug.syncValue("Validating and inserting new block in the end of the value", block), validation.valid || validation.resolution?.autoResolve) {
16277
16302
  let engineBlock = toEngineBlock(applyAutoResolution(validation, [block], block), { schemaTypes: context.schema });
16278
- return withRemoteChanges(editorEngine, () => {
16303
+ return withRemoteChanges(editorEngine, remoteSource, () => {
16279
16304
  withoutNormalizing(editorEngine, () => {
16280
16305
  withoutPatching(editorEngine, () => {
16281
16306
  editorEngine.apply({
@@ -16317,7 +16342,7 @@ function syncBlock({ context, sendBack, block, index, editorEngine, value }) {
16317
16342
  });
16318
16343
  })), validation.valid || validation.resolution?.autoResolve) {
16319
16344
  let repairedBlock = applyAutoResolution(validation, validationValue, block);
16320
- return oldBlock._key === block._key && oldBlock._type === block._type ? (debug.syncValue("Updating block", oldBlock, repairedBlock), withRemoteChanges(editorEngine, () => {
16345
+ return oldBlock._key === block._key && oldBlock._type === block._type ? (debug.syncValue("Updating block", oldBlock, repairedBlock), withRemoteChanges(editorEngine, remoteSource, () => {
16321
16346
  withoutNormalizing(editorEngine, () => {
16322
16347
  withoutPatching(editorEngine, () => {
16323
16348
  updateBlock({
@@ -16329,7 +16354,7 @@ function syncBlock({ context, sendBack, block, index, editorEngine, value }) {
16329
16354
  });
16330
16355
  });
16331
16356
  });
16332
- })) : (debug.syncValue("Replacing block", oldBlock, repairedBlock), withRemoteChanges(editorEngine, () => {
16357
+ })) : (debug.syncValue("Replacing block", oldBlock, repairedBlock), withRemoteChanges(editorEngine, remoteSource, () => {
16333
16358
  withoutNormalizing(editorEngine, () => {
16334
16359
  withoutPatching(editorEngine, () => {
16335
16360
  replaceBlock({
@@ -16627,7 +16652,7 @@ function createActors(config) {
16627
16652
  isPublicOperation(event.operation) && config.relay.send({
16628
16653
  type: "operation",
16629
16654
  operation: event.operation,
16630
- origin: event.origin === "remote" ? "remote" : "local"
16655
+ origin: hasRemoteFrame(event.context) ? "remote" : "local"
16631
16656
  });
16632
16657
  })), config.subscriptions.push(() => {
16633
16658
  let subscription = syncActor.on("*", (event) => {