tiptap

A Beginner's Guide to Formatting Paste with Tiptap

August 13, 20245 min read

Recently we have started migrating all our editors to the in-house solution built on top of the Tiptap editor. The reason for choosing tiptap is its flexibility and extensibility that would solve a few use cases of us to replicate the behaviour of the previous text editor features as much as possible.

The Problem: Unwanted Styles When Pasting Content

The ability to format on paste from several sources is one of these features. One of the most frequent tasks our clients do is making email templates by pasting text from the internet into the editor and adding content they find relevant. But some of our customers usually wish to eliminate the default styles that this process carries over from the original website. The email templates, blogs, etc. may become inconsistent as a result of these default styles.

So, we needed to device a flow that lets customer choose to keep the styles or discard them. Now we have to break this into multiple steps and start looking at the Tiptap for the feasibilities and they are

Step-1 :: Override Default Pasting Behaviour

When user has pasted the content, Tiptap has its own way to process the pasted content and we needed to tap into it.

A quick search would land you on this documentation with pasteHandler which will show some guideline but there is not much. Below is the one line that we get on pasteHandler

You can use that to hook into event handlers and pass - for example - a custom paste handler, too.

sample-code

Tiptap document is descriptive to some extent and like any other OSS documentation they don't provide details on each API and expect the developers to deep dive to solve the problems. And we did the same.

After a few hit and trains we were certain that the better way to do it is using  editorProps and the API offered by ProseMirror are very extensive but the same issue happens the Developer experience is not good in the docs. Nevertheless we needed to proceed with every API we find is relevant and decided on two options

  • handlePaste: This is the first trigger when you paste the content into Tiptap. It gives us the pasted text as a slice that the editor understands, plus an event. At first, we tried changing pasted content right in the handlePaste function and its working expected. But, it wont solve our use-case. We actually wanted users to choose to format or ignore. Then we need to somehow exclude the content to be parsed by this and its relatively easy than we expected - returning true will give us an option to bypass this.

    bypass-pastehandler

  • transformPasted: TransformPasted is designed to transform pasted or drag-and-drop content. It accepts two arguments: slice, which contains the pasted content, and view, which provides the EditorView instance and returns a slice. In our setup, we activated a popup by flipping a switch to 'on'. We stored the data chunk for later in a ref, and gave it back from the function. Now, the popup shows up, blocking the usual paste action, while we keep the data chunk in a ref, ready for the next steps after the user chooses what to do.

user-selection-popup

Step-2 :: Process the User Selection

We can remove the styles now and we are confident about it. Now, the second problem presents itself. To understand it we need to understand what do we mean by "styles".

Styles are the attributes essential for effective communication, as they emphasize key points, improve readability, and enhance visual appeal.

The problem now is to what to retain and what to remove ?

We are again on the path of finding the patterns and found that a few specific attributes are removed when you paste a content across a few apps. Like Text formats like Bold, italics, font-weight, font-family, colors and highlights etc.. We also observed that the Headings, links and other "ELEMENTS" are still retained. In the terminology of Tiptap - we need to remove the textStyle.

If you are familiar with Prosemirror or Tiptap, you wound understand the structure of the Slice they provide and how we need to traverse through them. if not, You can check it here.

So, we need to carefully go through the content of the Slice and remove the textStyle of the elements only while retaining the other behaviour and we have made a few mistakes and we have a better way to do it

Step-3 :: Updating the content

At this point, we have spent couple of days to implement the above two solutions and we need to deliver the solution to out editor package for the clients to be consumed. Finally the last problem presented to us.

Not every user simply replaces the entire text, they would sometime select the portion of the text and replace it with external content. And the editor needs to respect that. We have solved more complicated problem till now in this and this didnt seem like a challenging one. By this time we are a little fimilar on the documentation and quickly realised this can be implemented with the combination of two API

We needed to make sure the selection is retained with respective ranges.

preserving-selection

And Tadaaa 🎉 !!

Conclusion

This solution demonstrates the power of customization in TipTap and ProseMirror. By digging into the underlying libraries and exploring the available options, we were able to implement a robust and flexible solution that enhances the overall user experience of our rich text editor.

If you are interested to look at the whole implementation here is the link https://github.com/iamentafaz/tiptap-paste

Back to Blog