Async text paste

Hey, when users paste plaintext content, I need to run some tests on the text first and only if it does not contain X, Y and Z, I want to let it be pasted as it would have been without tests. Unfortunately these tests work asynchronously. I think I have a working solution, but it feels a bit hacky as I needed to copy some code from the ProseMirror repositories and import a function only exported for testing. Suggestions are appreciated.

First I added a transformPastedText property to a plugin. It takes the text, sends it to the async handler, and always returns an empty string.

Then, once the async handler receives a response, and we found out that it indeed needs to be treated as plain text, we run this insertText function, which basically is trying to turn the text into an HTMl paste instead and then tries to emulate the steps that an HTML paste would take:

    insertText() {
        // Inserts text as if it was pasted. We do that by converting it to html and inserting it that way.
        // Adapted from prosemirror-view/src/input.js
        let dom = document.createElement("div")
        this.text.trim().split(/(?:\r\n?|\n)+/).forEach(block => {
            dom.appendChild(document.createElement("p")).textContent = block
        })
        let html = dom.innerHTML

        let slice = __parseFromClipboard(this.view, '', html, this.view.shiftKey, this.view.state.selection.$from)

        if (!slice) {
            return
        }

        let singleNode = this.sliceSingleNode(slice)
        let tr = singleNode ? this.view.state.tr.replaceSelectionWith(singleNode, this.view.shiftKey) : this.view.state.tr.replaceSelection(slice)
        this.view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste"))
    }

https://github.com/fiduswriter/fiduswriter/blob/webworker-paste/document/static/js/modules/editor/paste/text.js#L55-L73

Most of this is directly copied from ProseMirror so I wonder if there is a more elegant solution out there.

Another possible solution would be to just let the paste through, track the start and end positions of the inserted region for the duration of the async request, and then replace the region with new content when necessary. That also has the advantage of directly showing the user that something is happening, rather than delaying the response entirely.

1 Like

Good point! In our case we are just checking whether there are bibtex citations in the pasted text in a web worker, and so far that seems to only take milliseconds, so inserting something else may just cause unnecessary flickering. In general though you have a point and if we discover that it takes seconds under certain circumstances, we’ll need to add visual feedback during to the user as you describe.