Skip to content

Commit

Permalink
feat(server): add server search endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Tahul committed Jun 26, 2023
1 parent 2605000 commit c51f298
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 29 deletions.
81 changes: 52 additions & 29 deletions components/docs/DocsSearch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ defineProps({
}
})
type DocusSearchResult = {
id: string
path: string
dir: string
title: string
description: string
keywords: string[]
body?: any[]
}
const show = ref(false)
const q = ref('')
Expand All @@ -17,28 +27,34 @@ const resultsAreaRef = ref(null)
const selected = ref(-1)
const { data: files } = await useLazyAsyncData(
'components',
() => queryContent('components').where({ _type: 'markdown', draft: { $ne: false }, navigation: { $ne: false } }).find(), { default: () => [] }
const { data: files } = await useLazyAsyncData<DocusSearchResult[]>(
'search-api',
() => $fetch('/api/search')
)
const { results } = useFuse(q, files, {
fuseOptions: {
keys: [
'title',
'description',
],
ignoreLocation: true,
threshold: 0,
includeMatches: true,
includeScore: true,
},
matchAllWhenSearchEmpty: false
})
const { results } = useFuse<DocusSearchResult>(
q,
files as any,
{
fuseOptions: {
keys: [
'title',
'description',
'keywords',
'body'
],
ignoreLocation: true,
threshold: 0,
includeMatches: true,
includeScore: true,
},
matchAllWhenSearchEmpty: true
}
)
function findNavItem (children: any, path: string, parent: any) {
for (const child of children) {
if (child._path === path) {
if (child.path === path) {
return {
directoryTitle: parent.title,
directoryIcon: parent.icon
Expand Down Expand Up @@ -67,10 +83,13 @@ function getNavItemMeta(path?: string) {
return result
}
function highlight(text: string, { indices, value }: { indices: number[][], value: string }): string {
if (text === value) {
return ''
}
function highlight(
text: string,
result: any
): string {
const { indices, value }: { indices: number[][], value: string } = result || { indices: [], value: '' }
if (text === value) return ''
let content = ''
let nextUnhighlightedIndiceStartingIndex = 0
Expand All @@ -92,6 +111,7 @@ function highlight(text: string, { indices, value }: { indices: number[][], valu
content += value.substring(nextUnhighlightedIndiceStartingIndex)
const index = content.indexOf('<mark>')
if (index > 60) {
content = `...${content.substring(index - 60)}`
}
Expand All @@ -111,9 +131,12 @@ function up () {
else { selected.value = selected.value - 1 }
}
function go(index) {
function go(index: number) {
const selectedItem = results?.value?.[index]?.item
const path = selectedItem?._path
const path = selectedItem?.path
console.log({selectedItem})
if (path) {
show.value = false
useRouter().push(path)
Expand All @@ -122,7 +145,7 @@ function go(index) {
// Scroll to selected item on change
watch(selected, value => {
const nextId = results?.value?.[value]?.item?._id
const nextId = results?.value?.[value]?.item?.id
if (nextId) document.querySelector(`[id="${nextId}"]`)?.scrollIntoView({ block: 'nearest' })
})
Expand Down Expand Up @@ -165,18 +188,18 @@ watch(show, (value) => {
>
<div
v-for="(result, i) in results"
:id="result.item._id"
:key="result.item._id"
:id="result.item.id"
:key="result.item.id"
class="search-result"
:class="{ selected: selected === i }"
@click="go(selected)"
>
<Icon
v-if="getNavItemMeta(result?.item?._path)?.directoryIcon"
:name="getNavItemMeta(result?.item?._path)?.directoryIcon"
v-if="getNavItemMeta(result?.item?.path)?.directoryIcon"
:name="getNavItemMeta(result?.item?.path)?.directoryIcon"
/>
<span>
{{ getNavItemMeta(result?.item?._path)?.directoryTitle }}
{{ getNavItemMeta(result?.item?.path)?.directoryTitle }}
</span>
<span>
Expand Down
7 changes: 7 additions & 0 deletions nuxt.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ export default defineNuxtSchema({
*/
image: 'https://user-images.githubusercontent.com/904724/185365452-87b7ca7b-6030-4813-a2db-5e65c785bf88.png',

search: {
/**
* Search mode.
*/
mode: '',
},

/**
* Social links
*
Expand Down
44 changes: 44 additions & 0 deletions server/api/search.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { prefixStorage } from 'unstorage'
import { defineEventHandler } from 'h3'
import { useStorage } from '#imports'
import { serverQueryContent } from '#content/server'

const sourceStorage = prefixStorage(useStorage(), 'content:source')

export default defineEventHandler(async (event) => {
const appConfig = useAppConfig()

// const mode = appConfig?.docus?.search?.mode || 'meta'

// Fetch all documents
let docs = await serverQueryContent(event).find()

console.log({sourceStorage})

docs = await Promise.all(
docs
.filter(
(doc) => {
// Only use `.md` files which are not drafts and has content
return doc?._extension === 'md' &&
doc?._draft === false &&
doc?._empty === false
}
)
.map(
async ({ _id: id, _path: path, _dir: dir, title = '', description = '', body = undefined, ...rest }) => {
return {
id,
path,
dir,
title,
description,
keywords: body?.toc?.links.map(link => link?.text),
body: await sourceStorage?.getItem?.(id) || ''
}
}
)
)

return docs
})

0 comments on commit c51f298

Please sign in to comment.