@portabletext/editor 8.1.0 → 8.1.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
@@ -1,9 +1,9 @@
1
- import { a as getNodeChildren, i as getChildren, l as serializePath, n as parentPath, r as getNode, t as getParent, u as isKeyedSegment } from "./get-parent-Ci5241qs.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-CZd9VcVM.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-D1nM_ww9.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-B2fZcNok.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-DPnzucrd.js";
6
- import { n as isEmptyTextBlock, r as getTextBlockText, t as isEqualSelections } from "./util.is-equal-selections-N1hxVUbE.js";
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";
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";
@@ -7662,33 +7662,6 @@ function transformPointForMerge(point, mergePath, prevKey, position) {
7662
7662
  };
7663
7663
  }
7664
7664
  /**
7665
- * Create a placeholder text block -- the empty initial block used when the
7666
- * editor value is empty or when a container needs a default child.
7667
- *
7668
- * When `path` is provided and points into a container, the placeholder
7669
- * uses the container's default style. Without `path`, or at root depth,
7670
- * falls back to the root schema's first style.
7671
- */
7672
- function createPlaceholderBlock(snapshot, path) {
7673
- let style = resolveDefaultStyle(snapshot, path);
7674
- return {
7675
- _type: snapshot.context.schema.block.name,
7676
- _key: snapshot.context.keyGenerator(),
7677
- style,
7678
- markDefs: [],
7679
- children: [{
7680
- _type: snapshot.context.schema.span.name,
7681
- _key: snapshot.context.keyGenerator(),
7682
- text: "",
7683
- marks: []
7684
- }]
7685
- };
7686
- }
7687
- function resolveDefaultStyle(snapshot, path) {
7688
- let rootFallback = snapshot.context.schema.styles[0]?.name ?? "normal";
7689
- return path ? getPathSubSchema(snapshot, path).styles[0]?.name ?? rootFallback : rootFallback;
7690
- }
7691
- /**
7692
7665
  * Apply property changes at a known path using primitive `set` and `unset`
7693
7666
  * operations.
7694
7667
  *
@@ -7697,10 +7670,11 @@ function resolveDefaultStyle(snapshot, path) {
7697
7670
  * downstream patch consumers see the key change before any property
7698
7671
  * mutations that reference the new key.
7699
7672
  */
