Skip to content

Commit 79629dc

Browse files
committed
docs: add full-text search snippets
1 parent 606c73e commit 79629dc

File tree

7 files changed

+737
-23
lines changed

7 files changed

+737
-23
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<template>
2+
<UCard>
3+
<UButton
4+
variant="ghost"
5+
icon="i-heroicons-magnifying-glass-20-solid"
6+
@click="useContentSearch().open.value = true"
7+
>
8+
Open Search Modal
9+
</UButton>
10+
</UCard>
11+
</template>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<script setup lang="ts">
2+
import Fuse from 'fuse.js'
3+
4+
const query = ref('')
5+
const { data } = await useAsyncData('search-data', () => queryCollectionSearchSections('docs'))
6+
7+
const fuse = new Fuse(data.value, {
8+
keys: [
9+
'title',
10+
'description',
11+
],
12+
})
13+
14+
const result = computed<Array<{ item: typeof data.value[0] }>>(() => fuse.search(toValue(query)).slice(0, 10))
15+
</script>
16+
17+
<template>
18+
<UContainer class="p-4">
19+
<UCard>
20+
<UInput
21+
v-model="query"
22+
placeholder="Search..."
23+
class="w-full"
24+
/>
25+
<ul>
26+
<li
27+
v-for="link of result"
28+
:key="link.item.id"
29+
class="mt-2"
30+
>
31+
<UButton
32+
variant="ghost"
33+
class="w-full"
34+
:to="link.item.id"
35+
>
36+
{{ link.item.title }}
37+
<span class="text-gray-500 text-xs">
38+
{{ link.item.content?.slice(0, 100) }}...
39+
</span>
40+
</UButton>
41+
</li>
42+
</ul>
43+
</UCard>
44+
</UContainer>
45+
</template>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<script setup lang="ts">
2+
import MiniSearch from 'minisearch'
3+
4+
const query = ref('')
5+
const { data } = await useAsyncData('search-data', () => queryCollectionSearchSections('docs'))
6+
7+
const miniSearch = new MiniSearch({
8+
fields: ['title', 'content'],
9+
storeFields: ['title', 'content'],
10+
searchOptions: {
11+
prefix: true,
12+
fuzzy: 0.2,
13+
},
14+
})
15+
16+
// Add data to the MiniSearch instance
17+
miniSearch.addAll(toValue(data.value))
18+
const result = computed(() => miniSearch.search(toValue(query)).slice(0, 10))
19+
</script>
20+
21+
<template>
22+
<UContainer class="p-4">
23+
<UCard>
24+
<UInput
25+
v-model="query"
26+
placeholder="Search..."
27+
class="w-full"
28+
/>
29+
<ul>
30+
<li
31+
v-for="link of result"
32+
:key="link.id"
33+
class="mt-2"
34+
>
35+
<UButton
36+
variant="ghost"
37+
class="w-full"
38+
:to="link.id"
39+
>
40+
{{ link.title }}
41+
<span class="text-gray-500 text-xs">
42+
{{ link.content?.slice(0, 100) }}...
43+
</span>
44+
</UButton>
45+
</li>
46+
</ul>
47+
</UCard>
48+
</UContainer>
49+
</template>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
icon: i-heroicons-code-bracket-square
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
---
2+
title: Full-Text Search
3+
description: Implement full-text search in your website using Nuxt Content
4+
navigation:
5+
icon: i-heroicons-document-magnifying-glass
6+
---
7+
8+
Content module expose a handy utility [`queryCollectionSearchSections`{lang="ts-type"}][1] to break down content files into searchable sections. This is useful for implementing full-text search in your website.
9+
You can use the result of this utility in combination with [Nuxt UI Content Search][nuxt-ui-content-search] or other search libraries like [Fuse.js](https://fusejs.io/), [minisearch][mini-search], etc.
10+
11+
12+
## Nuxt UI Pro
13+
14+
Nuxt UI Pro provide a ready to use component for full-text search. You can use it by passing the result of `queryCollectionSearchSections` to the `files` prop of the component.
15+
16+
Read more about [Nuxt UI Content Search][nuxt-ui-content-search].
17+
18+
::code-group
19+
20+
```vue [UContentSearchExample.vue]
21+
<script setup lang="ts">
22+
const { data: navigation } = await useAsyncData('navigation', () => queryCollectionNavigation('docs'))
23+
const { data: files } = await useAsyncData('search', () => queryCollectionSearchSections('docs'))
24+
25+
const searchTerm = ref('')
26+
</script>
27+
28+
<template>
29+
<UContentSearch
30+
v-model:search-term="searchTerm"
31+
:files="files"
32+
:navigation="navigation"
33+
:fuse="{ resultLimit: 42 }"
34+
/>
35+
</template>
36+
```
37+
38+
:::preview-card{label="Live Preview"}
39+
:ExampleFulltextContentSearch
40+
:::
41+
42+
::
43+
44+
45+
46+
## MiniSearch example
47+
48+
Read more about [minisearch][mini-search].
49+
50+
::code-group
51+
52+
```vue [MiniSearchExample.vue]
53+
<script setup lang="ts">
54+
import MiniSearch from 'minisearch'
55+
56+
const query = ref('')
57+
const { data } = await useAsyncData('search', () => queryCollectionSearchSections('docs'))
58+
59+
const miniSearch = new MiniSearch({
60+
fields: ['title', 'content'],
61+
storeFields: ['title', 'content'],
62+
searchOptions: {
63+
prefix: true,
64+
fuzzy: 0.2,
65+
},
66+
})
67+
68+
// Add data to the MiniSearch instance
69+
miniSearch.addAll(toValue(data.value))
70+
const result = computed(() => miniSearch.search(toValue(query)))
71+
</script>
72+
73+
<template>
74+
<UContainer class="p-4">
75+
<UCard>
76+
<UInput v-model="query" placeholder="Search..." />
77+
<ul>
78+
<li v-for="link of result" :key="link.id" class="mt-2">
79+
<NuxtLink :to="link.id">{{ link.title }}</NuxtLink>
80+
<p class="text-gray-500 text-xs">{{ link.content }}</p>
81+
</li>
82+
</ul>
83+
</UCard>
84+
</UContainer>
85+
</template>
86+
```
87+
88+
:::preview-card{label="Live Preview"}
89+
:example-fulltext-mini-search
90+
:::
91+
92+
::
93+
94+
95+
## Fuse.js example
96+
97+
Read more about [Fuse.js][fusejs].
98+
99+
::code-group
100+
101+
```vue [FusejsExample.vue]
102+
<script setup lang="ts">
103+
import Fuse from 'fuse.js'
104+
105+
const query = ref('')
106+
const { data } = await useAsyncData('search-data', () => queryCollectionSearchSections('docs'))
107+
108+
const fuse = new Fuse(data.value, {
109+
keys: ['title', 'description']
110+
})
111+
112+
const result = computed(() => fuse.search(toValue(query)).slice(0, 10))
113+
</script>
114+
115+
<template>
116+
<UContainer class="p-4">
117+
<UCard>
118+
<UInput v-model="query" placeholder="Search..." class="w-full" />
119+
<ul>
120+
<li v-for="link of result" :key="link.item.id" class="mt-2">
121+
<UButton variant="ghost" class="w-full" :to="link.item.id">
122+
{{ link.item.title }}
123+
<span class="text-gray-500 text-xs">
124+
{{ link.item.content?.slice(0, 100) }}...
125+
</span>
126+
</UButton>
127+
</li>
128+
</ul>
129+
</UCard>
130+
</UContainer>
131+
</template>
132+
```
133+
134+
:::preview-card{label="Live Preview"}
135+
:example-fulltext-fusejs
136+
:::
137+
138+
::
139+
140+
141+
142+
143+
[1]: /api/query-collection-search-sections
144+
[fusejs]: https://fusejs.io
145+
[mini-search]: https://lucaong.github.io/minisearch
146+
[nuxt-ui-content-search]: https://ui.nuxt.com/pro/components/content-search

docs/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"@octokit/rest": "^21.0.2",
1616
"@vueuse/nuxt": "^11.1.0",
1717
"joi": "^17.13.3",
18+
"minisearch": "^7.1.0",
1819
"nuxt": "3.13.2",
1920
"nuxt-og-image": "^3.0.6",
2021
"prettier": "^3.3.3",

0 commit comments

Comments
 (0)