Skip to content

Commit c4544a8

Browse files
committed
editor: add support for pasting unformatted links
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
1 parent b296f5d commit c4544a8

File tree

4 files changed

+94
-47
lines changed

4 files changed

+94
-47
lines changed

packages/editor/package-lock.json

Lines changed: 45 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/editor/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"detect-indent": "^7.0.1",
7070
"entities": "^5.0.0",
7171
"katex": "0.16.11",
72+
"linkify-html": "^4.2.0",
7273
"linkifyjs": "^4.1.3",
7374
"nanoid": "^5.0.7",
7475
"prism-themes": "^1.9.0",

packages/editor/src/extensions/link/helpers/pasteHandler.ts

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,69 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2020
import { Editor } from "@tiptap/core";
2121
import { MarkType } from "@tiptap/pm/model";
2222
import { Plugin, PluginKey } from "@tiptap/pm/state";
23+
import linkifyHtml from "linkify-html";
2324
import { find } from "linkifyjs";
25+
import { linkRegex } from "../link";
2426

2527
type PasteHandlerOptions = {
2628
editor: Editor;
2729
type: MarkType;
30+
linkOnPaste: boolean;
2831
};
2932

3033
export function pasteHandler(options: PasteHandlerOptions): Plugin {
34+
let shiftKey = false;
3135
return new Plugin({
3236
key: new PluginKey("handlePasteLink"),
3337
props: {
38+
handleKeyDown(_, event) {
39+
shiftKey = event.shiftKey;
40+
return false;
41+
},
3442
handlePaste: (view, event, slice) => {
43+
const clipboardHtmlData = event.clipboardData?.getData("text/html");
44+
if (clipboardHtmlData) {
45+
return false;
46+
}
47+
3548
const { state } = view;
3649
const { selection } = state;
3750
const { empty } = selection;
3851

39-
if (empty) {
40-
return false;
41-
}
42-
4352
let textContent = "";
4453

4554
slice.content.forEach((node) => {
4655
textContent += node.textContent;
4756
});
4857

58+
if (linkRegex.test(textContent)) {
59+
linkRegex.lastIndex = 0;
60+
return false;
61+
}
62+
63+
if (shiftKey) {
64+
return false;
65+
}
66+
67+
if (empty) {
68+
if (textContent) {
69+
const html = linkifyHtml(textContent);
70+
options.editor.commands.insertContent(html);
71+
return true;
72+
}
73+
return false;
74+
}
75+
76+
console.log({
77+
empty,
78+
textContent,
79+
linkOnPaste: options.linkOnPaste
80+
});
81+
82+
if (!options.linkOnPaste) {
83+
return false;
84+
}
85+
4986
const link = find(textContent).find(
5087
(item) => item.isLink && item.value === textContent
5188
);

packages/editor/src/extensions/link/link.ts

Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -227,35 +227,6 @@ export const Link = Mark.create<LinkOptions>({
227227
href: regExp.exec(match[0])?.[1]
228228
};
229229
}
230-
}),
231-
markPasteRule({
232-
find: (text) => {
233-
const foundLinks: PasteRuleMatch[] = [];
234-
235-
if (text) {
236-
const links = find(text).filter((item) => item.isLink);
237-
238-
if (links.length) {
239-
links.forEach((link) =>
240-
foundLinks.push({
241-
text: link.value,
242-
data: {
243-
href: link.href
244-
},
245-
index: link.start
246-
})
247-
);
248-
}
249-
}
250-
251-
return foundLinks;
252-
},
253-
type: this.type,
254-
getAttributes: (match) => {
255-
return {
256-
href: match.data?.href
257-
};
258-
}
259230
})
260231
];
261232
},
@@ -281,14 +252,13 @@ export const Link = Mark.create<LinkOptions>({
281252
);
282253
}
283254

284-
if (this.options.linkOnPaste) {
285-
plugins.push(
286-
pasteHandler({
287-
editor: this.editor,
288-
type: this.type
289-
})
290-
);
291-
}
255+
plugins.push(
256+
pasteHandler({
257+
editor: this.editor,
258+
type: this.type,
259+
linkOnPaste: this.options.linkOnPaste
260+
})
261+
);
292262

293263
return plugins;
294264
},

0 commit comments

Comments
 (0)