7700
- function setNodeProperties(editor, props, path) {
7701
- let nodeEntry = getNode(editor.snapshot, path);
7702
- if (!nodeEntry) return;
7703
- let nodeRecord = nodeEntry.node, propsRecord = props, keys = Object.keys(propsRecord), keyIndex = keys.indexOf("_key");
7673
+ function applyNodeProperties(editor, props, path) {
7674
+ let result = resolveNode(editor.snapshot, path);
7675
+ if (result.status === "unreachable") throw Error(`Unable to apply properties at structurally unreachable path ${safeStringify(path)}`);
7676
+ if (result.status === "missing") return;
7677
+ let nodeRecord = result.entry.node, propsRecord = props, keys = Object.keys(propsRecord), keyIndex = keys.indexOf("_key");
7704
7678
  keyIndex !== -1 && (keys.splice(keyIndex, 1), keys.unshift("_key"));
7705
7679
  let currentPath = path;
7706
7680
  for (let key of keys) if (propsRecord[key] !== nodeRecord[key]) if (propsRecord[key] != null) {
@@ -7729,6 +7703,33 @@ function setNodeProperties(editor, props, path) {
7729
7703
  });
7730
7704
  }
7731
7705
  /**
7706
+ * Create a placeholder text block -- the empty initial block used when the
7707
+ * editor value is empty or when a container needs a default child.
7708
+ *
7709
+ * When `path` is provided and points into a container, the placeholder
7710
+ * uses the container's default style. Without `path`, or at root depth,
7711
+ * falls back to the root schema's first style.
7712
+ */
7713
+ function createPlaceholderBlock(snapshot, path) {
7714
+ let style = resolveDefaultStyle(snapshot, path);
7715
+ return {
7716
+ _type: snapshot.context.schema.block.name,
7717
+ _key: snapshot.context.keyGenerator(),
7718
+ style,
7719
+ markDefs: [],
7720
+ children: [{
7721
+ _type: snapshot.context.schema.span.name,
7722
+ _key: snapshot.context.keyGenerator(),
7723
+ text: "",
7724
+ marks: []
7725
+ }]
7726
+ };
7727
+ }
7728
+ function resolveDefaultStyle(snapshot, path) {
7729
+ let rootFallback = snapshot.context.schema.styles[0]?.name ?? "normal";
7730
+ return path ? getPathSubSchema(snapshot, path).styles[0]?.name ?? rootFallback : rootFallback;
7731
+ }
7732
+ /**
7732
7733
  * Read the `_type` from a pre-resolved `of` entry.
7733
7734
  */
7734
7735
  function entryType(entry) {
@@ -7959,7 +7960,7 @@ const normalizeNode = (editor, entry) => {
7959
7960
  * Add missing .markDefs to text block nodes
7960
7961
  */
7961
7962
  if (!editor.isProcessingRemoteChanges && isTextBlockNode({ schema: editor.snapshot.context.schema }, node) && !Array.isArray(node.markDefs)) {
7962
- debug.normalization("adding .markDefs to block node"), setNodeProperties(editor, { markDefs: [] }, path);
7963
+ debug.normalization("adding .markDefs to block node"), applyNodeProperties(editor, { markDefs: [] }, path);
7963
7964
  return;
7964
7965
  }
7965
7966
  /**
@@ -7968,7 +7969,7 @@ const normalizeNode = (editor, entry) => {
7968
7969
  if (!editor.isProcessingRemoteChanges && isTextBlockNode({ schema: editor.snapshot.context.schema }, node) && node.style === void 0) {
7969
7970
  let defaultStyle = getPathSubSchema(editor.snapshot, path).styles.at(0)?.name;
7970
7971
  if (defaultStyle) {
7971
- debug.normalization("adding .style to block node"), setNodeProperties(editor, { style: defaultStyle }, path);
7972
+ debug.normalization("adding .style to block node"), applyNodeProperties(editor, { style: defaultStyle }, path);
7972
7973
  return;
7973
7974
  }
7974
7975
  }
@@ -7991,7 +7992,7 @@ const normalizeNode = (editor, entry) => {
7991
7992
  * Add missing .marks to span nodes
7992
7993
  */
7993
7994
  if (!editor.isProcessingRemoteChanges && isSpan({ schema: editor.snapshot.context.schema }, node) && !Array.isArray(node.marks)) {
7994
- debug.normalization("Adding .marks to span node"), setNodeProperties(editor, { marks: [] }, path);
7995
+ debug.normalization("Adding .marks to span node"), applyNodeProperties(editor, { marks: [] }, path);
7995
7996
  return;
7996
7997
  }
7997
7998
  /**
@@ -8002,7 +8003,7 @@ const normalizeNode = (editor, entry) => {
8002
8003
  if (!blockEntry) return;
8003
8004
  let annotations = node.marks?.filter((mark) => blockEntry.node.markDefs?.some((markDef) => markDef._key === mark));
8004
8005
  if (node.text === "" && annotations && annotations.length > 0) {
8005
- debug.normalization("removing annotations from empty span node"), setNodeProperties(editor, { marks: node.marks?.filter((mark) => !annotations.includes(mark)) }, path);
8006
+ debug.normalization("removing annotations from empty span node"), applyNodeProperties(editor, { marks: node.marks?.filter((mark) => !annotations.includes(mark)) }, path);
8006
8007
  return;
8007
8008
  }
8008
8009
  }
@@ -8013,7 +8014,7 @@ const normalizeNode = (editor, entry) => {
8013
8014
  let markDefs = node.markDefs ?? [], markDefKeys = /* @__PURE__ */ new Set(), newMarkDefs = [];
8014
8015
  for (let markDef of markDefs) markDefKeys.has(markDef._key) || (markDefKeys.add(markDef._key), newMarkDefs.push(markDef));
8015
8016
  if (markDefs.length !== newMarkDefs.length) {
8016
- debug.normalization("removing duplicate markDefs"), setNodeProperties(editor, { markDefs: newMarkDefs }, path);
8017
+ debug.normalization("removing duplicate markDefs"), applyNodeProperties(editor, { markDefs: newMarkDefs }, path);
8017
8018
  return;
8018
8019
  }
8019
8020
  }
@@ -8023,7 +8024,7 @@ const normalizeNode = (editor, entry) => {
8023
8024
  if (!editor.isProcessingRemoteChanges && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
8024
8025
  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)));
8025
8026
  if (node.markDefs && !isEqualMarkDefs(newMarkDefs, node.markDefs)) {
8026
- debug.normalization("removing markDef not in use"), setNodeProperties(editor, { markDefs: newMarkDefs }, path);
8027
+ debug.normalization("removing markDef not in use"), applyNodeProperties(editor, { markDefs: newMarkDefs }, path);
8027
8028
  return;
8028
8029
  }
8029
8030
  }
