pleroma/app/soapbox/features/compose/editor/plugins/mention-plugin.ts
marcin mikołajczak f81b5d9aa8 WIP mentions plugin
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
2023-03-11 00:17:54 +01:00

55 lines
1.5 KiB
TypeScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { useLexicalTextEntity } from '@lexical/react/useLexicalTextEntity';
import { useCallback, useEffect } from 'react';
import { $createMentionNode, MentionNode } from '../nodes/mention-node';
import type { TextNode } from 'lexical';
const REGEX = new RegExp('(^|$|(?:^|\\s))([@])([a-z\\d_-]+(?:@[^@\\s]+)?)', 'i');
export function MentionPlugin(): JSX.Element | null {
const [editor] = useLexicalComposerContext();
useEffect(() => {
if (!editor.hasNodes([MentionNode])) {
throw new Error('MentionPlugin: MentionNode not registered on editor');
}
}, [editor]);
const createMentionNode = useCallback((textNode: TextNode): MentionNode => {
return $createMentionNode(textNode.getTextContent());
}, []);
const getMentionMatch = useCallback((text: string) => {
const matchArr = REGEX.exec(text);
if (matchArr === null) {
return null;
}
const mentionLength = matchArr[3].length + 1;
const startOffset = matchArr.index + matchArr[1].length;
const endOffset = startOffset + mentionLength;
return {
end: endOffset,
start: startOffset,
};
}, []);
useLexicalTextEntity<MentionNode>(
getMentionMatch,
MentionNode,
createMentionNode,
);
return null;
}