(search)(faq) add search for faqs

This commit is contained in:
Valentyne Stigloher 2024-12-17 00:01:49 +01:00
parent a88807875d
commit ce682f75f9
4 changed files with 67 additions and 1 deletions

View File

@ -0,0 +1,17 @@
<script setup lang="ts">
import type { SearchResultFaq } from '~/server/api/search.get.ts';
defineProps<{
result: SearchResultFaq;
}>();
</script>
<template>
<nuxt-link :to="result.url" class="text-dark">
<div class="h3">
<Icon v="map-marker-question" />
<Spelling :text="result.title" />
</div>
<Spelling :text="result.content" />
</nuxt-link>
</template>

View File

@ -36,6 +36,7 @@ const searchInput = useTemplateRef('searchInput');
<SearchItemNoun v-else-if="result.type === 'noun'" :result="result" />
<SearchItemSource v-else-if="result.type === 'source'" :result="result" />
<SearchItemLink v-else-if="result.type === 'link'" :result="result" />
<SearchItemFaq v-else-if="result.type === 'faq'" :result="result" />
<SearchItemBlog v-else-if="result.type === 'blog'" :result="result" />
</li>
</ul>

View File

@ -322,6 +322,53 @@ class SearchIndexLink extends SearchIndex<SearchDocumentLink, SearchResultLink>
}
}
interface SearchDocumentFaq {
id: number;
type: SearchIndexFaq['TYPE'];
url: string;
title: string;
content: string;
}
export type SearchResultFaq = SearchDocumentFaq;
class SearchIndexFaq extends SearchIndex<SearchDocumentFaq, SearchResultFaq> {
TYPE = 'faq' as const;
constructor() {
super(['url', 'title', 'content']);
}
async getDocuments(config: Config): Promise<SearchDocumentFaq[]> {
if (!config.faq.enabled) {
return [];
}
return Object.entries(translator.get<Record<string, { question: string; answer: string[] }>>('faq.questions'))
.map(([key, { question, answer }], id) => {
return {
id,
type: this.TYPE,
url: `/${config.faq.route}#${key}`,
title: question,
content: answer.map((text) => clearLinkedText(text, false)).join(' '),
};
});
}
override transform(result: SearchResult): SearchResultFaq {
const document = this.documents[result.id];
const termsByField = getTermsByField(result.match);
return {
id: document.id,
type: document.type,
url: document.url,
title: highlightMatches(document.title, termsByField.title),
content: highlightMatches(document.content, termsByField.content, true),
};
}
}
interface SearchDocumentBlog extends PostMetadata {
id: number;
type: SearchIndexBlog['TYPE'];
@ -390,6 +437,7 @@ export default defineEventHandler(async (event) => {
new SearchIndexNoun(),
new SearchIndexSource(),
new SearchIndexLink(),
new SearchIndexFaq(),
new SearchIndexBlog(),
].map((index) => [index.TYPE, index]),
);

View File

@ -28,7 +28,7 @@ export class Translator {
);
}
get<T extends string | string[] = string>(
get<T = string>(
key: string,
warn: boolean = false,
base: boolean = false,