@@ -8063,11 +8064,11 @@ const normalizeNode = (editor, entry) => {
8063
8064
  _type: firstChildType.type === "object" && "name" in firstChildType ? firstChildType.name : firstChildType.type,
8064
8065
  _key: editor.snapshot.context.keyGenerator()
8065
8066
  }), needsField && childNode) {
8066
- setNodeProperties(editor, { [arrayField.name]: [childNode] }, path);
8067
+ applyNodeProperties(editor, { [arrayField.name]: [childNode] }, path);
8067
8068
  return;
8068
8069
  }
8069
8070
  if (needsField) {
8070
- setNodeProperties(editor, { [arrayField.name]: [] }, path);
8071
+ applyNodeProperties(editor, { [arrayField.name]: [] }, path);
8071
8072
  return;
8072
8073
  }
8073
8074
  if (childNode) {
@@ -11189,7 +11190,7 @@ const addAnnotationOperationImplementation = ({ snapshot, operation }) => {
11189
11190
  for (let { node: block, path: blockPath } of selectedBlocks) {
11190
11191
  if (!isTextBlock({ schema: editor.snapshot.context.schema }, block) || block.children.length === 0 || block.children.length === 1 && block.children[0]?.text === "" || !getPathSubSchema(snapshot, blockPath).annotations.some((annotation) => annotation.name === parsedAnnotation._type)) continue;
11191
11192
  let annotationKey = blockIndex === 0 ? parsedAnnotation._key : context.keyGenerator(), markDefs = block.markDefs ?? [];
11192
- markDefs.find((markDef) => markDef._type === parsedAnnotation._type && markDef._key === annotationKey) === void 0 && setNodeProperties(editor, { markDefs: [...markDefs, {
11193
+ markDefs.find((markDef) => markDef._type === parsedAnnotation._type && markDef._key === annotationKey) === void 0 && applyNodeProperties(editor, { markDefs: [...markDefs, {
11193
11194
  ...parsedAnnotation,
11194
11195
  _key: annotationKey
11195
11196
  }] }, blockPath);
@@ -11207,7 +11208,7 @@ const addAnnotationOperationImplementation = ({ snapshot, operation }) => {
11207
11208
  for (let { node: span, path: spanPath } of children) {
11208
11209
  if (!isSpan({ schema: editor.snapshot.context.schema }, span) || !selectionRange || !rangeIntersects(editor.snapshot, selectionRange, spanPath)) continue;
11209
11210
  let marks = span.marks ?? [];
11210
- setNodeProperties(editor, { marks: [...marks, annotationKey] }, spanPath);
11211
+ applyNodeProperties(editor, { marks: [...marks, annotationKey] }, spanPath);
11211
11212
  }
11212
11213
  blockIndex++;
11213
11214
  }
@@ -11245,7 +11246,7 @@ const removeAnnotationOperationImplementation = ({ snapshot, operation }) => {
11245
11246
  ...previousSpansWithSameAnnotation,
11246
11247
  [selectedChild, selectedChildPath],
11247
11248
  ...nextSpansWithSameAnnotation
11248
- ]) setNodeProperties(editor, { marks: child.marks?.filter((mark) => mark !== annotationToRemove) }, childPath);
11249
+ ]) applyNodeProperties(editor, { marks: child.marks?.filter((mark) => mark !== annotationToRemove) }, childPath);
11249
11250
  } else {
11250
11251
  let ref = at ? rangeRef(editor, at, { affinity: "inward" }) : null;
11251
11252
  withoutNormalizing(editor, () => {
@@ -11270,7 +11271,7 @@ const removeAnnotationOperationImplementation = ({ snapshot, operation }) => {
11270
11271
  for (let { node: child, path: childPath } of children) {
11271
11272
  if (!isSpan({ schema: editor.snapshot.context.schema }, child) || !selectionRange || !rangeIntersects(editor.snapshot, selectionRange, childPath)) continue;
11272
11273
  let markDefs = block.markDefs ?? [], marks = child.marks ?? [], marksWithoutAnnotation = marks.filter((mark) => markDefs.find((markDef) => markDef._key === mark)?._type !== operation.annotation.name);
11273
- marksWithoutAnnotation.length !== marks.length && setNodeProperties(editor, { marks: marksWithoutAnnotation }, childPath);
11274
+ marksWithoutAnnotation.length !== marks.length && applyNodeProperties(editor, { marks: marksWithoutAnnotation }, childPath);
11274
11275
  }
11275
11276
  }
11276
11277
  }), ref?.unref();
@@ -11333,7 +11334,7 @@ const blockSetOperationImplementation = ({ snapshot, operation }) => {
11333
11334
  }
11334
11335
  context.schema.block.fields?.some((field) => field.name === key) && (filteredProps[key] = operation.props[key]);
11335
11336
  }
11336
- setNodeProperties(operation.editor, filteredProps, blockEntry.path);
11337
+ applyNodeProperties(operation.editor, filteredProps, blockEntry.path);
11337
11338
  } else {
11338
11339
  let schemaDefinition = getBlockObjectSchema(snapshot, engineBlock, blockEntry.path), filteredProps = {};
11339
11340
  for (let key of Object.keys(operation.props)) if (key !== "_type") {
@@ -11344,7 +11345,7 @@ const blockSetOperationImplementation = ({ snapshot, operation }) => {
11344
11345
  schemaDefinition?.fields?.some((field) => field.name === key) && (filteredProps[key] = operation.props[key]);
11345
11346
  }
11346
11347
  let patches = Object.entries(filteredProps).map(([key, value]) => set(value, [key])), updatedEngineBlock = applyAll(engineBlock, patches);
11347
- setNodeProperties(operation.editor, updatedEngineBlock, blockEntry.path);
11348
+ applyNodeProperties(operation.editor, updatedEngineBlock, blockEntry.path);
11348
11349
  }
11349
11350
  }, blockUnsetOperationImplementation = ({ snapshot, operation }) => {
11350
11351
  let { context } = snapshot, blockEntry = getNode(operation.editor.snapshot, operation.at);
@@ -11353,12 +11354,12 @@ const blockSetOperationImplementation = ({ snapshot, operation }) => {
11353
11354
  if (isTextBlockNode(context, engineBlock)) {
11354
11355
  let propsToRemove = operation.props.filter((prop) => prop !== "_type" && prop !== "_key"), unsetProps = {};
11355
11356
  for (let prop of propsToRemove) unsetProps[prop] = null;
11356
- setNodeProperties(operation.editor, unsetProps, blockEntry.path), operation.props.includes("_key") && setNodeProperties(operation.editor, { _key: context.keyGenerator() }, blockEntry.path);
11357
+ applyNodeProperties(operation.editor, unsetProps, blockEntry.path), operation.props.includes("_key") && applyNodeProperties(operation.editor, { _key: context.keyGenerator() }, blockEntry.path);
11357
11358
  return;
11358
11359
  }
11359
11360
  let unsetProps = {};
11360
11361
  for (let key of operation.props) key !== "_type" && (key === "_key" ? unsetProps._key = context.keyGenerator() : unsetProps[key] = null);
11361
- setNodeProperties(operation.editor, unsetProps, blockEntry.path);
11362
+ applyNodeProperties(operation.editor, unsetProps, blockEntry.path);
11362
11363
  };
11363
11364
  /**
11364
11365
  * Compute the canonical path that a new node will have when inserted as a
@@ -11385,7 +11386,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11385
11386
  let { node: child, path: childPath } = childEntry;
11386
11387
  if (isSpan({ schema: operation.editor.snapshot.context.schema }, child)) {
11387
11388
  let { _type, text, ...rest } = operation.props;
11388
- setNodeProperties(operation.editor, {
11389
+ applyNodeProperties(operation.editor, {
11389
11390
  ...child,
11390
11391
  ...rest
11391
11392
  }, childPath);
@@ -11408,7 +11409,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11408
11409
  if (!definition) return;
11409
11410
  let { _type, _key, ...rest } = operation.props;
11410
11411
  for (let prop in rest) definition.fields.some((field) => field.name === prop) || delete rest[prop];
11411
- setNodeProperties(operation.editor, {
11412
+ applyNodeProperties(operation.editor, {
11412
11413
  ...child,
11413
11414
  _key: typeof _key == "string" ? _key : child._key,
11414
11415
  ...rest
@@ -11429,13 +11430,13 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11429
11430
  }
11430
11431
  newNode[prop] = null;
11431
11432
  }
11432
- setNodeProperties(operation.editor, newNode, childPath);
11433
+ applyNodeProperties(operation.editor, newNode, childPath);
11433
11434
  return;
11434
11435
  }
11435
11436
  if (isObject(operation.editor.snapshot, child)) {
11436
11437
  let unsetProps = {};
11437
11438
  for (let prop of operation.props) prop !== "_type" && (prop === "_key" ? unsetProps._key = context.keyGenerator() : unsetProps[prop] = null);
11438
- setNodeProperties(operation.editor, unsetProps, childPath);
11439
+ applyNodeProperties(operation.editor, unsetProps, childPath);
11439
11440
  return;
11440
11441
  }
11441
11442
  throw Error(`Unable to determine the type of child at ${safeStringify(operation.at)}`);
@@ -11458,7 +11459,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11458
11459
  let blockPath = parentPath(spanPath);
11459
11460
  if (!getPathSubSchema(snapshot, blockPath).decorators.some((decorator) => decorator.name === mark)) continue;
11460
11461
  let marks = [...(Array.isArray(node.marks) ? node.marks : []).filter((eMark) => eMark !== mark), mark];
11461
- setNodeProperties(editor, { marks }, spanPath);
11462
+ applyNodeProperties(editor, { marks }, spanPath);
11462
11463
  }
11463
11464
  });
11464
11465
  } else {
@@ -11477,7 +11478,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11477
11478
  for (let { path: spanPath } of Array.from(getNodes(editor.snapshot, {
11478
11479
  at: blockPath,
11479
11480
  match: (node) => isSpan({ schema: editor.snapshot.context.schema }, node)
11480
- }))) setNodeProperties(editor, { marks: newMarks }, spanPath);
11481
+ }))) applyNodeProperties(editor, { marks: newMarks }, spanPath);
11481
11482
  } else editor.snapshot.decoratorState[mark] = !0;
11482
11483
  }
11483
11484
  if (editor.snapshot.context.selection) {
@@ -11506,7 +11507,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11506
11507
  for (let { node, path: nodePath } of splitTextNodes) {
11507
11508
  if (!isSpan({ schema: editor.snapshot.context.schema }, node)) continue;
11508
11509
  let blockPath = parentPath(nodePath), block = getNode(editor.snapshot, blockPath)?.node;
11509
- isTextBlock({ schema: editor.snapshot.context.schema }, block) && block.children.includes(node) && setNodeProperties(editor, {
11510
+ isTextBlock({ schema: editor.snapshot.context.schema }, block) && block.children.includes(node) && applyNodeProperties(editor, {
11510
11511
  marks: (Array.isArray(node.marks) ? node.marks : []).filter((eMark) => eMark !== mark),
11511
11512
  _type: context.schema.span.name
11512
11513
  }, nodePath);
@@ -11522,7 +11523,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11522
11523
  for (let { path: spanPath } of Array.from(getNodes(editor.snapshot, {
11523
11524
  at: blockPath,
11524
11525
  match: (node) => isSpan({ schema: editor.snapshot.context.schema }, node)
11525
- }))) setNodeProperties(editor, { marks: existingMarksWithoutDecorator }, spanPath);
11526
+ }))) applyNodeProperties(editor, { marks: existingMarksWithoutDecorator }, spanPath);
11526
11527
  } else editor.snapshot.decoratorState[mark] = !1;
11527
11528
  }
11528
11529
  if (editor.snapshot.context.selection) {
@@ -11637,21 +11638,31 @@ function fieldAcceptsTextBlock(editor, node, _path) {
11637
11638
  * `destinationBlock` by key. Any child key the merging block shares with
11638
11639
  * the destination has to be renamed before the merge, or the engine's own
11639
11640
  * collision handling mints a fresh key for it, which reads on the wire as
11640
- * that node being destroyed and a new one created instead of moved. There
11641
- * is no such backstop for markDefs: an unrenamed collision either loses
11642
- * one of the two defs to last-wins replacement, or, on the `insert.block`
11643
- * path, gets silently re-minted by `adjustFragmentKeys` (see
11644
- * `dedupeEqualMarkDefs` below).
11641
+ * that node being destroyed and a new one created instead of moved.
11642
+ *
11643
+ * A colliding markDef that is deeply equal to the destination's is left
11644
+ * unrenamed and reported in `dedupedMarkDefKeys` instead: the merge keeps
11645
+ * a single copy under the original `_key` rather than duplicating
11646
+ * identical content under two keys. A colliding markDef that differs gets
11647
+ * renamed like a child would.
11648
+ *
11649
+ * `renamedBlock` keeps every deduped def in its own `markDefs`, even
11650
+ * though the destination already carries it: `renamedBlock` feeds
11651
+ * `insert.block` on some callers' paths, and that path parses the block
11652
+ * standalone, stripping any mark that doesn't resolve in the block's own
11653
+ * `markDefs`. A caller that appends `renamedBlock.markDefs` onto the
11654
+ * destination's must skip the keys listed in `dedupedMarkDefKeys`, or the
11655
+ * def duplicates.
11645
11656
  *
11646
11657
  * Pure: computes the renames and the block they produce without touching
11647
11658
  * an editor. Callers raise or apply the renames themselves, ahead of the
11648
11659
  * merge, against the still-living `mergingBlock`.
11649
11660
  */
11650
11661
  function planMergeKeyRenames(args) {
11651
- let { context, mergingBlock, destinationBlock, dedupeEqualMarkDefs } = args, destinationChildKeys = new Set(destinationBlock.children.map((child) => child._key)), destinationMarkDefsByKey = new Map((destinationBlock.markDefs ?? []).map((markDef) => [markDef._key, markDef])), markDefKeyMap = /* @__PURE__ */ new Map(), renamedMarkDefs = mergingBlock.markDefs?.flatMap((markDef) => {
11662
+ let { context, mergingBlock, destinationBlock } = args, destinationChildKeys = new Set(destinationBlock.children.map((child) => child._key)), destinationMarkDefsByKey = new Map((destinationBlock.markDefs ?? []).map((markDef) => [markDef._key, markDef])), markDefKeyMap = /* @__PURE__ */ new Map(), dedupedMarkDefKeys = [], renamedMarkDefs = mergingBlock.markDefs?.flatMap((markDef) => {
11652
11663
  let destinationMarkDef = destinationMarkDefsByKey.get(markDef._key);
11653
11664
  if (!destinationMarkDef) return [markDef];
11654
- if (dedupeEqualMarkDefs && isDeepEqual(markDef, destinationMarkDef)) return [];
11665
+ if (isDeepEqual(markDef, destinationMarkDef)) return dedupedMarkDefKeys.push(markDef._key), [markDef];
11655
11666
  let newKey = context.keyGenerator();
11656
11667
  return markDefKeyMap.set(markDef._key, newKey), [{
11657
11668
  ...markDef,
@@ -11686,7 +11697,8 @@ function planMergeKeyRenames(args) {
11686
11697
  ...mergingBlock.markDefs ? { markDefs: renamedMarkDefs } : {}
11687
11698
  },
11688
11699
  childRenames,
11689
- markDefRenames
11700
+ markDefRenames,
11701
+ dedupedMarkDefKeys
11690
11702
  };
11691
11703
  }
11692
11704
  /**
@@ -12022,11 +12034,10 @@ function mergeBlock(editor, startBlockPath, endBlockPath, removeEmptyStartBlock)
12022
12034
  removeNodeAt(editor, startBlockPath);
12023
12035
  return;
12024
12036
  }
12025
- let { renamedBlock, childRenames, markDefRenames } = planMergeKeyRenames({
12037
+ let { renamedBlock, childRenames, markDefRenames, dedupedMarkDefKeys } = planMergeKeyRenames({
12026
12038
  context: editor.snapshot.context,
12027
12039
  mergingBlock: endBlock.node,
12028
- destinationBlock: startBlock.node,
12029
- dedupeEqualMarkDefs: !0
12040
+ destinationBlock: startBlock.node
12030
12041
  });
12031
12042
  for (let { markDefKey, newKey } of markDefRenames) editor.apply({
12032
12043
  type: "set",
@@ -12038,13 +12049,13 @@ function mergeBlock(editor, startBlockPath, endBlockPath, removeEmptyStartBlock)
12038
12049
  ],
12039
12050
  value: newKey
12040
12051
  });
12041
- for (let { childKey, props } of childRenames) setNodeProperties(editor, props, [
12052
+ for (let { childKey, props } of childRenames) applyNodeProperties(editor, props, [
12042
12053
  ...endBlockPath,
12043
12054
  "children",
12044
12055
  { _key: childKey }
12045
12056
  ]);
12046
- let endMarkDefs = renamedBlock.markDefs;
12047
- Array.isArray(endMarkDefs) && endMarkDefs.length > 0 && setNodeProperties(editor, { markDefs: [...startBlock.node.markDefs ?? [], ...endMarkDefs] }, startBlockPath), applyMergeNode(editor, endBlockPath, startBlock.node.children.length);
12057
+ let endMarkDefs = renamedBlock.markDefs?.filter((markDef) => !dedupedMarkDefKeys.includes(markDef._key));
12058
+ Array.isArray(endMarkDefs) && endMarkDefs.length > 0 && applyNodeProperties(editor, { markDefs: [...startBlock.node.markDefs ?? [], ...endMarkDefs] }, startBlockPath), applyMergeNode(editor, endBlockPath, startBlock.node.children.length);
12048
12059
  }
12049
12060
  function removeNodeAt(editor, path) {
12050
12061
  getNode(editor.snapshot, path) && editor.apply({
@@ -12733,7 +12744,7 @@ function mergeTextBlockFragment(args) {
12733
12744
  block,
12734
12745
  endBlock
12735
12746
  });
12736
- setNodeProperties(editor, { markDefs: [...endBlock.markDefs ?? [], ...adjustedMarkDefs ?? []] }, endBlockPath);
12747
+ applyNodeProperties(editor, { markDefs: [...endBlock.markDefs ?? [], ...adjustedMarkDefs ?? []] }, endBlockPath);
12737
12748
  let atPathRef = pathRef(editor, at.path), atBlockStart = pointEquals(at, start(editor, endBlockPath)), firstInsertedKey = insertFragmentChildren(editor, adjustedBlock, at), resolvedAtPath = atPathRef.unref();
12738
12749
  if (select === "none") {
12739
12750
  (wasCrossBlock || !atBlockStart) && applySelect(editor, at);
@@ -12841,8 +12852,12 @@ function resolveChildIndex(children, segment) {
12841
12852
  }
12842
12853
  /**
12843
12854
  * Reassign keys on spans, inline objects and markDefs that collide with the
12844
- * end block's existing keys. Returns the adjusted block and the adjusted
12845
- * markDefs (to be merged into the end block).
12855
+ * end block's existing keys. A colliding markDef that is deeply equal to
12856
+ * the end block's is left out of the returned `adjustedMarkDefs` instead
12857
+ * of renamed, since the end block already carries it; its key isn't
12858
+ * remapped, so the fragment's marks keep pointing at it unchanged. The
12859
+ * caller must merge the returned `adjustedMarkDefs` into the end block's
12860
+ * own `markDefs`, or the deduped defs are lost.
12846
12861
  */
12847
12862
  function adjustFragmentKeys(args) {
12848
12863
  let { context, block, endBlock } = args;
@@ -12854,15 +12869,15 @@ function adjustFragmentKeys(args) {
12854
12869
  adjustedBlock: block,
12855
12870
  adjustedMarkDefs: block.markDefs
12856
12871
  };
12857
- let endBlockChildKeys = endBlock.children.map((child) => child._key), endBlockMarkDefsKeys = endBlock.markDefs?.map((markDef) => markDef._key) ?? [], markDefKeyMap = /* @__PURE__ */ new Map(), adjustedMarkDefs = block.markDefs?.map((markDef) => {
12858
- if (endBlockMarkDefsKeys.includes(markDef._key)) {
12859
- let newKey = context.keyGenerator();
12860
- return markDefKeyMap.set(markDef._key, newKey), {
12861
- ...markDef,
12862
- _key: newKey
12863
- };
12864
- }
12865
- return markDef;
12872
+ let endBlockChildKeys = endBlock.children.map((child) => child._key), endBlockMarkDefsByKey = new Map((endBlock.markDefs ?? []).map((markDef) => [markDef._key, markDef])), markDefKeyMap = /* @__PURE__ */ new Map(), adjustedMarkDefs = block.markDefs?.flatMap((markDef) => {
12873
+ let endBlockMarkDef = endBlockMarkDefsByKey.get(markDef._key);
12874
+ if (!endBlockMarkDef) return [markDef];
12875
+ if (isDeepEqual(markDef, endBlockMarkDef)) return [];
12876
+ let newKey = context.keyGenerator();
12877
+ return markDefKeyMap.set(markDef._key, newKey), [{
12878
+ ...markDef,
12879
+ _key: newKey
12880
+ }];
12866
12881
  }), adjustedChildren = block.children.map((child) => {
12867
12882
  if (isSpan(context, child)) {
12868
12883
  let marks = child.marks?.map((mark) => markDefKeyMap.get(mark) ?? mark) ?? [];
@@ -13437,8 +13452,7 @@ function planMergeKeyRenameActions(args) {
13437
13452
  let { context, mergingBlockPath, mergingBlock, destinationBlock } = args, { renamedBlock, childRenames, markDefRenames } = planMergeKeyRenames({
13438
13453
  context,
13439
13454
  mergingBlock,
13440
- destinationBlock,
13441
- dedupeEqualMarkDefs: !1
13455
+ destinationBlock
13442
13456
  }), renameActions = [];
13443
13457
  for (let { markDefKey, newKey } of markDefRenames) renameActions.push(raise$1({
13444
13458
  type: "set",
@@ -16369,13 +16383,13 @@ function replaceBlock({ context, editorEngine, block, index }) {
16369
16383
  }
16370
16384
  function updateBlock({ context, editorEngine, oldEngineBlock, block, index: _index }) {
16371
16385
  let engineBlock = toEngineBlock(block, { schemaTypes: context.schema }), { children: _children, ...blockProps } = engineBlock;
16372
- setNodeProperties(editorEngine, blockProps, [{ _key: oldEngineBlock._key }]);
16386
+ applyNodeProperties(editorEngine, blockProps, [{ _key: oldEngineBlock._key }]);
16373
16387
  let oldRecord = oldEngineBlock, newRecord = engineBlock, removedProperties = {};
16374
16388
  for (let key of Object.keys(oldRecord)) key !== "children" && key !== "text" && (newRecord.hasOwnProperty(key) || (removedProperties[key] = null));
16375
- if (Object.keys(removedProperties).length > 0 && setNodeProperties(editorEngine, removedProperties, [{ _key: oldEngineBlock._key }]), isTextBlock({ schema: editorEngine.snapshot.context.schema }, engineBlock) && isTextBlock({ schema: editorEngine.snapshot.context.schema }, oldEngineBlock)) {
16389
+ if (Object.keys(removedProperties).length > 0 && applyNodeProperties(editorEngine, removedProperties, [{ _key: oldEngineBlock._key }]), isTextBlock({ schema: editorEngine.snapshot.context.schema }, engineBlock) && isTextBlock({ schema: editorEngine.snapshot.context.schema }, oldEngineBlock)) {
16376
16390
  let oldKeys = oldEngineBlock.children.map((c) => c._key), newKeys = engineBlock.children.map((c) => c._key), oldKeySet = new Set(oldKeys), hasSharedKeys = newKeys.some((key) => oldKeySet.has(key));
16377
16391
  if (oldKeys.length === newKeys.length && oldKeys.length > 0 && oldKeySet.size === oldKeys.length && oldKeys.some((key, i) => key !== newKeys[i]) && newKeys.every((key) => oldKeySet.has(key)) || newKeys.length > 0 && !hasSharedKeys) {
16378
- debug.syncValue("Replacing children via set"), setNodeProperties(editorEngine, { children: engineBlock.children }, [{ _key: oldEngineBlock._key }]), editorEngine.onChange();
16392
+ debug.syncValue("Replacing children via set"), applyNodeProperties(editorEngine, { children: engineBlock.children }, [{ _key: oldEngineBlock._key }]), editorEngine.onChange();
16379
16393
  return;
16380
16394
  }
16381
16395
  let oldBlockChildrenLength = oldEngineBlock.children.length;
@@ -16404,7 +16418,7 @@ function updateBlock({ context, editorEngine, oldEngineBlock, block, index: _ind
16404
16418
  if (currentBlockChild._key === oldBlockChild?._key && currentBlockChild._type === oldBlockChild?._type) {
16405
16419
  debug.syncValue("Updating changed child", currentBlockChild, oldBlockChild);
16406
16420
  let isSpanNode = isSpan({ schema: context.schema }, currentBlockChild) && isSpan({ schema: context.schema }, oldBlockChild), childProps = { ...currentBlockChild };
16407
- isSpanNode && delete childProps.text, setNodeProperties(editorEngine, childProps, path), isSpanNode && isTextChanged ? (oldBlockChild.text.length > 0 && deleteRange(editorEngine, {
16421
+ isSpanNode && delete childProps.text, applyNodeProperties(editorEngine, childProps, path), isSpanNode && isTextChanged ? (oldBlockChild.text.length > 0 && deleteRange(editorEngine, {
16408
16422
  focus: {
16409
16423
  path,
16410
16424
  offset: 0