@portabletext/editor 1.0.17 → 1.0.19

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
@@ -106,7 +106,7 @@ function normalizeSelection(selection, value) {
106
106
  const { anchor, focus } = selection;
107
107
  return anchor && value.find((blk) => isEqual__default.default({ _key: blk._key }, anchor.path[0])) && (newAnchor = normalizePoint(anchor, value)), focus && value.find((blk) => isEqual__default.default({ _key: blk._key }, focus.path[0])) && (newFocus = normalizePoint(focus, value)), newAnchor && newFocus ? { anchor: newAnchor, focus: newFocus, backward: selection.backward } : null;
108
108
  }
109
- const EMPTY_MARKDEFS = [], EMPTY_MARKS$1 = [], VOID_CHILD_KEY = "void-child";
109
+ const EMPTY_MARKDEFS = [], VOID_CHILD_KEY = "void-child";
110
110
  function keepObjectEquality(object, keyMap) {
111
111
  const value = keyMap[object._key];
112
112
  return value && isEqual__default.default(object, value) ? value : (keyMap[object._key] = object, object);
@@ -854,24 +854,38 @@ function createOperationToPatches(types2) {
854
854
  return [patches.unset([{ _key: block._key }])];
855
855
  throw new Error("Block not found");
856
856
  } else if (editor.isTextBlock(block) && operation.path.length === 2) {
857
- const spanToRemove = editor.isTextBlock(block) && block.children && block.children[operation.path[1]];
858
- return spanToRemove ? [patches.unset([{ _key: block._key }, "children", { _key: spanToRemove._key }])] : (debug$k("Span not found in editor trying to remove node"), []);
857
+ const spanToRemove = block.children[operation.path[1]];
858
+ return spanToRemove ? block.children.filter((span) => span._key === operation.node._key).length > 1 ? (console.warn(
859
+ `Multiple spans have \`_key\` ${operation.node._key}. It's ambiguous which one to remove.`,
860
+ JSON.stringify(block, null, 2)
861
+ ), []) : [patches.unset([{ _key: block._key }, "children", { _key: spanToRemove._key }])] : (debug$k("Span not found in editor trying to remove node"), []);
859
862
  } else
860
863
  return debug$k("Not creating patch inside object block"), [];
861
864
  }
