Merge pull request #11 from ueberdosis/feature/add-link-extension

Add Link Extension
This commit is contained in:
Philipp Kühn
2020-09-24 23:46:16 +02:00
committed by GitHub
5 changed files with 112 additions and 8 deletions

View File

@@ -10,7 +10,7 @@ import { EditorContent } from '@tiptap/vue'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
// import Link from '@tiptap/extension-link'
import Link from '@tiptap/extension-link'
export default {
components: {
@@ -29,7 +29,7 @@ export default {
Document(),
Paragraph(),
Text(),
// Link(),
Link(),
],
content: `
<p>

View File

@@ -18,3 +18,4 @@ export { default as getHtmlFromFragment } from './src/utils/getHtmlFromFragment'
export { default as getTopNodeFromExtensions } from './src/utils/getTopNodeFromExtensions'
export { default as getNodesFromExtensions } from './src/utils/getNodesFromExtensions'
export { default as getMarksFromExtensions } from './src/utils/getMarksFromExtensions'
export { default as getMarkAttrs } from './src/utils/getMarkAttrs'

View File

@@ -14,14 +14,15 @@ export default function (regexp: RegExp, type: MarkType, getAttrs?: Function) {
// eslint-disable-next-line
while ((match = regexp.exec(text)) !== null) {
const m = match.length - 1
const outerMatch = Math.max(match.length - 2, 0)
const innerMatch = Math.max(match.length - 1, 0)
if (parent.type.allowsMarkType(type) && match[1]) {
if (parent.type.allowsMarkType(type)) {
const start = match.index
const matchStart = start + match[0].indexOf(match[m - 1])
const matchEnd = matchStart + match[m - 1].length // TODO: why is there no -1
const textStart = matchStart + match[m - 1].lastIndexOf(match[m])
const textEnd = textStart + match[m].length
const matchStart = start + match[0].indexOf(match[outerMatch])
const matchEnd = matchStart + match[outerMatch].length
const textStart = matchStart + match[outerMatch].lastIndexOf(match[innerMatch])
const textEnd = textStart + match[innerMatch].length
const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs
// adding text before markdown to nodes

View File

@@ -0,0 +1,85 @@
import {
Command, Mark, markPasteRule, getMarkAttrs,
} from '@tiptap/core'
import { Plugin, PluginKey } from 'prosemirror-state'
export interface LinkOptions {
openOnClick: boolean,
target: string,
}
export type LinkCommand = () => Command
declare module '@tiptap/core/src/Editor' {
interface Commands {
link: LinkCommand,
}
}
export const pasteRegex = /https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z]{2,}\b(?:[-a-zA-Z0-9@:%_+.~#?&//=]*)/gi
export default new Mark<LinkOptions>()
.name('link')
.defaults({
openOnClick: true,
target: '',
})
.schema(({ options }) => ({
attrs: {
href: {
default: null,
},
target: {
default: null,
},
},
inclusive: false,
parseDOM: [
{
tag: 'a[href]',
getAttrs: node => ({
href: (node as HTMLElement).getAttribute('href'),
target: (node as HTMLElement).getAttribute('target'),
}),
},
],
toDOM: node => ['a', {
...node.attrs,
rel: 'noopener noreferrer nofollow',
target: options.target,
}, 0],
}))
.commands(({ name }) => ({
link: () => ({ commands }) => {
return commands.toggleMark(name)
},
}))
.pasteRules(({ type }) => [
markPasteRule(pasteRegex, type, (url: string) => ({ href: url })),
])
.plugins(({ options }) => {
if (!options.openOnClick) {
return []
}
return [
new Plugin({
key: new PluginKey('handleClick'),
props: {
handleClick: (view, pos, event) => {
const { schema } = view.state
const attrs = getMarkAttrs(view.state, schema.marks.link)
if (attrs.href && event.target instanceof HTMLAnchorElement) {
window.open(attrs.href, attrs.target)
return false
}
return true
},
},
}),
]
})
.create()

View File

@@ -0,0 +1,17 @@
{
"name": "@tiptap/extension-link",
"version": "1.0.0",
"source": "index.ts",
"main": "dist/tiptap-extension-link.js",
"umd:main": "dist/tiptap-extension-link.umd.js",
"module": "dist/tiptap-extension-link.mjs",
"unpkg": "dist/tiptap-extension-link.js",
"jsdelivr": "dist/tiptap-extension-link.js",
"files": [
"src",
"dist"
],
"peerDependencies": {
"@tiptap/core": "2.x"
}
}