diff --git a/web/package.json b/web/package.json index 1fc3aa44e..0f04e656d 100644 --- a/web/package.json +++ b/web/package.json @@ -17,6 +17,7 @@ "axios": "^1.6.7", "classnames": "^2.5.1", "copy-to-clipboard": "^3.3.3", + "fuse.js": "^7.0.0", "highlight.js": "^11.9.0", "i18next": "^21.10.0", "i18next-browser-languagedetector": "^7.2.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 1e28fca5d..a0943e9ce 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -32,6 +32,9 @@ dependencies: copy-to-clipboard: specifier: ^3.3.3 version: 3.3.3 + fuse.js: + specifier: ^7.0.0 + version: 7.0.0 highlight.js: specifier: ^11.9.0 version: 11.9.0 @@ -3114,6 +3117,11 @@ packages: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} dev: true + /fuse.js@7.0.0: + resolution: {integrity: sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==} + engines: {node: '>=10'} + dev: false + /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} diff --git a/web/src/components/MemoEditor/Editor/TagSuggestions.tsx b/web/src/components/MemoEditor/Editor/TagSuggestions.tsx index 2f9f86dab..f236c265a 100644 --- a/web/src/components/MemoEditor/Editor/TagSuggestions.tsx +++ b/web/src/components/MemoEditor/Editor/TagSuggestions.tsx @@ -1,4 +1,5 @@ import classNames from "classnames"; +import Fuse from "fuse.js"; import { useEffect, useRef, useState } from "react"; import getCaretCoordinates from "textarea-caret"; import OverflowTip from "@/components/kit/OverflowTip"; @@ -35,27 +36,9 @@ const TagSuggestions = ({ editorRef, editorActions }: Props) => { const suggestionsRef = useRef([]); suggestionsRef.current = (() => { - const input = getCurrentWord()[0].slice(1).toLowerCase(); - - const customMatches = (tag: string, input: string) => { - const tagLowerCase = tag.toLowerCase(); - const inputLowerCase = input.toLowerCase(); - let inputIndex = 0; - - for (let i = 0; i < tagLowerCase.length; i++) { - if (tagLowerCase[i] === inputLowerCase[inputIndex]) { - inputIndex++; - if (inputIndex === inputLowerCase.length) { - return true; - } - } - } - - return false; - }; - - const matchedTags = tagsRef.current.filter((tag) => customMatches(tag, input)); - return matchedTags.slice(0, 5); + const search = getCurrentWord()[0].slice(1).toLowerCase(); + const fuse = new Fuse(tagsRef.current); + return fuse.search(search).map((result) => result.item); })(); const isVisibleRef = useRef(false);