|
1 | | -import { InputRule, markInputRule, markPasteRule, PasteRule } from '@tiptap/core' |
2 | | -import type { LinkOptions } from '@tiptap/extension-link' |
3 | | -import { Link } from '@tiptap/extension-link' |
| 1 | +import Link from '@tiptap/extension-link' |
4 | 2 |
|
5 | | -const inputRegex = /(?:^|\s)\[([^\]]*)?\]\((\S+)(?: ["“](.+)["”])?\)$/i |
6 | | - |
7 | | -const pasteRegex = /(?:^|\s)\[([^\]]*)?\]\((\S+)(?: ["“](.+)["”])?\)/gi |
8 | | - |
9 | | -function linkInputRule(config: Parameters<typeof markInputRule>[0]) { |
10 | | - const defaultMarkInputRule = markInputRule(config) |
11 | | - |
12 | | - return new InputRule({ |
13 | | - find: config.find, |
14 | | - handler(props) { |
15 | | - const { tr } = props.state |
16 | | - |
17 | | - defaultMarkInputRule.handler(props) |
18 | | - tr.setMeta('preventAutolink', true) |
19 | | - }, |
20 | | - }) |
21 | | -} |
22 | | - |
23 | | -function linkPasteRule(config: Parameters<typeof markPasteRule>[0]) { |
24 | | - const defaultMarkPasteRule = markPasteRule(config) |
25 | | - |
26 | | - return new PasteRule({ |
27 | | - find: config.find, |
28 | | - handler(props) { |
29 | | - const { tr } = props.state |
30 | | - |
31 | | - defaultMarkPasteRule.handler(props) |
32 | | - tr.setMeta('preventAutolink', true) |
33 | | - }, |
34 | | - }) |
35 | | -} |
36 | | - |
37 | | -type CustomLinkExtensionOptions = LinkOptions |
38 | | - |
39 | | -const CustomLinkExtension = Link.extend<CustomLinkExtensionOptions>({ |
| 3 | +export const CustomLinkExtension = Link.extend({ |
40 | 4 | inclusive: false, |
41 | | - addOptions() { |
42 | | - return { |
43 | | - ...this.parent?.(), |
44 | | - openOnClick: 'whenNotEditable', |
45 | | - } |
46 | | - }, |
47 | | - addAttributes() { |
48 | | - return { |
49 | | - ...this.parent?.(), |
50 | | - title: { |
51 | | - default: null, |
52 | | - }, |
53 | | - } |
54 | | - }, |
55 | | - |
56 | | - addInputRules() { |
57 | | - return [ |
58 | | - linkInputRule({ |
59 | | - find: inputRegex, |
60 | | - type: this.type, |
61 | | - |
62 | | - // We need to use `pop()` to remove the last capture groups from the match to |
63 | | - // satisfy Tiptap's `markPasteRule` expectation of having the content as the last |
64 | | - // capture group in the match (this makes the attribute order important) |
65 | | - getAttributes(match) { |
66 | | - return { |
67 | | - title: match.pop()?.trim(), |
68 | | - href: match.pop()?.trim(), |
69 | | - } |
70 | | - }, |
71 | | - }), |
72 | | - ] |
73 | | - }, |
74 | | - addPasteRules() { |
75 | | - return [ |
76 | | - linkPasteRule({ |
77 | | - find: pasteRegex, |
78 | | - type: this.type, |
79 | | - |
80 | | - // We need to use `pop()` to remove the last capture groups from the match to |
81 | | - // satisfy Tiptap's `markInputRule` expectation of having the content as the last |
82 | | - // capture group in the match (this makes the attribute order important) |
83 | | - getAttributes(match) { |
84 | | - return { |
85 | | - title: match.pop()?.trim(), |
86 | | - href: match.pop()?.trim(), |
87 | | - } |
88 | | - }, |
89 | | - }), |
90 | | - ] |
91 | | - }, |
| 5 | +}).configure({ |
| 6 | + openOnClick: false, |
| 7 | + HTMLAttributes: { |
| 8 | + class: 'custom-link', |
| 9 | + rel: 'noopener noreferrer', |
| 10 | + target: '_blank', |
| 11 | + }, |
| 12 | + protocols: ['http', 'https', 'mailto', 'tel'], |
| 13 | + autolink: true, |
| 14 | + linkOnPaste: true, |
92 | 15 | }) |
93 | | - |
94 | | -export { CustomLinkExtension } |
95 | | - |
96 | | -export type { CustomLinkExtensionOptions } |
0 commit comments