@portabletext/editor 7.4.0 → 7.5.1

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.
package/lib/index.js CHANGED
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { c } from "react/compiler-runtime";
3
3
  import { useSelector, useActorRef } from "@xstate/react";
4
4
  import React, { createContext, useContext, useRef, useEffect, useLayoutEffect, useState, useReducer, useCallback, memo, forwardRef, useMemo, Component, useSyncExternalStore, startTransition } from "react";
5
- import { isKeyedSegment, getNode, getParent, parentPath, getChildren, getNodeChildren } from "./_chunks-es/get-parent.js";
5
+ import { serializePath, isKeyedSegment, getNode, getParent, parentPath, getChildren, getNodeChildren } from "./_chunks-es/get-parent.js";
6
6
  import { isPath, getLeaf, isRange, isPoint, isObject, isLeafObject, getAncestor, pathContains, getSpan, isBeforePoint, getText, rangeIntersects, getTextBlock, getUnionSchema, getFirstChild } from "./_chunks-es/get-first-child.js";
7
7
  import { rangeEdges, isTextBlockNode, isBackwardRange, hasNode, getNodes, isAncestorPath, isEditableContainer, getSibling, isInline, isObject as isObject$1, isSpanNode, isBlock, getEnclosingBlock, getAncestors, getPathSubSchema, getBlock, resolveContainerAt, comparePaths, getEnclosingContainer, comparePoints$1 as comparePoints, isAfterPoint } from "./_chunks-es/get-path-sub-schema.js";
8
8
  import { isSpan, isTextBlock, compileSchema } from "@portabletext/schema";
@@ -21,9 +21,6 @@ import { markdownToPortableText, portableTextToMarkdown } from "@portabletext/ma
21
21
  import { applyAll, unset, set, insert, setIfMissing, diffMatchPatch as diffMatchPatch$1 } from "@portabletext/patches";
22
22
  import { EditorContext as EditorContext$1 } from "./_chunks-es/use-editor.js";
23
23
  import { useEditor } from "./_chunks-es/use-editor.js";