862
865
  function mergeNodePatch(editor, operation, beforeValue) {
863
- const patches$1 = [], block = beforeValue[operation.path[0]], targetBlock = editor.children[operation.path[0]];
866
+ const patches$1 = [], block = beforeValue[operation.path[0]], updatedBlock = editor.children[operation.path[0]];
864
867
  if (operation.path.length === 1)
865
868
  if (block?._key) {
866
869
  const newBlock = fromSlateValue([editor.children[operation.path[0] - 1]], textBlockName)[0];
867
870
  patches$1.push(patches.set(newBlock, [{ _key: newBlock._key }])), patches$1.push(patches.unset([{ _key: block._key }]));
868
871
  } else
869
872
  throw new Error("Target key not found!");
870
- else if (operation.path.length === 2 && editor.isTextBlock(targetBlock)) {
871
- const mergedSpan = editor.isTextBlock(block) && block.children[operation.path[1]] || void 0, targetSpan = targetBlock.children[operation.path[1] - 1];
872
- editor.isTextSpan(targetSpan) && (patches$1.push(
873
- patches.set(targetSpan.text, [{ _key: block._key }, "children", { _key: targetSpan._key }, "text"])
874
- ), mergedSpan && patches$1.push(patches.unset([{ _key: block._key }, "children", { _key: mergedSpan._key }])));
873
+ else if (editor.isTextBlock(block) && editor.isTextBlock(updatedBlock) && operation.path.length === 2) {
874
+ const updatedSpan = updatedBlock.children[operation.path[1] - 1] && editor.isTextSpan(updatedBlock.children[operation.path[1] - 1]) ? updatedBlock.children[operation.path[1] - 1] : void 0, removedSpan = block.children[operation.path[1]] && editor.isTextSpan(block.children[operation.path[1]]) ? block.children[operation.path[1]] : void 0;
875
+ updatedSpan && (block.children.filter((span) => span._key === updatedSpan._key).length === 1 ? patches$1.push(
876
+ patches.set(updatedSpan.text, [
877
+ { _key: block._key },
878
+ "children",
879
+ { _key: updatedSpan._key },
880
+ "text"
881
+ ])
882
+ ) : console.warn(
883
+ `Multiple spans have \`_key\` ${updatedSpan._key}. It's ambiguous which one to update.`,
884
+ JSON.stringify(block, null, 2)
885
+ )), removedSpan && (block.children.filter((span) => span._key === removedSpan._key).length === 1 ? patches$1.push(patches.unset([{ _key: block._key }, "children", { _key: removedSpan._key }])) : console.warn(
886
+ `Multiple spans have \`_key\` ${removedSpan._key}. It's ambiguous which one to remove.`,
887
+ JSON.stringify(block, null, 2)
888
+ ));
875
889
  } else
876
890
  debug$k("Void nodes can't be merged, not creating any patches");
877
891
  return patches$1;
@@ -1138,9 +1152,10 @@ function createWithEditableAPI(portableTextEditor, types$1, keyGenerator) {
1138
1152
  const [block] = slate.Editor.node(editor, originalSelection.focus, { depth: 1 });
1139
1153
  if (!editor.isTextBlock(block))
1140
1154
  return;
1141
- slate.Range.isCollapsed(originalSelection) && (editor.pteExpandToWord(), editor.onChange());
1142
1155
  const [textNode] = slate.Editor.node(editor, originalSelection.focus, { depth: 2 });
1143
- editor.selection && (slate.Editor.withoutNormalizing(editor, () => {
1156
+ if (!types.isPortableTextSpan(textNode) || textNode.text === "")
1157
+ return;
1158
+ slate.Range.isCollapsed(originalSelection) && (editor.pteExpandToWord(), editor.onChange()), editor.selection && (slate.Editor.withoutNormalizing(editor, () => {
1144
1159
  const annotationKey = keyGenerator();
1145
1160
  slate.Transforms.setNodes(
1146
1161
  editor,
@@ -2756,7 +2771,7 @@ function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
2756
2771
  change$.next({ type: "selection", selection: ptRange });
2757
2772
  };
2758
2773
  return editor.normalizeNode = (nodeEntry) => {
2759
- const [node, path] = nodeEntry, isSpan = slate.Text.isText(node) && node._type === types2.span.name, isTextBlock = editor.isTextBlock(node);
2774
+ const [node, path] = nodeEntry;
2760
2775
  if (editor.isTextBlock(node)) {
2761
2776
  const children = slate.Node.children(editor, path);
2762
2777
  for (const [child, childPath] of children) {
@@ -2771,65 +2786,47 @@ function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
2771
2786
  }
2772
2787
  }
2773
2788
  }
2774
- if (isSpan || isTextBlock) {
2775
- if (isSpan && !Array.isArray(node.marks)) {
2776
- debug$c("Adding .marks to span node"), slate.Transforms.setNodes(editor, { marks: [] }, { at: path });
2777
- return;
2778
- }
2779
- if (isSpan && (node.marks || []).length > 0) {
2780
- const spanMarks = node.marks || EMPTY_MARKS$1, annotationMarks = spanMarks.filter(
2781
- (mark) => !types2.decorators.map((dec) => dec.value).includes(mark)
2789
+ if (editor.isTextSpan(node) && !Array.isArray(node.marks)) {
2790
+ debug$c("Adding .marks to span node"), slate.Transforms.setNodes(editor, { marks: [] }, { at: path });
2791
+ return;
2792
+ }
2793
+ if (editor.isTextSpan(node)) {
2794
+ const blockPath = slate.Path.parent(path), [block] = slate.Editor.node(editor, blockPath), decorators2 = types2.decorators.map((decorator) => decorator.value), annotations = node.marks?.filter((mark) => !decorators2.includes(mark));
2795
+ if (editor.isTextBlock(block) && node.text === "" && annotations && annotations.length > 0) {
2796
+ debug$c("Removing annotations from empty span node"), slate.Transforms.setNodes(
2797
+ editor,
2798
+ { marks: node.marks?.filter((mark) => decorators2.includes(mark)) },
2799
+ { at: path }
2782
2800
  );
2783
- if (annotationMarks.length > 0) {
2784
- const [block] = slate.Editor.node(editor, slate.Path.parent(path)), orphanedMarks = editor.isTextBlock(block) && annotationMarks.filter(
2785
- (mark) => !block.markDefs?.find((def) => def._key === mark)
2786
- ) || [];
2787
- if (orphanedMarks.length > 0) {
2788
- debug$c("Removing orphaned .marks from span node"), slate.Transforms.setNodes(
2789
- editor,
2790
- { marks: spanMarks.filter((mark) => !orphanedMarks.includes(mark)) },
2791
- { at: path }
2792
- );
2793
- return;
2794
- }
2795
- }
2801
+ return;
2796
2802
  }
2797
- for (const op of editor.operations) {
2798
- if (op.type === "merge_node" && op.path.length === 1 && "markDefs" in op.properties && op.properties._type === types2.block.name && Array.isArray(op.properties.markDefs) && op.properties.markDefs.length > 0 && op.path[0] - 1 >= 0) {
2799
- const [targetBlock, targetPath] = slate.Editor.node(editor, [op.path[0] - 1]);
2800
- if (debug$c("Copying markDefs over to merged block", op), editor.isTextBlock(targetBlock)) {
2801
- const oldDefs = Array.isArray(targetBlock.markDefs) && targetBlock.markDefs || [], newMarkDefs = uniq__default.default([...oldDefs, ...op.properties.markDefs]);
2802
- if (!isEqual__default.default(newMarkDefs, targetBlock.markDefs)) {
2803
- slate.Transforms.setNodes(editor, { markDefs: newMarkDefs }, { at: targetPath, voids: !1 });
2804
- return;
2805
- }
2806
- }
2807
- }
2808
- if (op.type === "split_node" && op.path.length === 1 && slate.Element.isElementProps(op.properties) && op.properties._type === types2.block.name && "markDefs" in op.properties && Array.isArray(op.properties.markDefs) && op.properties.markDefs.length > 0 && op.path[0] + 1 < editor.children.length) {
2809
- const [targetBlock, targetPath] = slate.Editor.node(editor, [op.path[0] + 1]);
2810
- if (debug$c("Copying markDefs over to split block", op), editor.isTextBlock(targetBlock)) {
2811
- const oldDefs = Array.isArray(targetBlock.markDefs) && targetBlock.markDefs || [];
2812
- slate.Transforms.setNodes(
2803
+ }
2804
+ if (editor.isTextBlock(node)) {
2805
+ const decorators2 = types2.decorators.map((decorator) => decorator.value);
2806
+ for (const [child, childPath] of slate.Node.children(editor, path))
2807
+ if (editor.isTextSpan(child)) {
2808
+ const marks = child.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators2.includes(mark) && !node.markDefs?.find((def) => def._key === mark));
2809
+ if (orphanedAnnotations.length > 0) {
2810
+ debug$c("Removing orphaned annotations from span node"), slate.Transforms.setNodes(
2813
2811
  editor,
2814
- { markDefs: uniq__default.default([...oldDefs, ...op.properties.markDefs]) },
2815
- { at: targetPath, voids: !1 }
2812
+ { marks: marks.filter((mark) => !orphanedAnnotations.includes(mark)) },
2813
+ { at: childPath }
2816
2814
  );
2817
2815
  return;
2818
2816
  }
2819
2817
  }
2820
- if (op.type === "split_node" && op.path.length === 2 && op.properties._type === types2.span.name && "marks" in op.properties && Array.isArray(op.properties.marks) && op.properties.marks.length > 0 && op.path[0] + 1 < editor.children.length) {
2821
- const [child, childPath] = slate.Editor.node(editor, [op.path[0] + 1, 0]);
2822
- if (slate.Text.isText(child) && child.text === "" && Array.isArray(child.marks) && child.marks.length > 0) {
2823
- slate.Transforms.setNodes(editor, { marks: [] }, { at: childPath, voids: !1 });
2824
- return;
2825
- }
2826
- }
2827
- if (op.type === "split_node" && op.path.length === 1 && op.properties._type === types2.block.name && "markDefs" in op.properties && Array.isArray(op.properties.markDefs) && op.properties.markDefs.length > 0) {
2828
- const [block, blockPath] = slate.Editor.node(editor, [op.path[0]]);
2829
- if (editor.isTextBlock(block) && block.children.length === 1 && block.markDefs && block.markDefs.length > 0 && slate.Text.isText(block.children[0]) && block.children[0].text === "" && (!block.children[0].marks || block.children[0].marks.length === 0)) {
2830
- slate.Transforms.setNodes(editor, { markDefs: [] }, { at: blockPath });
2831
- return;
2832
- }
2818
+ }
2819
+ if (editor.isTextSpan(node)) {
2820
+ const blockPath = slate.Path.parent(path), [block] = slate.Editor.node(editor, blockPath);
2821
+ if (editor.isTextBlock(block)) {
2822
+ const decorators2 = types2.decorators.map((decorator) => decorator.value), marks = node.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators2.includes(mark) && !block.markDefs?.find((def) => def._key === mark));
2823
+ if (orphanedAnnotations.length > 0) {
2824
+ debug$c("Removing orphaned annotations from span node"), slate.Transforms.setNodes(
2825
+ editor,
2826
+ { marks: marks.filter((mark) => !orphanedAnnotations.includes(mark)) },
2827
+ { at: path }
2828
+ );
2829
+ return;
2833
2830
  }
2834
2831
  }
2835
2832
  }
@@ -2923,6 +2920,14 @@ function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
2923
2920
  }
2924
2921
  }
2925
2922
  }
2923
+ if (op.type === "merge_node" && op.path.length === 1 && "markDefs" in op.properties && op.properties._type === types2.block.name && Array.isArray(op.properties.markDefs) && op.properties.markDefs.length > 0 && op.path[0] - 1 >= 0) {
2924
+ const [targetBlock, targetPath] = slate.Editor.node(editor, [op.path[0] - 1]);
2925
+ if (editor.isTextBlock(targetBlock)) {
2926
+ const oldDefs = Array.isArray(targetBlock.markDefs) && targetBlock.markDefs || [], newMarkDefs = uniq__default.default([...oldDefs, ...op.properties.markDefs]);
2927
+ debug$c("Copying markDefs over to merged block", op), slate.Transforms.setNodes(editor, { markDefs: newMarkDefs }, { at: targetPath, voids: !1 }), apply2(op);
2928
+ return;
2929
+ }
2930
+ }
2926
2931
  apply2(op);
2927
2932
  }, editor.addMark = (mark) => {
2928
2933
  if (editor.selection) {