@portabletext/editor 8.1.2 → 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 (33) hide show
  1. package/lib/{behavior.types.action-C0XDEQnB.d.ts → behavior.types.action-DbwK30_J.d.ts} +52 -25
  2. package/lib/behavior.types.action-DbwK30_J.d.ts.map +1 -0
  3. package/lib/behaviors/index.d.ts +1 -1
  4. package/lib/{get-container-D2pN5Npr.js → get-container-CXdmRdiX.js} +3 -3
  5. package/lib/{get-container-D2pN5Npr.js.map → get-container-CXdmRdiX.js.map} +1 -1
  6. package/lib/{get-parent-DgaKcy8-.js → get-parent-BLzi7eLr.js} +39 -14
  7. package/lib/get-parent-BLzi7eLr.js.map +1 -0
  8. package/lib/{get-path-sub-schema-Dd0QYZ0m.js → get-path-sub-schema-DsN1qF_l.js} +9 -5
  9. package/lib/get-path-sub-schema-DsN1qF_l.js.map +1 -0
  10. package/lib/index.d.ts +1 -1
  11. package/lib/index.js +227 -215
  12. package/lib/index.js.map +1 -1
  13. package/lib/plugins/index.d.ts +1 -1
  14. package/lib/{selector.is-selecting-entire-blocks-BFhnnkHf.js → selector.is-selecting-entire-blocks-BHVYIXbI.js} +8 -5
  15. package/lib/selector.is-selecting-entire-blocks-BHVYIXbI.js.map +1 -0
  16. package/lib/selectors/index.d.ts +1 -1
  17. package/lib/selectors/index.js +4 -4
  18. package/lib/traversal/index.d.ts +9 -6
  19. package/lib/traversal/index.d.ts.map +1 -1
  20. package/lib/traversal/index.js +3 -3
  21. package/lib/{util.is-equal-selections-BdK98okY.js → util.is-equal-selections-sCQib0IC.js} +2 -2
  22. package/lib/{util.is-equal-selections-BdK98okY.js.map → util.is-equal-selections-sCQib0IC.js.map} +1 -1
  23. package/lib/{util.slice-blocks-_ElaB53f.js → util.slice-blocks-B-iKFEG7.js} +43 -56
  24. package/lib/util.slice-blocks-B-iKFEG7.js.map +1 -0
  25. package/lib/utils/index.d.ts +1 -1
  26. package/lib/utils/index.js +4 -8
  27. package/lib/utils/index.js.map +1 -1
  28. package/package.json +1 -1
  29. package/lib/behavior.types.action-C0XDEQnB.d.ts.map +0 -1
  30. package/lib/get-parent-DgaKcy8-.js.map +0 -1
  31. package/lib/get-path-sub-schema-Dd0QYZ0m.js.map +0 -1
  32. package/lib/selector.is-selecting-entire-blocks-BFhnnkHf.js.map +0 -1
  33. 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";
@@ -748,6 +748,36 @@ function move(editor, options = {}) {
748
748
  }
749
749
  editor.setSelection(props);
