mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-07-31 15:24:31 +03:00
Lexical: Added auto links on enter/space
This commit is contained in:
74
resources/js/wysiwyg/services/auto-links.ts
Normal file
74
resources/js/wysiwyg/services/auto-links.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import {
|
||||
$getSelection, BaseSelection,
|
||||
COMMAND_PRIORITY_NORMAL,
|
||||
KEY_ENTER_COMMAND,
|
||||
KEY_SPACE_COMMAND,
|
||||
LexicalEditor,
|
||||
TextNode
|
||||
} from "lexical";
|
||||
import {$getTextNodeFromSelection} from "../utils/selection";
|
||||
import {$createLinkNode, LinkNode} from "@lexical/link";
|
||||
|
||||
|
||||
function isLinkText(text: string): boolean {
|
||||
const lower = text.toLowerCase();
|
||||
if (!lower.startsWith('http')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const linkRegex = /(http|https):\/\/(\S+)\.\S+$/;
|
||||
return linkRegex.test(text);
|
||||
}
|
||||
|
||||
|
||||
function handlePotentialLinkEvent(node: TextNode, selection: BaseSelection, editor: LexicalEditor) {
|
||||
const selectionRange = selection.getStartEndPoints();
|
||||
if (!selectionRange) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cursorPoint = selectionRange[0].offset - 1;
|
||||
const nodeText = node.getTextContent();
|
||||
const rTrimText = nodeText.slice(0, cursorPoint);
|
||||
const priorSpaceIndex = rTrimText.lastIndexOf(' ');
|
||||
const startIndex = priorSpaceIndex + 1;
|
||||
const textSegment = nodeText.slice(startIndex, cursorPoint);
|
||||
|
||||
if (!isLinkText(textSegment)) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.update(() => {
|
||||
const linkNode: LinkNode = $createLinkNode(textSegment);
|
||||
linkNode.append(new TextNode(textSegment));
|
||||
|
||||
const splits = node.splitText(startIndex, cursorPoint);
|
||||
const targetIndex = splits.length === 3 ? 1 : 0;
|
||||
const targetText = splits[targetIndex];
|
||||
if (targetText) {
|
||||
targetText.replace(linkNode);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function registerAutoLinks(editor: LexicalEditor): () => void {
|
||||
|
||||
const handler = (payload: KeyboardEvent): boolean => {
|
||||
const selection = $getSelection();
|
||||
const textNode = $getTextNodeFromSelection(selection);
|
||||
if (textNode && selection) {
|
||||
handlePotentialLinkEvent(textNode, selection, editor);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const unregisterSpace = editor.registerCommand(KEY_SPACE_COMMAND, handler, COMMAND_PRIORITY_NORMAL);
|
||||
const unregisterEnter = editor.registerCommand(KEY_ENTER_COMMAND, handler, COMMAND_PRIORITY_NORMAL);
|
||||
|
||||
return (): void => {
|
||||
unregisterSpace();
|
||||
unregisterEnter();
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user