Skip to content

Commit acfd670

Browse files
committed
Prioritize matches in headers and tags
1 parent ffba742 commit acfd670

File tree

2 files changed

+46
-6
lines changed

2 files changed

+46
-6
lines changed

components/DocList.vue

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,23 @@ export default defineComponent({
2323
const filter = computed(() => props.tag ? `#${props.tag}` : props.filter)
2424
2525
const { docs } = useDocs({ filter })
26-
const { searchResults } = useSearch(docs, { keys: ['text'], searchQuery })
26+
const { searchResults } = useSearch(docs, {
27+
keys: [
28+
{
29+
name: 'headers',
30+
weight: 1,
31+
},
32+
{
33+
name: 'tags',
34+
weight: 0.6,
35+
},
36+
{
37+
name: 'text',
38+
weight: 0.4,
39+
},
40+
],
41+
searchQuery,
42+
})
2743
2844
const finalDocs = computed(() => {
2945
return searchResults.value.map((doc: Doc) => ({

composables/useSearch.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
import { debouncedRef } from '@vueuse/core'
22
import Fuse from 'fuse.js'
33

4-
const regexSearchShape = /^\/(?<regex>.+)\/(?<flags>[a-z]*)$/s
4+
type Key<T extends string> = T | { name: T, weight: number }
55

6-
const fuzzy = <T>(list: Ref<T[]>, keys: string[]) => {
6+
const fuzzy = <T extends string, Item extends Record<T, unknown> = Record<T, unknown>>(list: Ref<Item[]>, keys: Key<T>[]): Fuse<Item> => {
77
return new Fuse(list.value, { includeScore: true, keys })
88
}
99

10-
export const useSearch = <T extends Record<string, any>>(list: Ref<T[]>, { keys, searchQuery = ref('') }: { keys: string[], searchQuery?: Ref<string> }) => {
10+
const regexSearchShape = /^\/(?<regex>.+)\/(?<flags>[a-z]*)$/s
11+
12+
const toKeyName = <T extends string>(key: Key<T>): T => {
13+
if (typeof key === 'object') {
14+
return key.name
15+
}
16+
17+
return key
18+
}
19+
20+
export const useSearch = <T extends string, Item extends Record<T, unknown> = Record<T, unknown>>(list: Ref<Item[]>, { keys, searchQuery = ref('') }: { keys: Key<T>[], searchQuery?: Ref<string> }) => {
1121
const filterer = computed(() => fuzzy(list, keys))
1222
const searchQueryDebounced = debouncedRef(searchQuery, 50)
1323
const searchResults = computed(() => {
@@ -25,7 +35,14 @@ export const useSearch = <T extends Record<string, any>>(list: Ref<T[]>, { keys,
2535

2636
return list.value.filter((item) => {
2737
return keys.some((key) => {
28-
return searchRegex.test(item[key])
38+
const k = toKeyName(key)
39+
const v = item[k]
40+
41+
if (typeof v === 'string') {
42+
return searchRegex.test(v)
43+
}
44+
45+
return false
2946
})
3047
})
3148
} catch (error) {
@@ -45,7 +62,14 @@ export const useSearch = <T extends Record<string, any>>(list: Ref<T[]>, { keys,
4562
// 4. If all else fails, do a case-insensitive full-text match.
4663
return list.value.filter((item) => {
4764
return keys.some((key) => {
48-
return item[key].toLowerCase().includes(searchQueryDebounced.value.toLowerCase())
65+
const k = toKeyName(key)
66+
const v = item[k]
67+
68+
if (typeof v === 'string') {
69+
return v.toLowerCase().includes(searchQueryDebounced.value.toLowerCase())
70+
}
71+
72+
return false
4973
})
5074
})
5175
})

0 commit comments

Comments
 (0)