aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Corentin Thomasset <corentin.thomasset74@gmail.com> 2022-12-16 18:10:50 +0100
committerGravatar Corentin Thomasset <corentin.thomasset74@gmail.com> 2022-12-16 18:10:50 +0100
commit1b5d4e72bdb222dd721a1e484c3e5d73bb62d2b1 (patch)
tree3e3430a05511b61ccd34376ca4be8fca231100ab /src
parent8476cf319b7ebae87c7928592604a54833ac56ef (diff)
downloadit-tools-1b5d4e72bdb222dd721a1e484c3e5d73bb62d2b1.tar.gz
it-tools-1b5d4e72bdb222dd721a1e484c3e5d73bb62d2b1.tar.zst
it-tools-1b5d4e72bdb222dd721a1e484c3e5d73bb62d2b1.zip
refactor(search-bar): improved tool fuzzy search
Diffstat (limited to 'src')
-rw-r--r--src/components/SearchBar.vue24
-rw-r--r--src/composable/fuzzySearch.ts23
2 files changed, 31 insertions, 16 deletions
diff --git a/src/components/SearchBar.vue b/src/components/SearchBar.vue
index 7305239..b1645ec 100644
--- a/src/components/SearchBar.vue
+++ b/src/components/SearchBar.vue
@@ -1,30 +1,22 @@
<script lang="ts" setup>
+import { useFuzzySearch } from '@/composable/fuzzySearch';
import { tools } from '@/tools';
import { SearchRound } from '@vicons/material';
import { useMagicKeys, whenever } from '@vueuse/core';
-import { deburr } from 'lodash';
import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter();
const queryString = ref('');
-const cleanString = (s: string) => deburr(s.trim().toLowerCase());
-
-const searchableTools = tools.map(({ name, description, keywords, path }) => ({
- searchableText: [name, description, ...keywords].map(cleanString).join(' '),
- path,
- name,
-}));
-
-const options = computed(() => {
- const query = cleanString(queryString.value);
-
- return searchableTools
- .filter(({ searchableText }) => searchableText.includes(query))
- .map(({ name, path }) => ({ label: name, value: path }));
+const { searchResult } = useFuzzySearch({
+ search: queryString,
+ data: tools,
+ options: { keys: [{ name: 'name', weight: 2 }, 'description', 'keywords'] },
});
+const options = computed(() => searchResult.value.map(({ name, path }) => ({ label: name, value: path })));
+
function onSelect(path: string) {
router.push(path);
queryString.value = '';
@@ -52,7 +44,7 @@ whenever(keys.ctrl_k, () => {
v-model:value="queryString"
:options="options"
:input-props="{ autocomplete: 'disabled' }"
- :on-select="onSelect"
+ :on-select="(value) => onSelect(String(value))"
>
<template #default="{ handleInput, handleBlur, handleFocus, value: slotValue }">
<n-input
diff --git a/src/composable/fuzzySearch.ts b/src/composable/fuzzySearch.ts
new file mode 100644
index 0000000..b46f9de
--- /dev/null
+++ b/src/composable/fuzzySearch.ts
@@ -0,0 +1,23 @@
+import { get, type MaybeRef } from '@vueuse/core';
+import Fuse from 'fuse.js';
+import { computed } from 'vue';
+
+export { useFuzzySearch };
+
+function useFuzzySearch<Data>({
+ search,
+ data,
+ options = {},
+}: {
+ search: MaybeRef<string>;
+ data: Data[];
+ options?: Fuse.IFuseOptions<Data>;
+}) {
+ const fuse = new Fuse(data, options);
+
+ const searchResult = computed(() => {
+ return fuse.search(get(search)).map(({ item }) => item);
+ });
+
+ return { searchResult };
+}