feat: add linkOnPaste option for adding a link to the current selection if the pasted content only contains an url, fix #1210
This commit is contained in:
@@ -19,9 +19,10 @@ yarn add @tiptap/extension-link
|
||||
|
||||
## Settings
|
||||
| Option | Type | Default | Description |
|
||||
| -------------- | --------- | ----------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||
| -------------- | --------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------- |
|
||||
| HTMLAttributes | `Object` | `{ target: '_blank', rel: 'noopener noreferrer nofollow' }` | Custom HTML attributes that should be added to the rendered HTML tag. |
|
||||
| openOnClick | `Boolean` | `true` | If enabled, links will be opened on click. |
|
||||
| linkOnPaste | `Boolean` | `true` | Adds a link to the current selection if the pasted content only contains an url. |
|
||||
|
||||
## Commands
|
||||
| Command | Parameters | Description |
|
||||
|
||||
@@ -7,7 +7,17 @@ import {
|
||||
import { Plugin, PluginKey } from 'prosemirror-state'
|
||||
|
||||
export interface LinkOptions {
|
||||
/**
|
||||
* If enabled, links will be opened on click.
|
||||
*/
|
||||
openOnClick: boolean,
|
||||
/**
|
||||
* Adds a link to the current selection if the pasted content only contains an url.
|
||||
*/
|
||||
linkOnPaste: boolean,
|
||||
/**
|
||||
* A list of HTML attributes to be rendered.
|
||||
*/
|
||||
HTMLAttributes: Record<string, any>,
|
||||
}
|
||||
|
||||
@@ -32,6 +42,7 @@ declare module '@tiptap/core' {
|
||||
|
||||
export const pasteRegex = /https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z]{2,}\b(?:[-a-zA-Z0-9@:%._+~#=?!&/]*)(?:[-a-zA-Z0-9@:%._+~#=?!&/]*)/gi
|
||||
export const pasteRegexWithBrackets = /(?:\()https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z]{2,}\b(?:[-a-zA-Z0-9@:%._+~#=?!&/()]*)(?:\))/gi
|
||||
export const pasteRegexExact = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z]{2,}\b(?:[-a-zA-Z0-9@:%._+~#=?!&/]*)(?:[-a-zA-Z0-9@:%._+~#=?!&/]*)$/gi
|
||||
|
||||
export const Link = Mark.create<LinkOptions>({
|
||||
name: 'link',
|
||||
@@ -42,6 +53,7 @@ export const Link = Mark.create<LinkOptions>({
|
||||
|
||||
defaultOptions: {
|
||||
openOnClick: true,
|
||||
linkOnPaste: true,
|
||||
HTMLAttributes: {
|
||||
target: '_blank',
|
||||
rel: 'noopener noreferrer nofollow',
|
||||
@@ -91,13 +103,12 @@ export const Link = Mark.create<LinkOptions>({
|
||||
},
|
||||
|
||||
addProseMirrorPlugins() {
|
||||
if (!this.options.openOnClick) {
|
||||
return []
|
||||
}
|
||||
const plugins = []
|
||||
|
||||
return [
|
||||
if (this.options.openOnClick) {
|
||||
plugins.push(
|
||||
new Plugin({
|
||||
key: new PluginKey('handleClick'),
|
||||
key: new PluginKey('handleClickLink'),
|
||||
props: {
|
||||
handleClick: (view, pos, event) => {
|
||||
const attrs = this.editor.getMarkAttributes('link')
|
||||
@@ -113,6 +124,44 @@ export const Link = Mark.create<LinkOptions>({
|
||||
},
|
||||
},
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
if (this.options.linkOnPaste) {
|
||||
plugins.push(
|
||||
new Plugin({
|
||||
key: new PluginKey('handlePasteLink'),
|
||||
props: {
|
||||
handlePaste: (view, event, slice) => {
|
||||
const { state } = view
|
||||
const { selection } = state
|
||||
const { empty } = selection
|
||||
|
||||
if (empty) {
|
||||
return false
|
||||
}
|
||||
|
||||
let textContent = ''
|
||||
|
||||
slice.content.forEach(node => {
|
||||
textContent += node.textContent
|
||||
})
|
||||
|
||||
if (!textContent || !textContent.match(pasteRegexExact)) {
|
||||
return false
|
||||
}
|
||||
|
||||
this.editor.commands.setMark(this.type, {
|
||||
href: textContent,
|
||||
})
|
||||
|
||||
return true
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
return plugins
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user