using nodePaste or PasteRule how do you access the text in links from clipboard #5122
Replies: 1 comment
-
So it seems that no matter what you do using nodes instead of marks, links copied to clipboard that have both text/plain and text/html component of the clipboard do not seem to be processed properly. Tried a few combinations of group and content settings in the node. if you restrict the content to inline* or text* it strips the tag out of the string and just pastes the inner html as plain text, no url is processed. If anyone else gets here and is trying to do something similar with inline nodes for links instead of marks (the exact use case described in the docs here, ie you really want mark, but need the features of a node https://tiptap.dev/docs/editor/api/schema#inline) This feels very hacky so a proper solution would be nice to have, but the only way I could get it to process the urls was to omit the content property and use inline: true and then hack the prosemirror pasteHandler to manually process the clipboard as per below. This extracts the url and the inner text from the tag and puts the inner text into a value prop on the attributes. Which you can then use in your renderHtml or nodeView export function pasteHandler(options) {
return new Plugin({
key: new PluginKey('handlePasteLink'),
props: {
handlePaste: (view, event, slice) => {
const { state } = view
const { selection } = state
const { empty } = selection
const range = {
from: selection.ranges[0].$from.pos,
to: selection.ranges[0].$to.pos
}
let link
const html = event.clipboardData?.getData("text/html")
const text = event.clipboardData?.getData("text/plain")
const match = html.match(/<a\shref=['"](.*)['"]>(.*?)<\/a>/)
if (match) {
link = find(text).find(item => item.isLink && item.value === text)
if (link) {
link.value = match[2]
}
} else if (empty) {
return false
} else {
let textContent = ''
slice.content.forEach(node => {
textContent += node.textContent
})
link = find(textContent).find(item => item.isLink && item.value === textContent)
if (!textContent || !link) {
return false
}
}
options.editor
.chain()
.focus()
.insertContentAt(range, [
{
type: options.type.name,
attrs: link,
},
{
type: 'text',
text: ' ',
},
])
.run()
return true
},
},
})
} |
Beta Was this translation helpful? Give feedback.
-
If you copy a url in the edge browser address bar, it copies it to the clipboard as a link and not as plaintext. When you paste this into tiptap using the link extension, it pastes an a tag and uses the text as the inner html of the tag
eg go to http://www.google.com in the address bar of edge browser then highlight it and copy the url.
paste it into the link extension demo here https://tiptap.dev/docs/editor/api/marks/link
it will show up as Google
All well and good. We have created a customised link plugin that creates the links as nodes instead of marks as we want to display previews of links and things in iframes or video previews etc not just text links.
We've based it on the link extension and just changed it to use nodePaste and nodeViews etc. All that all works great, except when you paste a link that has been copied as a link not plain text, as it does in edge for example.
in markPaste, the text in the link comes through. So for above google link the text past to markPaste find function is 'Google'. Then when renderHtml runs, it puts the text inside the a tag.
with nodePaste, this doesn't happen, the text comes through as blank "". So renderHtml just renders an a tag with no inner text. And I can't see anywhere in the params passed to renderHtml where the text is.
TBH I've tried to dig right into link extension to find out how it's even finding the link in the first place to see what the difference between them is but I can't see how it is doing it
Does anyone know what is going on here? Is this an underlying tiptap nodePaste the issue, or is this something I can just fix in the custom extension through linkify or something? Just seems weird that it picks up the text fine and passes it to markPaste, but it doesn't pass it to nodePaste. I would have thought it would just be parsing the same values to all rules
Any help would be greatly appreciated
Beta Was this translation helpful? Give feedback.
All reactions