2 $getSelection, BaseSelection,
3 COMMAND_PRIORITY_NORMAL,
9 import {$getTextNodeFromSelection} from "../utils/selection";
10 import {$createLinkNode, LinkNode} from "@lexical/link";
13 function isLinkText(text: string): boolean {
14 const lower = text.toLowerCase();
15 if (!lower.startsWith('http')) {
19 const linkRegex = /(http|https):\/\/(\S+)\.\S+$/;
20 return linkRegex.test(text);
24 function handlePotentialLinkEvent(node: TextNode, selection: BaseSelection, editor: LexicalEditor) {
25 const selectionRange = selection.getStartEndPoints();
26 if (!selectionRange) {
30 const cursorPoint = selectionRange[0].offset;
31 const nodeText = node.getTextContent();
32 const rTrimText = nodeText.slice(0, cursorPoint);
33 const priorSpaceIndex = rTrimText.lastIndexOf(' ');
34 const startIndex = priorSpaceIndex + 1;
35 const textSegment = nodeText.slice(startIndex, cursorPoint);
37 if (!isLinkText(textSegment)) {
42 const linkNode: LinkNode = $createLinkNode(textSegment);
43 linkNode.append(new TextNode(textSegment));
45 const splits = node.splitText(startIndex, cursorPoint);
46 const targetIndex = splits.length === 3 ? 1 : 0;
47 const targetText = splits[targetIndex];
49 targetText.replace(linkNode);
55 export function registerAutoLinks(editor: LexicalEditor): () => void {
57 const handler = (payload: KeyboardEvent): boolean => {
58 const selection = $getSelection();
59 const textNode = $getTextNodeFromSelection(selection);
60 if (textNode && selection) {
61 handlePotentialLinkEvent(textNode, selection, editor);
67 const unregisterSpace = editor.registerCommand(KEY_SPACE_COMMAND, handler, COMMAND_PRIORITY_NORMAL);
68 const unregisterEnter = editor.registerCommand(KEY_ENTER_COMMAND, handler, COMMAND_PRIORITY_NORMAL);