24
- function serializePath(path2) {
25
- return path2.reduce((result, segment, index) => isKeyedSegment(segment) ? `${result}[_key=="${segment._key}"]` : `${result}${index === 0 ? "" : "."}${segment}`, "");
26
- }
27
24
  function getDomNode(editor, path2) {
28
25
  const editorElement = editor.domElement;
29
26
  if (!editorElement)
@@ -32,7 +29,7 @@ function getDomNode(editor, path2) {
32
29
  return editorElement;
33
30
  const serializedPath = serializePath(path2), selector = `[data-pt-path="${CSS.escape(serializedPath)}"]`, blockSegment = path2[0];
34
31
  if (isKeyedSegment(blockSegment)) {
35
- const blockIndex = editor.blockIndexMap.get(blockSegment._key);
32
+ const blockIndex = editor.blockIndexMap.get(serializePath([blockSegment]));
36
33
  if (blockIndex !== void 0) {
37
34
  const blockNode = editorElement.children[blockIndex];
38
35
  if (blockNode instanceof HTMLElement) {
@@ -4089,6 +4086,22 @@ function getEventPosition({
4089
4086
  editorEngine,
4090
4087
  event
4091
4088
  }), eventSelection = getSelectionFromEvent(editorEngine, event) ?? null;
4089
+ if (eventBlockPath && eventPositionBlock && !eventSelection && isLeafObject(editorEngine.snapshot, eventNode, eventPath) && eventPath.length > eventBlockPath.length)
4090
+ return {
4091
+ block: eventPositionBlock,
4092
+ isEditor: !1,
4093
+ isContainer: !1,
4094
+ selection: {
4095
+ anchor: {
4096
+ path: eventPath,
4097
+ offset: 0
4098
+ },
4099
+ focus: {
4100
+ path: eventPath,
4101
+ offset: 0
4102
+ }
4103
+ }
4104
+ };
4092
4105
  if (eventBlock && eventBlockPath && eventPositionBlock && !eventSelection && !isEventContainer(editorEngine, eventNode, eventPath))
4093
4106
  return {
4094
4107
  block: eventPositionBlock,
@@ -7642,8 +7655,8 @@ const modifyDescendant = (editor, path2, f) => {
7642
7655
  if (rootNumericIndex !== void 0)
7643
7656
  rootIndex = rootNumericIndex;
7644
7657
  else if (keyedSegments.length > 0) {
7645
- const rootKey = keyedSegments[0]._key;
7646
- editor.blockIndexMap.has(rootKey) ? rootIndex = editor.blockIndexMap.get(rootKey) : rootIndex = findIndexByKey(editor.snapshot.context.value, rootKey);
7658
+ const rootSegment = keyedSegments[0], mapIndex = editor.blockIndexMap.get(serializePath([rootSegment]));
7659
+ rootIndex = mapIndex !== void 0 ? mapIndex : findIndexByKey(editor.snapshot.context.value, rootSegment._key);
7647
7660
  } else {
7648
7661
  const firstSegment = path2[0];
7649
7662
  rootIndex = typeof firstSegment == "number" ? firstSegment : -1;
@@ -7682,9 +7695,7 @@ function applyOperation(editor, op) {
7682
7695
  let {
7683
7696
  node
7684
7697
  } = op;
7685
- const isRootInsert = parentPath(path2).length === 0;
7686
- let insertIndex = -1;
7687
- if (modifyChildren(editor, parentPath(path2), (children) => {
7698
+ modifyChildren(editor, parentPath(path2), (children) => {
7688
7699
  !editor.isProcessingRemoteChanges && !editor.isUndoing && !editor.isRedoing && node._key !== void 0 && children.some((sibling) => sibling._key === node._key) && (node = {
7689
7700
  ...node,
7690
7701
  _key: editor.snapshot.context.keyGenerator()
@@ -7692,7 +7703,7 @@ function applyOperation(editor, op) {
7692
7703
  const lastSegment = path2[path2.length - 1];
7693
7704
  let index;
7694
7705
  if (isKeyedSegment(lastSegment)) {
7695
- const siblingIndex = resolveChildIndex$1(children, lastSegment._key, isRootInsert ? editor.blockIndexMap : void 0);
7706
+ const siblingIndex = resolveChildIndex$1(editor.blockIndexMap, path2.slice(0, -1), lastSegment, children);
7696
7707
  if (siblingIndex === -1)
7697
7708
  throw new Error(`Cannot apply an "insert" operation at path [${path2}] because the sibling was not found.`);
7698
7709
  index = op.position === "after" ? siblingIndex + 1 : siblingIndex;
@@ -7707,14 +7718,8 @@ function applyOperation(editor, op) {
7707
7718
  path: node._key !== void 0 ? replaceLastSegment(path2, {
7708
7719
  _key: node._key
7709
7720
  }) : path2
7710
- }), insertIndex = index, insertChildren(children, index, node);
7711
- }), isRootInsert && insertIndex !== -1) {
7712
- if (insertIndex < editor.blockIndexMap.size)
7713
- for (const [key, idx] of editor.blockIndexMap)
7714
- idx >= insertIndex && editor.blockIndexMap.set(key, idx + 1);
7715
- editor.blockIndexMap.set(node._key, insertIndex);
7716
- }
7717
- transformSelection = !0;
7721
+ }), insertChildren(children, index, node);
7722
+ }), transformSelection = !0;
7718
7723
  break;
7719
7724
  }
7720
7725
  case "insert.text": {
@@ -7768,14 +7773,7 @@ function applyOperation(editor, op) {
7768
7773
  };
7769
7774
  }
7770
7775
  if (path2.length === 0) {
7771
- if (Array.isArray(value)) {
7772
- editor.snapshot.context.value = value, editor.blockIndexMap.clear();
7773
- for (let i = 0; i < editor.snapshot.context.value.length; i++) {
7774
- const child = editor.snapshot.context.value[i];
7775
- child && editor.blockIndexMap.set(child._key, i);
7776
- }
7777
- }
7778
- transformSelection = !0;
7776
+ Array.isArray(value) && (editor.snapshot.context.value = value), transformSelection = !0;
7779
7777
  break;
7780
7778
  }
7781
7779
  const {
@@ -7791,20 +7789,17 @@ function applyOperation(editor, op) {
7791
7789
  if (getNode(editor.snapshot, setNodePath))
7792
7790
  if (setPropertyPath.length === 1) {
7793
7791
  const propertyName = setPropertyPath[0];
7794
- if (modifyDescendant(editor, setNodePath, (node) => ({
7792
+ modifyDescendant(editor, setNodePath, (node) => ({
7795
7793
  ...node,
7796
7794
  [propertyName]: value
7797
- })), propertyName === "_key" && setNodePath.length === 1 && op.inverse?.type === "set" && typeof op.inverse.value == "string" && typeof value == "string") {
7798
- const blockIndex = editor.blockIndexMap.get(op.inverse.value);
7799
- blockIndex !== void 0 && (editor.blockIndexMap.delete(op.inverse.value), editor.blockIndexMap.set(value, blockIndex));
7800
- }
7795
+ }));
7801
7796
  } else
7802
7797
  modifyDescendant(editor, setNodePath, (node) => deepSet(node, setPropertyPath, value));
7803
7798
  else {
7804
- const blockKey = findBlockKey(path2);
7805
- if (!blockKey)
7799
+ const blockSegment = findBlockSegment(path2);
7800
+ if (!blockSegment)
7806
7801
  break;
7807
- const blockIndex = resolveBlockIndex(editor, blockKey);
7802
+ const blockIndex = resolveBlockIndex(editor, blockSegment);
7808
7803
  if (blockIndex === -1)
7809
7804
  break;
7810
7805
  const block = editor.snapshot.context.value[blockIndex];
@@ -7825,7 +7820,7 @@ function applyOperation(editor, op) {
7825
7820
  type: "set",
7826
7821
  path: path2,
7827
7822
  value: editor.snapshot.context.value
7828
- }), editor.snapshot.context.value = [], editor.blockIndexMap.clear(), transformSelection = !0;
7823
+ }), editor.snapshot.context.value = [], transformSelection = !0;
7829
7824
  break;
7830
7825
  }
7831
7826
  const lastSegment = path2[path2.length - 1];
@@ -7868,11 +7863,9 @@ function applyOperation(editor, op) {
7868
7863
  backward: isBackwardRange(selection, editor.snapshot.context)
7869
7864
  } : null;
7870
7865
  }
7871
- const isRootRemove = parentPath(path2).length === 0;
7872
- let removeIndex = -1, removedKey;
7873
- if (modifyChildren(editor, parentPath(path2), (children) => {
7866
+ modifyChildren(editor, parentPath(path2), (children) => {
7874
7867
  let index;
7875
- if (isKeyedSegment(lastSegment) ? index = resolveChildIndex$1(children, lastSegment._key, isRootRemove ? editor.blockIndexMap : void 0) : index = lastSegment, index === -1 || index >= children.length)
7868
+ if (isKeyedSegment(lastSegment) ? index = resolveChildIndex$1(editor.blockIndexMap, path2.slice(0, -1), lastSegment, children) : index = lastSegment, index === -1 || index >= children.length)
7876
7869
  throw new Error(`Cannot apply an "unset" (node removal) operation at path [${path2}] because the node was not found.`);
7877
7870
  if (!op.inverse && !editor.isProcessingRemoteChanges) {
7878
7871
  const previousSibling = index > 0 ? children[index - 1] : void 0;
@@ -7890,12 +7883,8 @@ function applyOperation(editor, op) {
7890
7883
  position: "before"
7891
7884
  };
7892
7885
  }
7893
- return removedKey = children[index]?._key, removeIndex = index, removeChildren(children, index, 1);
7894
- }), isRootRemove && removeIndex !== -1 && removedKey) {
7895
- editor.blockIndexMap.delete(removedKey);
7896
- for (const [key, idx] of editor.blockIndexMap)
7897
- idx > removeIndex && editor.blockIndexMap.set(key, idx - 1);
7898
- }
7886
+ return removeChildren(children, index, 1);
7887
+ });
7899
7888
  break;
7900
7889
  }
7901
7890
  const {
@@ -7926,10 +7915,10 @@ function applyOperation(editor, op) {
7926
7915
  } else
7927
7916
  modifyDescendant(editor, unsetNodePath, (node) => deepUnset(node, unsetPropertyPath));
7928
7917
  else {
7929
- const blockKey = findBlockKey(path2);
7930
- if (!blockKey)
7918
+ const blockSegment = findBlockSegment(path2);
7919
+ if (!blockSegment)
7931
7920
  break;
7932
- const blockIndex = resolveBlockIndex(editor, blockKey);
7921
+ const blockIndex = resolveBlockIndex(editor, blockSegment);
7933
7922
  if (blockIndex === -1)
7934
7923
  break;
7935
7924
  const block = editor.snapshot.context.value[blockIndex];
@@ -7995,25 +7984,18 @@ function replaceLastSegment(path2, segment) {
7995
7984
  const result = [...path2];
7996
7985
  return result[result.length - 1] = segment, result;
7997
7986
  }
7998
- function resolveChildIndex$1(children, key, blockIndexMap) {
7999
- if (blockIndexMap) {
8000
- const index = blockIndexMap.get(key);
8001
- if (index !== void 0) {
8002
- const candidate = children[index];
8003
- if (candidate && candidate._key === key)
8004
- return index;
8005
- }
8006
- }
8007
- return children.findIndex((child) => child._key === key);
7987
+ function resolveChildIndex$1(blockIndexMap, parentSegments, segment, children) {
7988
+ const index = blockIndexMap.get(serializePath([...parentSegments, segment]));
7989
+ return index !== void 0 && children[index]?._key === segment._key ? index : children.findIndex((child) => child._key === segment._key);
8008
7990
  }
8009
- function findBlockKey(path2) {
7991
+ function findBlockSegment(path2) {
8010
7992
  const firstSegment = path2[0];
8011
7993
  if (isKeyedSegment(firstSegment))
8012
- return firstSegment._key;
7994
+ return firstSegment;
8013
7995
  }
8014
- function resolveBlockIndex(editor, blockKey) {
8015
- const mapIndex = editor.blockIndexMap.get(blockKey);
8016
- return mapIndex !== void 0 ? mapIndex : editor.snapshot.context.value.findIndex((child) => child._key === blockKey);
7996
+ function resolveBlockIndex(editor, segment) {
7997
+ const value = editor.snapshot.context.value, index = editor.blockIndexMap.get(serializePath([segment]));
7998
+ return index !== void 0 && value[index]?._key === segment._key ? index : value.findIndex((block) => block._key === segment._key);
8017
7999
  }
8018
8000
  function splitNodeAndPropertyPath(path2) {
8019
8001
  let lastKeyedOrNumericIndex = -1;
@@ -9202,18 +9184,47 @@ const shouldNormalize = (_editor, {
9202
9184
  const onContextChange = e.onContextChange;
9203
9185
  onContextChange && onContextChange(options), onChange(options);
9204
9186
  }, e;
9205
- }, levelIndexMaps = /* @__PURE__ */ new Map();
9187
+ };
9188
+ class BlockIndexMap extends Map {
9189
+ get(key) {
9190
+ return key.startsWith("[_key==") ? super.get(key) : super.get(serializePath([{
9191
+ _key: key
9192
+ }]));
9193
+ }
9194
+ has(key) {
9195
+ return key.startsWith("[_key==") ? super.has(key) : super.has(serializePath([{
9196
+ _key: key
9197
+ }]));
9198
+ }
9199
+ }
9200
+ const levelIndexMaps = /* @__PURE__ */ new Map();
9206
9201
  function buildIndexMaps(context, {
9207
9202
  blockIndexMap,
9208
9203
  listIndexMap
9209
9204
  }) {
9210
- blockIndexMap.clear(), listIndexMap.clear(), levelIndexMaps.clear();
9205
+ blockIndexMap.clear();
9206
+ for (let blockIndex = 0; blockIndex < context.value.length; blockIndex++) {
9207
+ const block = context.value.at(blockIndex);
9208
+ if (block === void 0 || block._key === void 0)
9209
+ continue;
9210
+ const blockPath = [{
9211
+ _key: block._key
9212
+ }], blockKey = serializePath(blockPath);
9213
+ blockIndexMap.has(blockKey) || blockIndexMap.set(blockKey, blockIndex), collectDescendantIndexes(context, block, blockPath, void 0, blockIndexMap);
9214
+ }
9215
+ buildListIndexMap(context, listIndexMap);
9216
+ }
9217
+ function buildListIndexMap(context, listIndexMap) {
9218
+ listIndexMap.clear(), levelIndexMaps.clear();
9211
9219
  let previousListItem;
9212
9220
  for (let blockIndex = 0; blockIndex < context.value.length; blockIndex++) {
9213
9221
  const block = context.value.at(blockIndex);
9214
9222
  if (block === void 0)
9215
9223
  continue;
9216
- if (blockIndexMap.set(block._key, blockIndex), !isTextBlockNode(context, block)) {
9224
+ const blockPath = [{
9225
+ _key: block._key
9226
+ }];
9227
+ if (!isTextBlockNode(context, block)) {
9217
9228
  levelIndexMaps.clear(), previousListItem = void 0;
9218
9229
  continue;
9219
9230
  }
@@ -9223,9 +9234,7 @@ function buildIndexMaps(context, {
9223
9234
  }
9224
9235
  if (!previousListItem) {
9225
9236
  const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
9226
- levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath([{
9227
- _key: block._key
9228
- }]), 1), previousListItem = {
9237
+ levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(blockPath), 1), previousListItem = {
9229
9238
  listItem: block.listItem,
9230
9239
  level: block.level
9231
9240
  };
@@ -9233,9 +9242,7 @@ function buildIndexMaps(context, {
9233
9242
  }
9234
9243
  if (previousListItem.listItem === block.listItem && previousListItem.level < block.level) {
9235
9244
  const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
9236
- levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath([{
9237
- _key: block._key
9238
- }]), 1), previousListItem = {
9245
+ levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(blockPath), 1), previousListItem = {
9239
9246
  listItem: block.listItem,
9240
9247
  level: block.level
9241
9248
  };
@@ -9252,14 +9259,25 @@ function buildIndexMaps(context, {
9252
9259
  });
9253
9260
  });
9254
9261
  const levelIndexMap = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map(), levelCounter = levelIndexMap.get(block.level) ?? 0;
9255
- levelIndexMap.set(block.level, levelCounter + 1), levelIndexMaps.set(block.listItem, levelIndexMap), listIndexMap.set(serializePath([{
9256
- _key: block._key
9257
- }]), levelCounter + 1), previousListItem = {
9262
+ levelIndexMap.set(block.level, levelCounter + 1), levelIndexMaps.set(block.listItem, levelIndexMap), listIndexMap.set(serializePath(blockPath), levelCounter + 1), previousListItem = {
9258
9263
  listItem: block.listItem,
9259
9264
  level: block.level
9260
9265
  };
9261
9266
  }
9262
9267
  }
9268
+ function collectDescendantIndexes(context, node, nodePath, parent, blockIndexMap) {
9269
+ const result = getNodeChildren(context, node, parent);
9270
+ if (result)
9271
+ for (let i = 0; i < result.children.length; i++) {
9272
+ const child = result.children[i];
9273
+ if (!child._key)
9274
+ continue;
9275
+ const childSegment = {
9276
+ _key: child._key
9277
+ }, childPath = [...nodePath, result.fieldName, childSegment], childKey = serializePath(childPath);
9278
+ blockIndexMap.has(childKey) || blockIndexMap.set(childKey, i), collectDescendantIndexes(context, child, childPath, result.parent, blockIndexMap);
9279
+ }
9280
+ }
9263
9281
  function withRemoteChanges(editor, fn) {
9264
9282
  const prev = editor.isProcessingRemoteChanges;
9265
9283
  editor.isProcessingRemoteChanges = !0, fn(), editor.isProcessingRemoteChanges = prev;
@@ -10243,7 +10261,7 @@ function textPatch(snapshot, operation, beforeValue) {
10243
10261
  containers: snapshot.context.containers,
10244
10262
  value: beforeValue
10245
10263
  },
10246
- blockIndexMap: /* @__PURE__ */ new Map()
10264
+ blockIndexMap: snapshot.blockIndexMap
10247
10265
  }, prevSpan = getSpan(beforeSnapshot, operation.path), patch = diffMatchPatch$1(prevSpan?.node.text ?? "", span.node.text, [...operation.path, "text"]);
10248
10266
  return patch.value.length ? [patch] : [];
10249
10267
  }
@@ -10294,6 +10312,279 @@ function subscribePatchGeneration({
10294
10312
  });
10295
10313
  });
10296
10314
  }
10315
+ function transformBlockIndexMap(map, op, beforeValue, afterValue, context) {
10316
+ switch (op.type) {
10317
+ case "insert.text":
10318
+ case "remove.text":
10319
+ case "set.selection":
10320
+ return;
10321
+ case "insert": {
10322
+ const lastSegment = op.path[op.path.length - 1], anchorIndex = typeof lastSegment == "number" ? lastSegment : resolveChildIndexInValue(beforeValue, op.path);
10323
+ if (anchorIndex < 0)
10324
+ return;
10325
+ const siblingContext = resolveSiblingContext(context, afterValue, op.path);
10326
+ if (!siblingContext)
10327
+ return;
10328
+ const insertIndex = Math.min(op.position === "after" ? anchorIndex + 1 : anchorIndex, siblingContext.children.length - 1);
10329
+ reindexSiblings(map, siblingContext, insertIndex);
10330
+ const insertedNumericPath = [...op.path.slice(0, -1), insertIndex];
10331
+ addSubtree(map, context, afterValue, insertedNumericPath);
10332
+ return;
10333
+ }
10334
+ case "unset": {
10335
+ if (op.path.length === 0) {
10336
+ map.clear();
10337
+ return;
10338
+ }
10339
+ const lastSegment = op.path[op.path.length - 1];
10340
+ if (typeof lastSegment == "string") {
10341
+ hasKeyedEntries(resolveValueAtPath(beforeValue, op.path)) && reconcileOwnerSubtree(map, context, beforeValue, afterValue, op.path);
10342
+ return;
10343
+ }
10344
+ const removeIndex = typeof lastSegment == "number" ? lastSegment : resolveChildIndexInValue(beforeValue, op.path);
10345
+ if (pruneSubtreeAtPath(map, beforeValue, op.path), removeIndex >= 0) {
10346
+ const siblingContext = resolveSiblingContext(context, afterValue, op.path);
10347
+ siblingContext && reindexSiblings(map, siblingContext, removeIndex);
10348
+ }
10349
+ return;
10350
+ }
10351
+ case "set": {
10352
+ if (op.path.length === 0) {
10353
+ map.clear(), buildIndexMaps({
10354
+ schema: context.schema,
10355
+ value: afterValue,
10356
+ containers: context.containers
10357
+ }, {
10358
+ blockIndexMap: map,
10359
+ listIndexMap: /* @__PURE__ */ new Map()
10360
+ });
10361
+ return;
10362
+ }
10363
+ const lastSegment = op.path[op.path.length - 1];
10364
+ if (typeof lastSegment == "string") {
10365
+ if (lastSegment === "_key") {
10366
+ handleKeyChange(map, beforeValue, afterValue, op.path.slice(0, -1), context);
10367
+ return;
10368
+ }
10369
+ (op.value !== null && typeof op.value == "object" || hasKeyedEntries(resolveValueAtPath(beforeValue, op.path))) && reconcileOwnerSubtree(map, context, beforeValue, afterValue, op.path);
10370
+ return;
10371
+ }
10372
+ const childIndex = resolveChildIndexInValue(beforeValue, op.path);
10373
+ pruneSubtreeAtPath(map, beforeValue, op.path), childIndex >= 0 && addSubtree(map, context, afterValue, [...op.path.slice(0, -1), childIndex]);
10374
+ return;
10375
+ }
10376
+ }
10377
+ }
10378
+ function resolveChildIndexInValue(value, path2) {
10379
+ let currentChildren = value;
10380
+ for (let i = 0; i < path2.length - 1; i++) {
10381
+ const segment = path2[i];
10382
+ if (typeof segment == "string")
10383
+ continue;
10384
+ let node;
10385
+ if (isKeyedSegment(segment) ? node = currentChildren.find((c2) => c2._key === segment._key) : typeof segment == "number" && (node = currentChildren.at(segment)), !node)
10386
+ return -1;
10387
+ const next = path2[i + 1];
10388
+ if (typeof next == "string") {
10389
+ const field = node[next];
10390
+ if (!Array.isArray(field))
10391
+ return -1;
10392
+ currentChildren = field, i++;
10393
+ }
10394
+ }
10395
+ const last = path2[path2.length - 1];
10396
+ return typeof last == "number" ? last : isKeyedSegment(last) ? currentChildren.findIndex((c2) => c2._key === last._key) : -1;
10397
+ }
10398
+ function resolveSiblingContext(context, value, opPath) {
10399
+ if (opPath.length === 1)
10400
+ return {
10401
+ children: value,
10402
+ serializedPrefix: ""
10403
+ };
10404
+ const fieldSegment = opPath[opPath.length - 2];
10405
+ if (typeof fieldSegment != "string")
10406
+ return;
10407
+ const keyedParentPath = toKeyedPath(value, parentPath(opPath));
10408
+ if (keyedParentPath === void 0)
10409
+ return;
10410
+ const resolvedParent = resolveIndexableNode(context, value, keyedParentPath);
10411
+ if (!resolvedParent)
10412
+ return;
10413
+ const childrenResult = getNodeChildren(context, resolvedParent.node, resolvedParent.containerOfParent);
10414
+ if (!(!childrenResult || childrenResult.fieldName !== fieldSegment))
10415
+ return {
10416
+ children: childrenResult.children,
10417
+ serializedPrefix: serializePath([...keyedParentPath, fieldSegment])
10418
+ };
10419
+ }
10420
+ function reindexSiblings(map, siblingContext, startIndex) {
10421
+ for (let childIndex = Math.max(0, startIndex); childIndex < siblingContext.children.length; childIndex++) {
10422
+ const child = siblingContext.children[childIndex];
10423
+ !child || child._key === void 0 || map.set(`${siblingContext.serializedPrefix}[_key=="${child._key}"]`, childIndex);
10424
+ }
10425
+ }
10426
+ function pruneSubtreeAtPath(map, beforeValue, nodePath, keepSelf = !1) {
10427
+ const node = resolveNodeAtPath(beforeValue, nodePath);
10428
+ if (!node)
10429
+ return;
10430
+ const keyedPath = toKeyedPath(beforeValue, nodePath);
10431
+ keyedPath !== void 0 && (keepSelf || map.delete(serializePath(keyedPath)), walkKeyedChildrenInValue(node, keyedPath, (childPath) => {
10432
+ map.delete(serializePath(childPath));
10433
+ }));
10434
+ }
10435
+ function walkKeyedChildrenInValue(node, nodePath, visit) {
10436
+ for (const key of Object.keys(node)) {
10437
+ const field = node[key];
10438
+ if (Array.isArray(field))
10439
+ for (const child of field) {
10440
+ if (!child || child._key === void 0)
10441
+ continue;
10442
+ const childPath = [...nodePath, key, {
10443
+ _key: child._key
10444
+ }];
10445
+ visit(childPath), walkKeyedChildrenInValue(child, childPath, visit);
10446
+ }
10447
+ }
10448
+ }
10449
+ function addSubtree(map, context, afterValue, opPath) {
10450
+ const keyedPath = toKeyedPath(afterValue, opPath);
10451
+ if (keyedPath === void 0)
10452
+ return;
10453
+ const resolved = resolveIndexableNode(context, afterValue, keyedPath);
10454
+ if (!resolved)
10455
+ return;
10456
+ const childIndex = resolveChildIndexInValue(afterValue, opPath);
10457
+ childIndex >= 0 && map.set(serializePath(keyedPath), childIndex), collectDescendantIndexes(context, resolved.node, keyedPath, resolved.containerOfParent, map);
10458
+ }
10459
+ function resolveIndexableNode(context, value, keyedPath) {
10460
+ if (keyedPath.length === 0)
10461
+ return;
10462
+ let current = {
10463
+ value
10464
+ }, containerOfParent, index = 0;
10465
+ for (; index < keyedPath.length; ) {
10466
+ const childrenResult = getNodeChildren(context, current, containerOfParent);
10467
+ if (!childrenResult)
10468
+ return;
10469
+ if (index > 0) {
10470
+ const fieldSegment = keyedPath[index];
10471
+ if (typeof fieldSegment != "string" || fieldSegment !== childrenResult.fieldName)
10472
+ return;
10473
+ index++;
10474
+ }
10475
+ const childSegment = keyedPath[index];
10476
+ let child;
10477
+ if (isKeyedSegment(childSegment) ? child = childrenResult.children.find((candidate) => candidate._key === childSegment._key) : typeof childSegment == "number" && (child = childrenResult.children.at(childSegment)), !child)
10478
+ return;
10479
+ current = child, containerOfParent = childrenResult.parent, index++;
10480
+ }
10481
+ return {
10482
+ node: current,
10483
+ containerOfParent
10484
+ };
10485
+ }
10486
+ function reconcileOwnerSubtree(map, context, beforeValue, afterValue, propertyPath) {
10487
+ let ownerPathEnd = propertyPath.length;
10488
+ for (; ownerPathEnd > 0 && typeof propertyPath[ownerPathEnd - 1] == "string"; )
10489
+ ownerPathEnd--;
10490
+ if (ownerPathEnd === 0)
10491
+ return;
10492
+ const ownerPath = propertyPath.slice(0, ownerPathEnd);
10493
+ pruneSubtreeAtPath(
10494
+ map,
10495
+ beforeValue,
10496
+ ownerPath,
10497
+ /*keepSelf*/
10498
+ !0
10499
+ ), addSubtree(map, context, afterValue, ownerPath);
10500
+ }
10501
+ function resolveValueAtPath(value, path2) {
10502
+ let nodePathEnd = path2.length;
10503
+ for (; nodePathEnd > 0 && typeof path2[nodePathEnd - 1] == "string"; )
10504
+ nodePathEnd--;
10505
+ if (nodePathEnd === 0)
10506
+ return;
10507
+ let current = resolveNodeAtPath(value, path2.slice(0, nodePathEnd));
10508
+ for (let i = nodePathEnd; i < path2.length; i++) {
10509
+ if (current === null || typeof current != "object")
10510
+ return;
10511
+ current = current[path2[i]];
10512
+ }
10513
+ return current;
10514
+ }
10515
+ function hasKeyedEntries(value) {
10516
+ return Array.isArray(value) && value.some((entry) => entry !== null && typeof entry == "object" && entry._key !== void 0);
10517
+ }
10518
+ function toKeyedPath(value, path2) {
10519
+ const result = [];
10520
+ let currentChildren = value, currentNode;
10521
+ for (let i = 0; i < path2.length; i++) {
10522
+ const segment = path2[i];
10523
+ if (typeof segment == "string") {
10524
+ if (result.push(segment), !currentNode)
10525
+ return;
10526
+ const field = currentNode[segment];
10527
+ if (!Array.isArray(field))
10528
+ return;
10529
+ currentChildren = field;
10530
+ continue;
10531
+ }
10532
+ if (typeof segment == "number") {
10533
+ if (currentNode = currentChildren.at(segment), !currentNode || currentNode._key === void 0)
10534
+ return;
10535
+ result.push({
10536
+ _key: currentNode._key
10537
+ });
10538
+ continue;
10539
+ }
10540
+ if (isKeyedSegment(segment)) {
10541
+ if (currentNode = currentChildren.find((c2) => c2._key === segment._key), !currentNode)
10542
+ return;
10543
+ result.push(segment);
10544
+ continue;
10545
+ }
10546
+ return;
10547
+ }
10548
+ return result;
10549
+ }
10550
+ function handleKeyChange(map, beforeValue, afterValue, nodePath, context) {
10551
+ pruneSubtreeAtPath(
10552
+ map,
10553
+ beforeValue,
10554
+ nodePath,
10555
+ /*keepSelf*/
10556
+ !1
10557
+ );
10558
+ const childIndex = resolveChildIndexInValue(beforeValue, nodePath);
10559
+ if (childIndex < 0)
10560
+ return;
10561
+ const newKeyedNodePath = [...nodePath.slice(0, -1), childIndex];
10562
+ addSubtree(map, context, afterValue, newKeyedNodePath);
10563
+ }
10564
+ function resolveNodeAtPath(value, path2) {
10565
+ let currentChildren = value, currentNode;
10566
+ for (let i = 0; i < path2.length; i++) {
10567
+ const segment = path2[i];
10568
+ if (typeof segment == "string") {
10569
+ if (!currentNode)
10570
+ return;
10571
+ const field = currentNode[segment];
10572
+ if (!Array.isArray(field))
10573
+ return;
10574
+ currentChildren = field;
10575
+ continue;
10576
+ }
10577
+ if (isKeyedSegment(segment))
10578
+ currentNode = currentChildren.find((c2) => c2._key === segment._key);
10579
+ else if (typeof segment == "number")
10580
+ currentNode = currentChildren.at(segment);
10581
+ else
10582
+ return;
10583
+ if (!currentNode)
10584
+ return;
10585
+ }
10586
+ return currentNode;
10587
+ }
10297
10588
  function subscribeUpdateValue(context, editor) {
10298
10589
  const unsubscribeNormalizationLog = debug.normalization.enabled ? subscribeToOperations(editor, (event) => {
10299
10590
  event.isNormalizingNode && debug.normalization(`((engine operation))
@@ -10302,13 +10593,13 @@ ${safeStringify(event.operation, 2)}`);
10302
10593
  phase: "before"
10303
10594
  }) : void 0, unsubscribeIndexMaps = subscribeToOperations(editor, (event) => {
10304
10595
  const operation = event.operation;
10305
- operation.type !== "set.selection" && (operation.type === "insert.text" || operation.type === "remove.text" || operation.path.length <= 2 && buildIndexMaps({
10596
+ operation.type !== "set.selection" && (operation.type === "insert.text" || operation.type === "remove.text" || (transformBlockIndexMap(editor.blockIndexMap, operation, event.beforeValue, editor.snapshot.context.value, {
10597
+ schema: context.schema,
10598
+ containers: editor.snapshot.context.containers
10599
+ }), operation.path.length <= 2 && buildListIndexMap({
10306
10600
  schema: context.schema,
10307
10601
  value: editor.snapshot.context.value
10308
- }, {
10309
- blockIndexMap: editor.blockIndexMap,
10310
- listIndexMap: editor.listIndexMap
10311
- }));
10602
+ }, editor.listIndexMap)));
10312
10603
  });
10313
10604
  return () => {
10314
10605
  unsubscribeNormalizationLog?.(), unsubscribeIndexMaps();
@@ -10316,7 +10607,7 @@ ${safeStringify(event.operation, 2)}`);
10316
10607
  }
10317
10608
  function createEditorEngine(config) {
10318
10609
  debug.setup("creating new editor engine instance");
10319
- const context = config.editorActor.getSnapshot().context, placeholderBlock = createPlaceholderBlock({
10610
+ const context = config.editorActor.getSnapshot().context, blockIndexMap = new BlockIndexMap(), placeholderBlock = createPlaceholderBlock({
10320
10611
  context: {
10321
10612
  schema: context.schema,
10322
10613
  // No containers registered at engine-init time. NodePlugin
@@ -10325,10 +10616,10 @@ function createEditorEngine(config) {
10325
10616
  value: [],
10326
10617
  keyGenerator: context.keyGenerator
10327
10618
  },
10328
- blockIndexMap: /* @__PURE__ */ new Map()
10619
+ blockIndexMap
10329
10620
  }), editor = createEditor();
10330
10621
  editor.snapshot = {
10331
- blockIndexMap: /* @__PURE__ */ new Map(),
10622
+ blockIndexMap,
10332
10623
  context: {
10333
10624
  containers: /* @__PURE__ */ new Map(),
10334
10625
  converters: context.initialConverters,
@@ -10339,7 +10630,7 @@ function createEditorEngine(config) {
10339
10630
  value: [placeholderBlock]
10340
10631
  },
10341
10632
  decoratorState: {}
10342
- }, editor.containers = /* @__PURE__ */ new Map(), editor.blockObjects = /* @__PURE__ */ new Map(), editor.inlineObjects = /* @__PURE__ */ new Map(), editor.spans = /* @__PURE__ */ new Map(), editor.textBlocks = /* @__PURE__ */ new Map(), editor.decoratedRanges = [], editor.blockIndexMap = editor.snapshot.blockIndexMap, editor.history = {
10633
+ }, editor.containers = /* @__PURE__ */ new Map(), editor.blockObjects = /* @__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 = {
10343
10634
  undos: [],
10344
10635
  redos: []
10345
10636
  }, editor.listIndexMap = /* @__PURE__ */ new Map(), editor.remotePatches = [], editor.undoStepId = void 0, editor.isDeferringMutations = !1, editor.isNormalizingNode = !1, editor.isPatching = !0, editor.isPerformingBehaviorOperation = !1, editor.isProcessingRemoteChanges = !1, editor.isRedoing = !1, editor.isUndoing = !1, editor.withHistory = !0;
@@ -10359,7 +10650,8 @@ function createEditorEngine(config) {
10359
10650
  editor: editorEngine
10360
10651
  }), buildIndexMaps({
10361
10652
  schema: context.schema,
10362
- value: editorEngine.snapshot.context.value
10653
+ value: editorEngine.snapshot.context.value,
10654
+ containers: editorEngine.snapshot.context.containers
10363
10655
  }, {
10364
10656
  blockIndexMap: editorEngine.blockIndexMap,
10365
10657
  listIndexMap: editorEngine.listIndexMap
@@ -14798,7 +15090,9 @@ const abstractDeserializeBehaviors = [
14798
15090
  })
14799
15091
  ];
14800
15092
  function getUniqueBlockKey(blockKey) {
14801
- return (snapshot) => !blockKey || snapshot.blockIndexMap.has(blockKey) ? snapshot.context.keyGenerator() : blockKey;
15093
+ return (snapshot) => !blockKey || snapshot.blockIndexMap.has(serializePath([{
15094
+ _key: blockKey
15095
+ }])) ? snapshot.context.keyGenerator() : blockKey;
14802
15096
  }
14803
15097
  function selectionAt(path2) {
14804
15098
  return {