question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

PasteRule does not work for nodes

See original GitHub issue

Describe the bug When attempting to add a pasteRule for a Node, it does not work as the pasteRule helper function have a call to a Mark node (note how we call addToSet on the created node, which may not be a mark but a node):

nodes.push(child.cut(start, end).mark(type.create(attrs).addToSet(child.marks)));

Steps to Reproduce / Codesandbox Example

  1. Add a paste rule to any node such as a media embed
pasteRules({type}) {
  return [pasteRule(/SOME_YOUTUBE_REGEX/g, type, (url) => ({src: url}))]
}
  1. try to paste a heading: https://www.youtube.com/watch?v=H08tGjXNHO4
  2. See error in console: Uncaught TypeError: type.create(...).addToSet is not a function

Expected behavior a new MediaEmbed node should be created with the given attrs

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:6
  • Comments:22 (19 by maintainers)

github_iconTop GitHub Comments

4reactions
jeisslercommented, Feb 2, 2022

I’m also facing issue w/ implementing a nodePasteRule and wondered if anyone has gotten something similar to @kfirba solution working w/ TipTap 2 and the addPasteRules method? So far I’ve tried altering the code shown to accept a config object rather than just arguments to be closer to the TipTap nodeInputRule & markPasteRule, but I’m getting Uncaught TypeError: find is not a function. Thanks for making TipTap and any further suggestions.

Uncaught TypeError: find is not a function
    at pasteRuleMatcherHandler (tiptap-core.esm.js:2452:1)
    at tiptap-core.esm.js:2485:1
    at Fragment.nodesBetween (index.es.js:80:1)
    at Node.nodesBetween (index.es.js:1071:1)
    at run (tiptap-core.esm.js:2478:1)
    at Plugin.appendTransaction (tiptap-core.esm.js:2571:1)
    at EditorState.applyTransaction (index.es.js:842:1)
    at EditorState.apply (index.es.js:807:1)
    at Editor.dispatchTransaction (tiptap-core.esm.js:3448:1)
    at EditorView.dispatch (index.es.js:5247:29)
4reactions
kfirbacommented, May 5, 2020

@philippkuehn I’ve created a simple helper function to solve that:

export function nodePasteRule(regexp, type, getAttrs) {
  const handler = fragment => {
    const nodes = [];

    fragment.forEach(child => {
      if (child.isText) {
        const {text} = child;
        let pos = 0;
        let match;

        // eslint-disable-next-line
        while ((match = regexp.exec(text)) !== null) {
          if (match[0]) {
            const start = match.index;
            const end = start + match[0].length;
            const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs;

            // adding text before markdown to nodes
            if (start > 0) {
              nodes.push(child.cut(pos, start));
            }

            // create the node
            nodes.push(type.create(attrs));

            pos = end;
          }
        }

        // adding rest of text to nodes
        if (pos < text.length) {
          nodes.push(child.cut(pos));
        }
      } else {
        nodes.push(child.copy(handler(child.content)));
      }
    });

    return Fragment.fromArray(nodes);
  };

  return new Plugin({
    props: {
      transformPasted: slice => new Slice(handler(slice.content), slice.openStart, slice.openEnd),
    },
  });
}

Basically it is a very similar function as markPasteRule but it just creates the node with the given attribute instead of trying to add a mark ~and does not contain a while loop. Even in the markPasteRule I’m not sure why there is a while loop when match is only every assigned once?~ It seems like the while loop is for the regexp.exec call due to it attempting to match from the lastIndex: https://stackoverflow.com/questions/1520800/why-does-a-regexp-with-global-flag-give-wrong-results

I guess that if you want you could extract the common logic between those 2 methods and just pass a handler to create the node/mark.

What do you think?

Read more comments on GitHub >

github_iconTop Results From Across the Web

prosemirror-paste-rules | Remirror
A function that transforms the match into the content to use when creating a node. Pass () => {} to remove the matched...
Read more >
Custom extensions – Tiptap Editor
Let's walk through a few common use cases. The default Blockquote extension can wrap other nodes, like headings. If you want to allow...
Read more >
prosemirror-paste-rules - npm
The problem. You want to automatically transform pasted content within your editor into nodes marks, or different text.
Read more >
How to use the tiptap-commands.nodeInputRule function in ...
Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues...
Read more >
Tiptap editor, how to paste multiple empty lines?
I'm trying to extend the Paragraph extension to add a <p></p> for each new lines, but I can't make the regex to work....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found