Updating an old link element by pasting a new link in slate.js

148 Views Asked by At

CodeSandbox Example:

https://codesandbox.io/s/slate-2-images-and-links-forked-5p6mom

I made a withLink() plugin that would automatically linkify a link text when a user pastes a link string into the editor. I'm not sure how to update a link element when the user pastes a new link over it:

enter image description here

The problem is that using Transform.removeNode and Transform.insertNode together also removes the previous paragraph node when replacing the link. Do you have any suggestion?

Related Code:

export const wrapLink = (editor: Editor, url: string): void => {
  const { selection } = editor;
  const isCollapsed = selection && Range.isCollapsed(selection);
  const linkElement: LinkElement = {
    type: CustomElementTypes.link,
    url,
    children: [{ text: url }]
  };
  // Detect if the user is highlighting an old URL
  if (isCollapsed) {
    console.log("add new link");
    Transforms.insertNodes(editor, linkElement);
  } else {
    console.log("replace old link");
    Transforms.removeNodes(editor);
    Transforms.insertNodes(editor, linkElement);
    Transforms.collapse(editor, { edge: "end" });
  }
};
1

There are 1 best solutions below

0
Tobi On

To replace an existing Link you have to get the current node in your slate editor. You can do it like that:

const [link] = Editor.nodes(editor, {
  match: (n) =>
    !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === 'link',
})

You can read the current url and other props from that node as well as the position:

const [linkObject, path] = link

Finaly replace only the url of the noce without replacing the visible text:

Transforms.setNodes(editor, { url: YOUR_NEW_URL }, { at: path })

So the full replace function can look like that:

const replaceUrlInExistingAnchor = (editor: Editor, url: string) => {
  const [link] = Editor.nodes(editor, {
    match: (n) =>
      !Editor.isEditor(n) && Element.isElement(n) && n.type === 'link',
  })
  if (link) {
    const [_linkObject, path] = link
    Transforms.setNodes(editor, { url }, { at: path })
  }
}