Przeglądaj źródła

add useEmojiAutocompletion hooks

WNomunomu 2 lat temu
rodzic
commit
067b16e330

+ 4 - 66
packages/editor/src/services/codemirror-editor/use-codemirror-editor/use-codemirror-editor.ts

@@ -1,16 +1,15 @@
 import { useMemo } from 'react';
 import { useMemo } from 'react';
 
 
-import { type CompletionContext, type Completion, autocompletion } from '@codemirror/autocomplete';
 import { indentWithTab, defaultKeymap } from '@codemirror/commands';
 import { indentWithTab, defaultKeymap } from '@codemirror/commands';
 import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
 import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
-import { syntaxTree } from '@codemirror/language';
 import { languages } from '@codemirror/language-data';
 import { languages } from '@codemirror/language-data';
 import { EditorState, Prec, type Extension } from '@codemirror/state';
 import { EditorState, Prec, type Extension } from '@codemirror/state';
 import { keymap, EditorView } from '@codemirror/view';
 import { keymap, EditorView } from '@codemirror/view';
 import { useCodeMirror, type UseCodeMirror } from '@uiw/react-codemirror';
 import { useCodeMirror, type UseCodeMirror } from '@uiw/react-codemirror';
-import emojiData from 'emoji-mart/data/all.json';
 import deepmerge from 'ts-deepmerge';
 import deepmerge from 'ts-deepmerge';
 
 
+import { useEmojiAutocompletion } from '../use-emoji-autocompletion/use-emoji-autocompletion';
+
 import { useAppendExtensions, type AppendExtensions } from './utils/append-extensions';
 import { useAppendExtensions, type AppendExtensions } from './utils/append-extensions';
 import { useFocus, type Focus } from './utils/focus';
 import { useFocus, type Focus } from './utils/focus';
 import { useGetDoc, type GetDoc } from './utils/get-doc';
 import { useGetDoc, type GetDoc } from './utils/get-doc';
@@ -36,70 +35,9 @@ const defaultExtensions: Extension[] = [
   Prec.lowest(keymap.of(defaultKeymap)),
   Prec.lowest(keymap.of(defaultKeymap)),
 ];
 ];
 
 
-const getEmojiDataArray = (): string[] => {
-  const rawEmojiDataArray = emojiData.categories;
-
-  const emojiCategoriesData = [
-    'people',
-    'nature',
-    'foods',
-    'activity',
-    'places',
-    'objects',
-    'symbols',
-    'flags',
-  ];
-
-  const fixedEmojiDataArray: string[] = [];
-
-  emojiCategoriesData.forEach((value) => {
-    const tempArray = rawEmojiDataArray.find(obj => obj.id === value)?.emojis;
-
-    if (tempArray == null) {
-      return;
-    }
-
-    fixedEmojiDataArray.push(...tempArray);
-  });
-
-  return fixedEmojiDataArray;
-};
-
-const emojiDataArray = getEmojiDataArray();
-
-const emojiOptions = emojiDataArray.map(
-  tag => ({ label: `:${tag}:`, type: tag }),
-);
-
-const completeEmojiInput = (context: CompletionContext) => {
-  const nodeBefore = syntaxTree(context.state).resolveInner(context.pos, -1);
-  const textBefore = context.state.sliceDoc(nodeBefore.from, context.pos);
-  const emojiBefore = /:\w*$/.exec(textBefore);
-
-  if (!emojiBefore && !context.explicit) return null;
-
-  return {
-    from: emojiBefore ? nodeBefore.from + emojiBefore.index : context.pos,
-    options: emojiOptions,
-    validFor: /^(:\w*)?$/,
-  };
-};
-
-const emojiIcon = autocompletion({
-  addToOptions: [{
-    render: (completion: Completion, state: EditorState) => {
-      const emojiName = completion.type ?? '';
-      const element = document.createElement('span');
-      element.innerText = emojiName;
-      return element;
-    },
-    position: 20,
-  }],
-  icons: false,
-  override: [completeEmojiInput],
-});
 
 
 export const useCodeMirrorEditor = (props?: UseCodeMirror): UseCodeMirrorEditor => {
 export const useCodeMirrorEditor = (props?: UseCodeMirror): UseCodeMirrorEditor => {
+  const emojiAutocompletionSettings = useEmojiAutocompletion();
 
 
   const mergedProps = useMemo(() => {
   const mergedProps = useMemo(() => {
     return deepmerge(
     return deepmerge(
@@ -107,7 +45,7 @@ export const useCodeMirrorEditor = (props?: UseCodeMirror): UseCodeMirrorEditor
       {
       {
         extensions: [
         extensions: [
           defaultExtensions,
           defaultExtensions,
-          emojiIcon,
+          emojiAutocompletionSettings,
         ],
         ],
         // Reset settings of react-codemirror.
         // Reset settings of react-codemirror.
         // The extension defined first will be used, so it must be disabled here.
         // The extension defined first will be used, so it must be disabled here.

+ 76 - 0
packages/editor/src/services/codemirror-editor/use-emoji-autocompletion/use-emoji-autocompletion.ts

@@ -0,0 +1,76 @@
+import { type CompletionContext, type Completion, autocompletion } from '@codemirror/autocomplete';
+import { syntaxTree } from '@codemirror/language';
+import { Extension } from '@codemirror/state';
+import { emojiIndex } from 'emoji-mart';
+import emojiData from 'emoji-mart/data/all.json';
+
+const getEmojiDataArray = (): string[] => {
+  const rawEmojiDataArray = emojiData.categories;
+
+  const emojiCategoriesData = [
+    'people',
+    'nature',
+    'foods',
+    'activity',
+    'places',
+    'objects',
+    'symbols',
+    'flags',
+  ];
+
+  const fixedEmojiDataArray: string[] = [];
+
+  emojiCategoriesData.forEach((value) => {
+    const tempArray = rawEmojiDataArray.find(obj => obj.id === value)?.emojis;
+
+    if (tempArray == null) {
+      return;
+    }
+
+    fixedEmojiDataArray.push(...tempArray);
+  });
+
+  return fixedEmojiDataArray;
+};
+
+const emojiDataArray = getEmojiDataArray();
+
+const emojiOptions = emojiDataArray.map(
+  tag => ({ label: `:${tag}:`, type: tag }),
+);
+
+const emojiAutocompletion = (context: CompletionContext) => {
+  const nodeBefore = syntaxTree(context.state).resolveInner(context.pos, -1);
+  const textBefore = context.state.sliceDoc(nodeBefore.from, context.pos);
+  const emojiBefore = /:\w{2,}$/.exec(textBefore);
+
+  if (!emojiBefore && !context.explicit) return null;
+
+  return {
+    from: emojiBefore ? nodeBefore.from + emojiBefore.index : context.pos,
+    options: emojiOptions,
+    validFor: /^:\w{2,}$/,
+  };
+};
+
+const emojiAutocompletionSettings = autocompletion({
+  addToOptions: [{
+    render: (completion: Completion) => {
+      const emojiName = completion.type ?? '';
+      const emojiData = emojiIndex.emojis[emojiName];
+
+      const emoji = emojiData.native ?? emojiData[1].native;
+
+      const element = document.createElement('span');
+      element.innerHTML = emoji;
+      return element;
+    },
+    position: 20,
+  }],
+  icons: false,
+  override: [emojiAutocompletion],
+});
+
+export const useEmojiAutocompletion = (): Extension => {
+  return emojiAutocompletionSettings;
+};