750
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
+ }
751
781
  function subscribeToOperations(editor, listener, options) {
752
782
  let phase = options?.phase ?? "after";
753
783
  return editor.operationListeners[phase] = [...editor.operationListeners[phase], listener], () => {
@@ -763,20 +793,16 @@ function subscribeToOperations(editor, listener, options) {
763
793
  * the apply.
764
794
  */
765
795
  function createOperationEvent(editor, operation) {
766
- let isNormalizingNode = !!editor.isNormalizingNode, isProcessingRemoteChanges = !!editor.isProcessingRemoteChanges, isUndoing = !!editor.isUndoing, isRedoing = !!editor.isRedoing;
767
796
  return {
768
797
  operation,
769
798
  beforeValue: editor.snapshot.context.value,
770
799
  beforeSelection: editor.snapshot.context.selection,
771
800
  operationsInProgress: editor.operations.length > 0,
772
- isNormalizingNode,
773
801
  isPatching: !!editor.isPatching,
774
- isProcessingRemoteChanges,
775
- isUndoing,
776
- isRedoing,
777
802
  withHistory: !!editor.withHistory,
778
803
  undoStepId: editor.undoStepId,
779
- origin: isProcessingRemoteChanges ? "remote" : isUndoing ? "undo" : isRedoing ? "redo" : isNormalizingNode ? "normalization" : "local"
804
+ origin: getOrigin(editor.applyContext),
805
+ context: Object.freeze([...editor.applyContext])
780
806
  };
781
807
  }
782
808
  function emitOperationEvent(listeners, event) {
@@ -4205,7 +4231,7 @@ const engineOperationCallback = ({ input, sendBack }) => subscribeToOperations(i
4205
4231
  event.operation.type !== "set.selection" && sendBack({
4206
4232
  type: "engine operation",
4207
4233
  operation: event.operation,
4208
- origin: event.origin
4234
+ origin: hasRemoteFrame(event.context) ? "remote" : "local"
4209
4235
  });
4210
4236
  }, { phase: "before" });
4211
4237
  function mergeRangeDecoration(leaf, decoration) {
@@ -4268,7 +4294,7 @@ const rangeDecorationsMachine = setup({
4268
4294
  decoratedRange.rangeDecoration.onMoved?.({
4269
4295
  newSelection: null,
4270
4296
  rangeDecoration: decoratedRange.rangeDecoration,
4271
- origin: event.origin === "remote" ? "remote" : "local"
4297
+ origin: event.origin
4272
4298
  });
4273
4299
  continue;
4274
4300
  }
@@ -4276,7 +4302,7 @@ const rangeDecorationsMachine = setup({
4276
4302
  (newRange && newRange !== currentSelection || newRange === null && currentSelection) && decoratedRange.rangeDecoration.onMoved?.({
4277
4303
  newSelection: newRange,
4278
4304
  rangeDecoration: decoratedRange.rangeDecoration,
4279
- origin: event.origin === "remote" ? "remote" : "local"
4305
+ origin: event.origin
4280
4306
  }), newRange !== null && rangeDecorationState.push({
4281
4307
  ...newRange || currentSelection,
4282
4308
  rangeDecoration: {
@@ -5469,16 +5495,7 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5469
5495
  type: "behavior event",
5470
5496
  behaviorEvent: {
5471
5497
  type: "insert.blocks",
5472
- blocks: parseBlocks({
5473
- keyGenerator: editorEngine.snapshot.context.keyGenerator,
5474
- schema: editorEngine.snapshot.context.schema,
5475
- blocks: result_1.insert,
5476
- options: {
5477
- normalize: !1,
5478
- removeUnusedMarkDefs: !0,
5479
- validateFields: !1
5480
- }
5481
- }),
5498
+ blocks: result_1.insert,
5482
5499
  placement: "auto"
5483
5500
  },
5484
5501
  editor: editorEngine
@@ -5915,11 +5932,7 @@ const converterJson = defineConverter({
5915
5932
  let parsedBlock = parseBlock({
5916
5933
  keyGenerator: snapshot.context.keyGenerator,
5917
5934
  block,
5918
- options: {
5919
- normalize: !1,
5920
- removeUnusedMarkDefs: !0,
5921
- validateFields: !1
5922
- },
5935
+ profile: "lenient",
5923
5936
  schema: snapshot.context.schema
5924
5937
  });
5925
5938
  return parsedBlock ? [parsedBlock] : [];
@@ -5967,11 +5980,7 @@ const converterJson = defineConverter({
5967
5980
  let parsedBlock = parseBlock({
5968
5981
  keyGenerator: snapshot.context.keyGenerator,
5969
5982
  block,
5970
- options: {
5971
- normalize: !1,
5972
- removeUnusedMarkDefs: !0,
5973
- validateFields: !1
5974
- },
5983
+ profile: "lenient",
5975
5984
  schema: snapshot.context.schema
5976
5985
  });
5977
5986
  return parsedBlock ? [parsedBlock] : [];
@@ -6007,11 +6016,7 @@ const converterJson = defineConverter({
6007
6016
  let parsedBlock = parseBlock({
6008
6017
  keyGenerator: snapshot.context.keyGenerator,
6009
6018
  block,
6010
- options: {
6011
- normalize: !1,
6012
- removeUnusedMarkDefs: !0,
6013
- validateFields: !1
6014
- },
6019
+ profile: "lenient",
6015
6020
  schema: snapshot.context.schema
6016
6021
  });
6017
6022
  return parsedBlock ? [parsedBlock] : [];
@@ -6312,7 +6317,7 @@ function createBehaviorApiPlugin(editorActor) {
6312
6317
  return function behaviorApiPlugin(editor) {
6313
6318
  let { select, setSelection } = editor;
6314
6319
  return editor.select = (location) => {
6315
- if (editor.isNormalizingNode || editor.isPerformingBehaviorOperation) {
6320
+ if (isInNormalization(editor.applyContext) || editor.isPerformingBehaviorOperation) {
6316
6321
  select(location);
6317
6322
  return;
6318
6323
  }
@@ -6333,7 +6338,7 @@ function createBehaviorApiPlugin(editorActor) {
6333
6338
  editor
6334
6339
  });
6335
6340
  }, editor.setSelection = (partialRange) => {
6336
- if (editor.isNormalizingNode || editor.isPerformingBehaviorOperation) {
6341
+ if (isInNormalization(editor.applyContext) || editor.isPerformingBehaviorOperation) {
6337
6342
  setSelection(partialRange);
6338
6343
  return;
6339
6344
  }
@@ -6478,8 +6483,8 @@ function getDirtyPaths(context, op) {
6478
6483
  let levels = [[]];
6479
6484
  if (Array.isArray(op.value)) for (let i = 0; i < op.value.length; i++) {
6480
6485
  let child = op.value[i];
6481
- if (typeof child != "object" || !child || !("_key" in child) || typeof child._key != "string") continue;
6482
- let childNode = child, childPath = [{ _key: childNode._key }];
6486
+ if (typeof child != "object" || !child) continue;
6487
+ let childNode = child, childPath = [nodeSegment(childNode, i)];
6483
6488
  levels.push(childPath), collectDescendantPaths(context, childNode, childPath, levels, context.containers.get(childNode._type));
6484
6489
  }
6485
6490
  return levels;
@@ -6503,11 +6508,11 @@ function getDirtyPaths(context, op) {
6503
6508
  let parentRegistration = resolveContainerAt(context.containers, context.value, nodePath), seed = parentRegistration && "field" in parentRegistration ? parentRegistration : void 0;
6504
6509
  for (let i = 0; i < op.value.length; i++) {
6505
6510
  let child = op.value[i];
6506
- if (typeof child != "object" || !child || !("_key" in child) || typeof child._key != "string") continue;
6511
+ if (typeof child != "object" || !child) continue;
6507
6512
  let childNode = child, childPath = [
6508
6513
  ...nodePath,
6509
6514
  propertyName,
6510
- { _key: childNode._key }
6515
+ nodeSegment(childNode, i)
6511
6516
  ];
6512
6517
  levels.push(childPath), collectDescendantPaths(context, childNode, childPath, levels, seed);
6513
6518
  }
@@ -6583,7 +6588,14 @@ function normalize(editor, options = {}) {
6583
6588
  let entry = getNode(editor.snapshot, dirtyPath);
6584
6589
  if (!entry) continue;
6585
6590
  let entryNode = entry.node;
6586
- 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
+ }
6587
6599
  }
6588
6600
  let dirtyPaths = getDirtyPaths(editor), initialDirtyPathsLength = dirtyPaths.length, iteration = 0;
6589
6601
  for (; dirtyPaths.length !== 0;) {
@@ -6594,10 +6606,23 @@ function normalize(editor, options = {}) {
6594
6606
  operation
6595
6607
  })) return;
6596
6608
  let dirtyPath = popDirtyPath(editor);
6597
- if (dirtyPath.length === 0) editor.isNormalizingNode = !0, editor.normalizeNode([editor, dirtyPath], { operation }), editor.isNormalizingNode = !1;
6598
- 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)) {
6599
6617
  let entry = getNode(editor.snapshot, dirtyPath);
6600
- 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
+ }
6601
6626
  }
6602
6627
  iteration++, dirtyPaths = getDirtyPaths(editor);
6603
6628
  }
@@ -6766,74 +6791,42 @@ function replaceChildren(xs, index, removeCount, ...newValues) {
6766
6791
  let result = xs.slice();
6767
6792
  return result.splice(index, removeCount, ...newValues), result;
6768
6793
  }
6769
- const removeChildren = replaceChildren;
6770
- /**
6771
- * Find the index of a node in an array by its _key.
6772
- */
6773
- function findIndexByKey(children, key) {
6774
- return children.findIndex((child) => child._key === key);
6775
- }
6776
- /**
6777
- * Extract the keyed segments from a path (skipping field name strings).
6778
- */
6779
- function getKeyedSegments(path) {
6780
- return path.filter(isKeyedSegment);
6781
- }
6782
- /**
6783
- * Replace a descendant with a new node, replacing all ancestors
6784
- */
6785
- const modifyDescendant = (editor, path, f) => {
6794
+ const removeChildren = replaceChildren, modifyDescendant = (editor, path, f) => {
6786
6795
  if (path.length === 0) return;
6787
6796
  let context = {
6788
6797
  schema: editor.snapshot.context.schema,
6789
6798
  containers: editor.snapshot.context.containers
6790
6799
  }, nodeEntry = getNode(editor.snapshot, path);
6791
6800
  if (!nodeEntry) return;
6792
- let node = nodeEntry.node, modifiedNode = f(node), keyedSegments = getKeyedSegments(nodeEntry.path), numericIndices = /* @__PURE__ */ new Map();
6793
- {
6794
- let keyedIdx = 0;
6795
- for (let segment of path) typeof segment == "number" ? (numericIndices.set(keyedIdx, segment), keyedIdx++) : isKeyedSegment(segment) && keyedIdx++;
6796
- }
6797
- let fieldNames = [];
6798
- {
6799
- let currentNode = { value: editor.snapshot.context.value }, currentParent;
6800
- for (let i = 0; i < keyedSegments.length; i++) {
6801
- let result = getNodeChildren(context, currentNode, currentParent);
6802
- if (!result) return;
6803
- fieldNames.push(result.fieldName);
6804
- let numericIndex = numericIndices.get(i), child = numericIndex === void 0 ? result.children.find((c) => c._key === keyedSegments[i]._key) : result.children[numericIndex];
6805
- if (!child) return;
6806
- currentNode = child, currentParent = result.parent;
6807
- }
6808
- }
6809
- for (let level = keyedSegments.length - 2; level >= 0; level--) {
6810
- let childKey = keyedSegments[level + 1]._key, fieldName = fieldNames[level + 1], ancestorPathEnd = -1, keyedCount = 0;
6811
- for (let pi = 0; pi < path.length; pi++) if (typeof path[pi] != "string") {
6812
- if (keyedCount === level) {
6813
- ancestorPathEnd = pi + 1;
6814
- break;
6815
- }
6816
- keyedCount++;
6817
- }
6818
- let ancestorPath = ancestorPathEnd > 0 ? path.slice(0, ancestorPathEnd) : [], ancestorEntry = getNode(editor.snapshot, ancestorPath);
6819
- if (!ancestorEntry) return;
6820
- 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;
6821
- 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];
6822
6824
  modifiedNode = {
6823
- ...ancestorNode,
6824
- [fieldName]: replaceChildren(currentChildren, childIndex, 1, modifiedNode)
6825
+ ...parentNode,
6826
+ [fieldName]: replaceChildren(children, index, 1, modifiedNode)
6825
6827
  };
6826
6828
  }
6827
- let rootIndex, rootNumericIndex = numericIndices.get(0);
6828
- if (rootNumericIndex !== void 0) rootIndex = rootNumericIndex;
6829
- else if (keyedSegments.length > 0) {
6830
- let rootSegment = keyedSegments[0], mapIndex = editor.blockIndexMap.get(serializePath([rootSegment]));
6831
- rootIndex = mapIndex === void 0 ? findIndexByKey(editor.snapshot.context.value, rootSegment._key) : mapIndex;
6832
- } else {
6833
- let firstSegment = path[0];
6834
- rootIndex = typeof firstSegment == "number" ? firstSegment : -1;
6835
- }
6836
- 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);
6837
6830
  }, modifyChildren = (editor, path, f) => {
6838
6831
  if (path.length === 0) editor.snapshot.context.value = f(editor.snapshot.context.value);
6839
6832
  else {
@@ -6867,7 +6860,7 @@ function applyOperation(editor, op) {
6867
6860
  break;
6868
6861
  }
6869
6862
  modifyChildren(editor, parentPath(path), (children) => {
6870
- !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 = {
6871
6864
  ...node,
6872
6865
  _key: editor.snapshot.context.keyGenerator()
6873
6866
  }, op.node = node);
@@ -6879,7 +6872,7 @@ function applyOperation(editor, op) {
6879
6872
  } else if (typeof lastSegment == "number") index = op.position === "after" ? lastSegment + 1 : lastSegment;
6880
6873
  else throw Error(`Cannot apply an "insert" operation at path [${path}] because the last segment is a field name.`);
6881
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.`);
6882
- return !op.inverse && !editor.isProcessingRemoteChanges && (op.inverse = {
6875
+ return !op.inverse && !hasRemoteFrame(editor.applyContext) && (op.inverse = {
6883
6876
  type: "unset",
6884
6877
  path: node._key === void 0 ? path : replaceLastSegment(path, { _key: node._key })
6885
6878
  }), insertChildren(children, index, node);
@@ -6912,7 +6905,7 @@ function applyOperation(editor, op) {
6912
6905
  }
6913
6906
  case "set": {
6914
6907
  let { path, value } = op;
6915
- if (!op.inverse && !editor.isProcessingRemoteChanges) {
6908
+ if (!op.inverse && !hasRemoteFrame(editor.applyContext)) {
6916
6909
  let previousValue = getValue(editor.snapshot.context.value, path), inversePath = path[path.length - 1] === "_key" && typeof value == "string" && isKeyedSegment(path[path.length - 2]) ? [
6917
6910
  ...path.slice(0, -2),
6918
6911
  { _key: value },
@@ -6965,7 +6958,7 @@ function applyOperation(editor, op) {
6965
6958
  case "unset": {
6966
6959
  let { path } = op;
6967
6960
  if (path.length === 0) {
6968
- !op.inverse && !editor.isProcessingRemoteChanges && (op.inverse = {
6961
+ !op.inverse && !hasRemoteFrame(editor.applyContext) && (op.inverse = {
6969
6962
  type: "set",
6970
6963
  path,
6971
6964
  value: editor.snapshot.context.value
@@ -6974,7 +6967,7 @@ function applyOperation(editor, op) {
6974
6967
  }
6975
6968
  let lastSegment = path[path.length - 1];
6976
6969
  if ((isKeyedSegment(lastSegment) || typeof lastSegment == "number") && !targetsStructuralChildren(editor, path)) {
6977
- if (!op.inverse && !editor.isProcessingRemoteChanges) {
6970
+ if (!op.inverse && !hasRemoteFrame(editor.applyContext)) {
6978
6971
  let arrayValue = getValue(editor.snapshot.context.value, path.slice(0, -1));
6979
6972
  Array.isArray(arrayValue) && (op.inverse = {
6980
6973
  type: "set",
@@ -7010,7 +7003,7 @@ function applyOperation(editor, op) {
7010
7003
  modifyChildren(editor, parentPath(path), (children) => {
7011
7004
  let index;
7012
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.`);
7013
- if (!op.inverse && !editor.isProcessingRemoteChanges) {
7006
+ if (!op.inverse && !hasRemoteFrame(editor.applyContext)) {
7014
7007
  let previousSibling = index > 0 ? children[index - 1] : void 0;
7015
7008
  op.inverse = previousSibling?._key ? {
7016
7009
  type: "insert",
@@ -7030,7 +7023,7 @@ function applyOperation(editor, op) {
7030
7023
  }
7031
7024
  let { nodePath: unsetNodePath, propertyPath: unsetPropertyPath } = splitNodePath(path);
7032
7025
  if (unsetPropertyPath.length === 0 || unsetNodePath.length === 0) break;
7033
- if (!op.inverse && !editor.isProcessingRemoteChanges) {
7026
+ if (!op.inverse && !hasRemoteFrame(editor.applyContext)) {
7034
7027
  let previousValue = getValue(editor.snapshot.context.value, path);
7035
7028
  if (previousValue === void 0) break;
7036
7029
  op.inverse = {
@@ -7161,18 +7154,21 @@ function resolveChildIndex$1(blockIndexMap, parentSegments, segment, children) {
7161
7154
  return index !== void 0 && children[index]?._key === segment._key ? index : children.findIndex((child) => child._key === segment._key);
7162
7155
  }
7163
7156
  /**
7164
- * 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.
7165
7159
  */
7166
7160
  function findBlockSegment(path) {
7167
7161
  let firstSegment = path[0];
7168
- if (isKeyedSegment(firstSegment)) return firstSegment;
7162
+ if (isKeyedSegment(firstSegment) || typeof firstSegment == "number") return firstSegment;
7169
7163
  }
7170
7164
  /**
7171
7165
  * Resolve a root block's index via `blockIndexMap`, falling back to a
7172
7166
  * linear scan when the map misses or disagrees with the tree.
7173
7167
  */
7174
7168
  function resolveBlockIndex(editor, segment) {
7175
- 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]));
7176
7172
  return index !== void 0 && value[index]?._key === segment._key ? index : value.findIndex((block) => block._key === segment._key);
7177
7173
  }
7178
7174
  /**
@@ -7276,7 +7272,12 @@ const apply$1 = (editor, op) => {
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));
@@ -7856,7 +7857,7 @@ const normalizeNode = (editor, entry) => {
7856
7857
  /**
7857
7858
  * Merge spans with same set of .marks
7858
7859
  */
7859
- if (!editor.isProcessingRemoteChanges && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
7860
+ if (!hasRemoteFrame(editor.applyContext) && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
7860
7861
  let children = getChildren(editor.snapshot, path);
7861
7862
  for (let i = 0; i < children.length - 1; i++) {
7862
7863
  let { node: child } = children[i], { node: nextNode, path: nextChildPath } = children[i + 1];
@@ -7891,35 +7892,15 @@ const normalizeNode = (editor, entry) => {
7891
7892
  });
7892
7893
  return;
7893
7894
  }
7894
- if (nodeRecord._key === void 0 && path.length > 0) {
7895
+ if (!hasUsableKey(nodeRecord._key) && path.length > 0) {
7895
7896
  let newKey = editor.snapshot.context.keyGenerator();
7896
- debug.normalization("Setting missing key on node");
7897
- let numericPath = [], currentNode;
7898
- for (let segment of path) {
7899
- if (typeof segment == "string") {
7900
- currentNode && numericPath.push(segment);
7901
- continue;
7902
- }
7903
- let siblings = currentNode ? currentNode[numericPath[numericPath.length - 1]] ?? [] : editor.snapshot.context.value;
7904
- if (isKeyedSegment(segment) && segment._key !== void 0) numericPath.push(segment), currentNode = Array.prototype.find.call(siblings, (child) => child._key === segment._key);
7905
- else {
7906
- let index = typeof segment == "number" ? segment : -1;
7907
- if (index === -1) {
7908
- for (let i = 0; i < siblings.length; i++) if (siblings[i]._key === void 0) {
7909
- index = i;
7910
- break;
7911
- }
7912
- }
7913
- index !== -1 && (numericPath.push(index), currentNode = siblings[index]);
7914
- }
7915
- }
7916
- editor.apply({
7897
+ debug.normalization("Setting missing key on node"), editor.apply({
7917
7898
  type: "set",
7918
- path: [...numericPath, "_key"],
7899
+ path: [...path, "_key"],
7919
7900
  value: newKey,
7920
7901
  inverse: {
7921
7902
  type: "unset",
7922
- path: [...numericPath, "_key"]
7903
+ path: [...path, "_key"]
7923
7904
  }
7924
7905
  });
7925
7906
  return;
@@ -7961,14 +7942,14 @@ const normalizeNode = (editor, entry) => {
7961
7942
  /**
7962
7943
  * Add missing .markDefs to text block nodes
7963
7944
  */
7964
- 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)) {
7965
7946
  debug.normalization("adding .markDefs to block node"), applyNodeProperties(editor, { markDefs: [] }, path);
7966
7947
  return;
7967
7948
  }
7968
7949
  /**
7969
7950
  * Add missing .style to text block nodes
7970
7951
  */
7971
- 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) {
7972
7953
  let defaultStyle = getPathSubSchema(editor.snapshot, path).styles.at(0)?.name;
7973
7954
  if (defaultStyle) {
7974
7955
  debug.normalization("adding .style to block node"), applyNodeProperties(editor, { style: defaultStyle }, path);
@@ -7993,14 +7974,14 @@ const normalizeNode = (editor, entry) => {
7993
7974
  /**
7994
7975
  * Add missing .marks to span nodes
7995
7976
  */
7996
- 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)) {
7997
7978
  debug.normalization("Adding .marks to span node"), applyNodeProperties(editor, { marks: [] }, path);
7998
7979
  return;
7999
7980
  }
8000
7981
  /**
8001
7982
  * Remove annotations from empty spans
8002
7983
  */
8003
- if (!editor.isProcessingRemoteChanges && isSpan({ schema: editor.snapshot.context.schema }, node)) {
7984
+ if (!hasRemoteFrame(editor.applyContext) && isSpan({ schema: editor.snapshot.context.schema }, node)) {
8004
7985
  let blockPath = parentPath(path), blockEntry = getTextBlock(editor.snapshot, blockPath);
8005
7986
  if (!blockEntry) return;
8006
7987
  let annotations = node.marks?.filter((mark) => blockEntry.node.markDefs?.some((markDef) => markDef._key === mark));
@@ -8012,7 +7993,7 @@ const normalizeNode = (editor, entry) => {
8012
7993
  /**
8013
7994
  * Remove duplicate markDefs
8014
7995
  */
8015
- if (!editor.isProcessingRemoteChanges && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
7996
+ if (!hasRemoteFrame(editor.applyContext) && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
8016
7997
  let markDefs = node.markDefs ?? [], markDefKeys = /* @__PURE__ */ new Set(), newMarkDefs = [];
8017
7998
  for (let markDef of markDefs) markDefKeys.has(markDef._key) || (markDefKeys.add(markDef._key), newMarkDefs.push(markDef));
8018
7999
  if (markDefs.length !== newMarkDefs.length) {
@@ -8023,7 +8004,7 @@ const normalizeNode = (editor, entry) => {
8023
8004
  /**
8024
8005
  * Remove markDefs not in use
8025
8006
  */
8026
- if (!editor.isProcessingRemoteChanges && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
8007
+ if (!hasRemoteFrame(editor.applyContext) && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
8027
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)));
8028
8009
  if (node.markDefs && !isEqualMarkDefs(newMarkDefs, node.markDefs)) {
8029
8010
  debug.normalization("removing markDef not in use"), applyNodeProperties(editor, { markDefs: newMarkDefs }, path);
@@ -8165,7 +8146,7 @@ const normalizeNode = (editor, entry) => {
8165
8146
  { _key: child._key }
8166
8147
  ];
8167
8148
  if (isSpan({ schema: editor.snapshot.context.schema }, child)) {
8168
- 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)) {
8169
8150
  if (child.text === "") {
8170
8151
  editor.apply({
8171
8152
  type: "unset",
@@ -8259,6 +8240,7 @@ const shouldNormalize = (_editor, { iteration, initialDirtyPathsLength }) => {
8259
8240
  }, createEditor = () => {
8260
8241
  let e = {
8261
8242
  [EDITOR_BRAND]: !0,
8243
+ applyContext: [],
8262
8244
  operations: [],
8263
8245
  operationListeners: {
8264
8246
  before: [],
@@ -8352,13 +8334,25 @@ function collectDescendantIndexes(context, node, nodePath, parent, blockIndexMap
8352
8334
  blockIndexMap.has(childKey) || blockIndexMap.set(childKey, i), collectDescendantIndexes(context, child, childPath, result.parent, blockIndexMap);
8353
8335
  }
8354
8336
  }
8355
- function withRemoteChanges(editor, fn) {
8356
- let prev = editor.isProcessingRemoteChanges;
8357
- 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
+ }
8358
8347
  }
8359
8348
  function pluginWithoutHistory(editor, fn) {
8360
8349
  let prev = editor.withHistory;
8361
- editor.withHistory = !1, fn(), editor.withHistory = prev;
8350
+ editor.withHistory = !1;
8351
+ try {
8352
+ fn();
8353
+ } finally {
8354
+ editor.withHistory = prev;
8355
+ }
8362
8356
  }
8363
8357
  function cloneDiff(diff2) {
8364
8358
  let [type, patch] = diff2;
@@ -9129,7 +9123,7 @@ function setupRemotePatches({ editorActor, subscriptions, editor }) {
9129
9123
  let patches = bufferedPatches;
9130
9124
  bufferedPatches = [];
9131
9125
  let changed = !1;
9132
- withRemoteChanges(editor, () => {
9126
+ withRemoteChanges(editor, "patches", () => {
9133
9127
  withoutNormalizing(editor, () => {
9134
9128
  withoutPatching(editor, () => {
9135
9129
  pluginWithoutHistory(editor, () => {
@@ -9154,10 +9148,10 @@ function setupRemotePatches({ editorActor, subscriptions, editor }) {
9154
9148
  };
9155
9149
  });
9156
9150
  }
9157
- function createUndoSteps({ steps, op, currentUndoStepId, previousUndoStepId, operationsInProgress, isNormalizingNode, selectionBeforeApply }) {
9151
+ function createUndoSteps({ steps, op, currentUndoStepId, previousUndoStepId, operationsInProgress, isInNormalization, selectionBeforeApply }) {
9158
9152
  let lastStep = steps.at(-1);
9159
9153
  if (!lastStep) return createNewStep(steps, op, selectionBeforeApply);
9160
- 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);
9161
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);
9162
9156
  if (currentUndoStepId === void 0 && previousUndoStepId === void 0) {
9163
9157
  if (op.type === "set.selection") return mergeIntoLastStep(steps, lastStep, op);
@@ -9217,7 +9211,7 @@ function subscribeHistory({ editorActor, subscriptions, editor }) {
9217
9211
  subscription.unsubscribe();
9218
9212
  };
9219
9213
  }), subscribeToOperations(editor, (event) => {
9220
- 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;
9221
9215
  let currentUndoStepId = event.undoStepId;
9222
9216
  if (!event.withHistory) {
9223
9217
  previousUndoStepId = currentUndoStepId;
@@ -9234,7 +9228,7 @@ function subscribeHistory({ editorActor, subscriptions, editor }) {
9234
9228
  currentUndoStepId,
9235
9229
  previousUndoStepId,
9236
9230
  operationsInProgress: event.operationsInProgress,
9237
- isNormalizingNode: event.isNormalizingNode,
9231
+ isInNormalization: isInNormalization(event.context),
9238
9232
  selectionBeforeApply: event.beforeSelection
9239
9233
  }); editor.history.undos.length > 1e3;) editor.history.undos.shift();
9240
9234
  previousUndoStepId = currentUndoStepId;
@@ -9264,7 +9258,7 @@ function insertNodePatch(operation) {
9264
9258
  function subscribePatchGeneration({ editorActor, editor }) {
9265
9259
  return subscribeToOperations(editor, (event) => {
9266
9260
  if (!event.isPatching) return;
9267
- 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);
9268
9262
  switch (editorWasEmpty && !editorIsEmpty && operation.type !== "set.selection" && patches.push(insert(previousValue, "before", [0])), operation.type) {
9269
9263
  case "insert.text":
9270
9264
  patches = [...patches, ...textPatch(editor.snapshot, operation, previousValue)];
@@ -9284,7 +9278,7 @@ function subscribePatchGeneration({ editorActor, editor }) {
9284
9278
  "set",
9285
9279
  "unset",
9286
9280
  "remove.text"
9287
- ].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({
9288
9282
  type: "internal.patch",
9289
9283
  patch: {
9290
9284
  ...patch,
@@ -9674,7 +9668,7 @@ function invalidateVerifiedGroups(groups, operation) {
9674
9668
  */
9675
9669
  function subscribeUpdateValue(context, editor) {
9676
9670
  let unsubscribeNormalizationLog = debug.normalization.enabled ? subscribeToOperations(editor, (event) => {
9677
- event.isNormalizingNode && debug.normalization(`((engine operation))\n${safeStringify(event.operation, 2)}`);
9671
+ isInNormalization(event.context) && debug.normalization(`((engine operation))\n${safeStringify(event.operation, 2)}`);
9678
9672
  }, { phase: "before" }) : void 0, unsubscribeIndexMaps = subscribeToOperations(editor, (event) => {
9679
9673
  let operation = event.operation;
9680
9674
  operation.type !== "set.selection" && operation.type !== "insert.text" && operation.type !== "remove.text" && (transformBlockIndexMap(editor.blockIndexMap, operation, event.beforeValue, editor.snapshot.context.value, {
@@ -9712,7 +9706,7 @@ function createEditorEngine(config) {
9712
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 = {
9713
9707
  undos: [],
9714
9708
  redos: []
9715
- }, 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;
9716
9710
  let editorEngine = plugins(withDOM(editor), { editorActor: config.editorActor });
9717
9711
  return subscribeUpdateValue(context, editorEngine), subscribePatchGeneration({
9718
9712
  editorActor: config.editorActor,
@@ -11038,7 +11032,7 @@ const coreListBehaviors = {
11038
11032
  let adjustLevel = !0, listStartBlockFound = !1;
11039
11033
  return [raise$1({
11040
11034
  ...event,
11041
- 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) ? {
11042
11036
  ...block,
11043
11037
  level: Math.min(10, Math.max(1, block.level + levelDifference))
11044
11038
  } : (listStartBlockFound && (adjustLevel = !1), block) : block))
@@ -11066,7 +11060,7 @@ const coreListBehaviors = {
11066
11060
  let adjustListItem = !0, listStartBlockFound = !1;
11067
11061
  return [raise$1({
11068
11062
  ...event,
11069
- 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) ? {
11070
11064
  ...block,
11071
11065
  listItem: block.level === insertedListBlock.level ? listItem : block.listItem
11072
11066
  } : (listStartBlockFound && (adjustListItem = !1), block) : block))
@@ -11166,7 +11160,12 @@ function createEditorSnapshot({ converters, editor, keyGenerator, readOnly, sche
11166
11160
  }
11167
11161
  function withPerformingBehaviorOperation(editor, fn) {
11168
11162
  let prev = editor.isPerformingBehaviorOperation;
11169
- editor.isPerformingBehaviorOperation = !0, fn(), editor.isPerformingBehaviorOperation = prev;
11163
+ editor.isPerformingBehaviorOperation = !0;
11164
+ try {
11165
+ fn();
11166
+ } finally {
11167
+ editor.isPerformingBehaviorOperation = prev;
11168
+ }
11170
11169
  }
11171
11170
  function withoutNormalizingConditional(editor, predicate, fn) {
11172
11171
  predicate() ? withoutNormalizing(editor, fn) : fn();
@@ -11180,7 +11179,7 @@ const addAnnotationOperationImplementation = ({ snapshot, operation }) => {
11180
11179
  },
11181
11180
  schema: annotationSchema,
11182
11181
  keyGenerator: context.keyGenerator,
11183
- options: { validateFields: !0 }
11182
+ profile: "strict"
11184
11183
  });
11185
11184
  if (!parsedAnnotation) throw Error(`Failed to parse annotation ${safeStringify(operation.annotation)}`);
11186
11185
  if (!effectiveSelection || isCollapsedRange(effectiveSelection)) return;
@@ -11336,7 +11335,7 @@ const blockSetOperationImplementation = ({ snapshot, operation }) => {
11336
11335
  let { markDefs } = parseMarkDefs({
11337
11336
  keyGenerator: context.keyGenerator,
11338
11337
  markDefs: operation.props[key],
11339
- options: { validateFields: !0 },
11338
+ profile: "strict",
11340
11339
  schema: getPathSubSchema(snapshot, blockEntry.path)
11341
11340
  });
11342
11341
  filteredProps[key] = markDefs;
@@ -12360,8 +12359,12 @@ const deleteOperationImplementation = ({ operation }) => {
12360
12359
  });
12361
12360
  };
12362
12361
  function pluginRedoing(editor, fn) {
12363
- let prev = editor.isRedoing;
12364
- 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
+ }
12365
12368
  }
12366
12369
  /**
12367
12370
  * This will adjust the operation paths and offsets according to the
@@ -12431,7 +12434,7 @@ const historyRedoOperationImplementation = ({ operation }) => {
12431
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 = {
12432
12435
  undos: [],
12433
12436
  redos: []
12434
- }, editor.withHistory = !0, editor.isRedoing = !1, editor.onChange();
12437
+ }, editor.onChange();
12435
12438
  return;
12436
12439
  }
12437
12440
  editor.history.undos.push(step), editor.history.redos.pop();
@@ -12439,8 +12442,12 @@ const historyRedoOperationImplementation = ({ operation }) => {
12439
12442
  }
12440
12443
  };
12441
12444
  function pluginUndoing(editor, fn) {
12442
- let prev = editor.isUndoing;
12443
- 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
+ }
12444
12451
  }
12445
12452
  function inverseOperation(op) {
12446
12453
  switch (op.type) {
@@ -12536,7 +12543,7 @@ const historyUndoOperationImplementation = ({ operation }) => {
12536
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 = {
12537
12544
  undos: [],
12538
12545
  redos: []
12539
- }, editor.withHistory = !0, editor.isUndoing = !1, editor.onChange();
12546
+ }, editor.onChange();
12540
12547
  return;
12541
12548
  }
12542
12549
  editor.history.redos.push(step), editor.history.undos.pop();
@@ -12553,11 +12560,7 @@ const historyUndoOperationImplementation = ({ operation }) => {
12553
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({
12554
12561
  block: operation.block,
12555
12562
  keyGenerator: context.keyGenerator,
12556
- options: {
12557
- normalize: !0,
12558
- removeUnusedMarkDefs: !0,
12559
- validateFields: !0
12560
- },
12563
+ profile: "strict",
12561
12564
  schema
12562
12565
  });
12563
12566
  if (!parsedBlock) return;
@@ -12957,13 +12960,11 @@ const insertChildOperationImplementation = ({ snapshot, operation }) => {
12957
12960
  ...focusBlockEntry.path,
12958
12961
  "children",
12959
12962
  focusChildSegment
12960
- ], markDefs = focusBlock.markDefs ?? [], markDefKeyMap = /* @__PURE__ */ new Map();
12961
- for (let markDef of markDefs) markDefKeyMap.set(markDef._key, markDef._key);
12962
- 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({
12963
12964
  span: operation.child,
12964
12965
  keyGenerator: context.keyGenerator,
12965
- markDefKeyMap,
12966
- options: { validateFields: !0 },
12966
+ markDefKeys,
12967
+ profile: "strict",
12967
12968
  schema
12968
12969
  });
12969
12970
  if (span) {
@@ -12984,7 +12985,7 @@ const insertChildOperationImplementation = ({ snapshot, operation }) => {
12984
12985
  let inlineObject = parseInlineObject({
12985
12986
  inlineObject: operation.child,
12986
12987
  keyGenerator: context.keyGenerator,
12987
- options: { validateFields: !0 },
12988
+ profile: "strict",
12988
12989
  schema
12989
12990
  });
12990
12991
  if (inlineObject) {
@@ -13077,7 +13078,14 @@ const moveBackwardOperationImplementation = ({ operation }) => {
13077
13078
  if (newSelection) {
13078
13079
  let anchorContainer = getContainer(operation.editor.snapshot, newSelection.anchor.path), focusContainer = getContainer(operation.editor.snapshot, newSelection.focus.path), containers = anchorContainer ? [anchorContainer] : [];
13079
13080
  focusContainer && focusContainer.node !== anchorContainer?.node && containers.push(focusContainer), containers.length > 0 && (withoutNormalizing(operation.editor, () => {
13080
- 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
+ }
13081
13089
  }), newSelection = resolveSelection(operation.editor, operation.at));
13082
13090
  }
13083
13091
  newSelection ? applySelect(operation.editor, newSelection) : applyDeselect(operation.editor), operation.editor.focused && operation.editor.snapshot.context.readOnly && (operation.editor.focused = !1);
@@ -14455,11 +14463,7 @@ const abstractInsertBehaviors = [
14455
14463
  endPoint: blockEndPoint
14456
14464
  }),
14457
14465
  keyGenerator: snapshot.context.keyGenerator,
14458
- options: {
14459
- normalize: !1,
14460
- removeUnusedMarkDefs: !0,
14461
- validateFields: !1
14462
- },
14466
+ profile: "lenient",
14463
14467
  schema: getPathSubSchema(snapshot, focusTextBlock.path)
14464
14468
  });
14465
14469
  return newTextBlock ? {
@@ -15275,7 +15279,7 @@ const editorMachine = setup({
15275
15279
  },
15276
15280
  guards: {
15277
15281
  "engine is busy": ({ context }) => context.editorEngine ? context.editorEngine.operations.length > 0 : !1,
15278
- "engine is normalizing node": ({ context }) => context.editorEngine ? context.editorEngine.isNormalizingNode : !1
15282
+ "engine is normalizing node": ({ context }) => context.editorEngine ? isInNormalization(context.editorEngine.applyContext) : !1
15279
15283
  }
15280
15284
  }).createMachine({
15281
15285
  id: "editor",
@@ -15987,7 +15991,7 @@ const syncValueCallback = ({ sendBack, input }) => {
15987
15991
  "clear pending value": assign({ pendingValue: void 0 }),
15988
15992
  "assign previous value": assign({ previousValue: ({ event }) => (assertEvent(event, "done syncing"), event.value) }),
15989
15993
  "record synced value on engine": ({ context, event }) => {
15990
- assertEvent(event, "done syncing"), context.editorEngine.lastSyncedValue = event.value;
15994
+ assertEvent(event, "done syncing"), event.changed && (context.editorEngine.lastSyncedValue = event.value);
15991
15995
  },
15992
15996
  "emit done syncing value": emit({ type: "done syncing value" }),
15993
15997
  "emit syncing value": emit({ type: "syncing value" })
@@ -15995,11 +15999,11 @@ const syncValueCallback = ({ sendBack, input }) => {
15995
15999
  guards: {
15996
16000
  "initial value synced": ({ context }) => context.initialValueSynced,
15997
16001
  "is busy": ({ context }) => {
15998
- let isBusy = context.editorEngine.isDeferringMutations || context.editorEngine.isProcessingRemoteChanges;
16002
+ let isBusy = context.editorEngine.isDeferringMutations || hasRemoteFrame(context.editorEngine.applyContext);
15999
16003
  return debug.syncValue(safeStringify({
16000
16004
  isBusy,
16001
16005
  isDeferringMutations: context.editorEngine.isDeferringMutations,
16002
- isProcessingRemoteChanges: context.editorEngine.isProcessingRemoteChanges
16006
+ hasRemoteFrame: hasRemoteFrame(context.editorEngine.applyContext)
16003
16007
  })), isBusy;
16004
16008
  },
16005
16009
  "is empty value": ({ event }) => event.type === "update value" && event.value === void 0,
@@ -16149,10 +16153,11 @@ const syncValueCallback = ({ sendBack, input }) => {
16149
16153
  }
16150
16154
  });
16151
16155
  async function updateValue({ context, sendBack, editorEngine, streamBlocks, value }) {
16152
- 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";
16153
16157
  if ((!value || value.length === 0) && (clearEditor({
16154
16158
  editorEngine,
16155
- doneSyncing
16159
+ doneSyncing,
16160
+ remoteSource
16156
16161
  }), isChanged = !0), value && value.length > 0) {
16157
16162
  if (streamBlocks) await new Promise((resolve) => {
16158
16163
  if (doneSyncing) {
@@ -16161,7 +16166,8 @@ async function updateValue({ context, sendBack, editorEngine, streamBlocks, valu
16161
16166
  }
16162
16167
  isChanged = removeExtraBlocks({
16163
16168
  editorEngine,
16164
- value
16169
+ value,
16170
+ remoteSource
16165
16171
  });
16166
16172
  let processBlocks = async () => {
16167
16173
  for await (let [currentBlock, currentBlockIndex] of getStreamedBlocks({ value })) {
@@ -16171,7 +16177,8 @@ async function updateValue({ context, sendBack, editorEngine, streamBlocks, valu
16171
16177
  block: currentBlock,
16172
16178
  index: currentBlockIndex,
16173
16179
  editorEngine,
16174
- value
16180
+ value,
16181
+ remoteSource
16175
16182
  });
16176
16183
  if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !isValid) break;
16177
16184
  }
@@ -16183,7 +16190,8 @@ async function updateValue({ context, sendBack, editorEngine, streamBlocks, valu
16183
16190
  if (doneSyncing) return;
16184
16191
  isChanged = removeExtraBlocks({
16185
16192
  editorEngine,
16186
- value
16193
+ value,
16194
+ remoteSource
16187
16195
  });
16188
16196
  let index = 0;
16189
16197
  for (let block of value) {
@@ -16193,7 +16201,8 @@ async function updateValue({ context, sendBack, editorEngine, streamBlocks, valu
16193
16201
  block,
16194
16202
  index,
16195
16203
  editorEngine,
16196
- value
16204
+ value,
16205
+ remoteSource
16197
16206
  });
16198
16207
  if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !blockValid) break;
16199
16208
  index++;
@@ -16203,7 +16212,8 @@ async function updateValue({ context, sendBack, editorEngine, streamBlocks, valu
16203
16212
  if (!isValid) {
16204
16213
  debug.syncValue("Invalid value, returning"), doneSyncing = !0, sendBack({
16205
16214
  type: "done syncing",
16206
- value
16215
+ value,
16216
+ changed: isChanged
16207
16217
  });
16208
16218
  return;
16209
16219
  }
@@ -16218,7 +16228,8 @@ async function updateValue({ context, sendBack, editorEngine, streamBlocks, valu
16218
16228
  value
16219
16229
  }), doneSyncing = !0, sendBack({
16220
16230
  type: "done syncing",
16221
- value
16231
+ value,
16232
+ changed: isChanged
16222
16233
  });
16223
16234
  return;
16224
16235
  }
@@ -16229,7 +16240,8 @@ async function updateValue({ context, sendBack, editorEngine, streamBlocks, valu
16229
16240
  } else debug.syncValue("remote value and local value are equal, no need to sync");
16230
16241
  doneSyncing = !0, sendBack({
16231
16242
  type: "done syncing",
16232
- value
16243
+ value,
16244
+ changed: isChanged
16233
16245
  });
16234
16246
  }
16235
16247
  async function* getStreamedBlocks({ value }) {
@@ -16239,8 +16251,8 @@ async function* getStreamedBlocks({ value }) {
16239
16251
  /**
16240
16252
  * Unsets every block; normalization then inserts the empty placeholder block.
16241
16253
  */
16242
- function clearEditor({ editorEngine, doneSyncing }) {
16243
- withRemoteChanges(editorEngine, () => {
16254
+ function clearEditor({ editorEngine, doneSyncing, remoteSource }) {
16255
+ withRemoteChanges(editorEngine, remoteSource, () => {
16244
16256
  withoutNormalizing(editorEngine, () => {
16245
16257
  pluginWithoutHistory(editorEngine, () => {
16246
16258
  withoutPatching(editorEngine, () => {
@@ -16262,9 +16274,9 @@ function clearEditor({ editorEngine, doneSyncing }) {
16262
16274
  * Compare the length of the value and the length of the editor's children, and
16263
16275
  * remove blocks that have become superfluous
16264
16276
  */
16265
- function removeExtraBlocks({ editorEngine, value }) {
16277
+ function removeExtraBlocks({ editorEngine, value, remoteSource }) {
16266
16278
  let isChanged = !1;
16267
- return withRemoteChanges(editorEngine, () => {
16279
+ return withRemoteChanges(editorEngine, remoteSource, () => {
16268
16280
  withoutNormalizing(editorEngine, () => {
16269
16281
  withoutPatching(editorEngine, () => {
16270
16282
  let childrenLength = editorEngine.snapshot.context.value.length;
@@ -16282,13 +16294,13 @@ function removeExtraBlocks({ editorEngine, value }) {
16282
16294
  });
16283
16295
  }), isChanged;
16284
16296
  }
16285
- function syncBlock({ context, sendBack, block, index, editorEngine, value }) {
16297
+ function syncBlock({ context, sendBack, block, index, editorEngine, value, remoteSource }) {
16286
16298
  let oldEngineBlock = editorEngine.snapshot.context.value.at(index), oldBlock = editorEngine.snapshot.context.value.at(index);
16287
16299
  if (!oldEngineBlock || !oldBlock) {
16288
16300
  let validation = validateValue([block], context.schema, context.keyGenerator);
16289
16301
  if (debug.syncValue("Validating and inserting new block in the end of the value", block), validation.valid || validation.resolution?.autoResolve) {
16290
16302
  let engineBlock = toEngineBlock(applyAutoResolution(validation, [block], block), { schemaTypes: context.schema });
16291
- return withRemoteChanges(editorEngine, () => {
16303
+ return withRemoteChanges(editorEngine, remoteSource, () => {
16292
16304
  withoutNormalizing(editorEngine, () => {
16293
16305
  withoutPatching(editorEngine, () => {
16294
16306
  editorEngine.apply({
@@ -16330,7 +16342,7 @@ function syncBlock({ context, sendBack, block, index, editorEngine, value }) {
16330
16342
  });
16331
16343
  })), validation.valid || validation.resolution?.autoResolve) {
16332
16344
  let repairedBlock = applyAutoResolution(validation, validationValue, block);
16333
- 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, () => {
16334
16346
  withoutNormalizing(editorEngine, () => {
16335
16347
  withoutPatching(editorEngine, () => {
16336
16348
  updateBlock({
@@ -16342,7 +16354,7 @@ function syncBlock({ context, sendBack, block, index, editorEngine, value }) {
16342
16354
  });
16343
16355
  });
16344
16356
  });
16345
- })) : (debug.syncValue("Replacing block", oldBlock, repairedBlock), withRemoteChanges(editorEngine, () => {
16357
+ })) : (debug.syncValue("Replacing block", oldBlock, repairedBlock), withRemoteChanges(editorEngine, remoteSource, () => {
16346
16358
  withoutNormalizing(editorEngine, () => {
16347
16359
  withoutPatching(editorEngine, () => {
16348
16360
  replaceBlock({
@@ -16640,7 +16652,7 @@ function createActors(config) {
16640
16652
  isPublicOperation(event.operation) && config.relay.send({
16641
16653
  type: "operation",
16642
16654
  operation: event.operation,
16643
- origin: event.origin === "remote" ? "remote" : "local"
16655
+ origin: hasRemoteFrame(event.context) ? "remote" : "local"
16644
16656
  });
16645
16657
  })), config.subscriptions.push(() => {
16646
16658
  let subscription = syncActor.on("*", (event) => {