(search)(inclusive) add search for inclusive

This commit is contained in:
Valentyne Stigloher 2024-12-17 20:45:22 +01:00
parent 0257c55081
commit a12b14256d
4 changed files with 80 additions and 1 deletions

View File

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

View File

@ -39,6 +39,7 @@ const searchInput = useTemplateRef('searchInput');
<SearchItemFaq v-else-if="result.type === 'faq'" :result="result" />
<SearchItemBlog v-else-if="result.type === 'blog'" :result="result" />
<SearchItemTerm v-else-if="result.type === 'term'" :result="result" />
<SearchItemInclusive v-else-if="result.type === 'inclusive'" :result="result" />
</li>
</ul>
</section>

View File

@ -7,6 +7,7 @@ import type { MatchInfo, SearchResult } from 'minisearch';
import type { Config } from '~/locale/config.ts';
import { getPosts, type PostMetadata } from '~/server/blog.ts';
import { getInclusiveEntries } from '~/server/express/inclusive.ts';
import { getNounEntries } from '~/server/express/nouns.ts';
import { getSourcesEntries } from '~/server/express/sources.ts';
import { getTermsEntries } from '~/server/express/terms.ts';
@ -502,6 +503,65 @@ class SearchIndexTerm extends SearchIndex<SearchDocumentTerm, SearchResultTerm>
}
}
interface SearchDocumentInclusive {
id: number;
type: SearchIndexInclusive['TYPE'];
url: string;
title: string;
content: string;
}
export type SearchResultInclusive = SearchDocumentInclusive;
class SearchIndexInclusive extends SearchIndex<SearchDocumentInclusive, SearchResultInclusive> {
TYPE = 'inclusive' as const;
constructor() {
super(['url', 'title', 'content']);
}
async getDocuments(config: Config): Promise<SearchDocumentInclusive[]> {
if (!config.inclusive.enabled) {
return [];
}
const base = encodeURIComponent(config.inclusive.route);
const db = useDatabase();
const inclusiveEntries = await getInclusiveEntries(db, () => false);
return inclusiveEntries.map((inclusiveEntry, id): SearchDocumentInclusive => {
const insteadOf = inclusiveEntry.insteadOf.split('|');
const say = inclusiveEntry.say?.split('|') ?? [];
let content = `${translator.translate('inclusive.insteadOf')}: ${insteadOf.join(', ')}` +
` ${translator.translate('inclusive.say')}: ${say.join(', ')}`;
if (inclusiveEntry.clarification) {
content += `; ${inclusiveEntry.clarification}`;
}
content += `; ${inclusiveEntry.because}`;
return {
id,
type: this.TYPE,
url: `/${base}?filter=${insteadOf[0]}`,
title: `${insteadOf[0]} ${say[0]}`,
content,
};
});
}
override transform(result: SearchResult): SearchResultInclusive {
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),
};
}
}
export default defineEventHandler(async (event) => {
const indices = Object.fromEntries(
[
@ -512,6 +572,7 @@ export default defineEventHandler(async (event) => {
new SearchIndexFaq(),
new SearchIndexBlog(),
new SearchIndexTerm(),
new SearchIndexInclusive(),
].map((index) => [index.TYPE, index]),
);
await Promise.all(Object.values(indices).map((index) => index.init(config)));

View File

@ -44,7 +44,7 @@ const approve = async (db: Database, id: string) => {
const router = Router();
const getInclusiveEntries = defineCachedFunction(async (db: Database, isGranted: Request['isGranted']) => {
export const getInclusiveEntries = defineCachedFunction(async (db: Database, isGranted: Request['isGranted']) => {
return sortClearedLinkedText(await db.all<InclusiveRowWithAuthor>(SQL`
SELECT i.*, u.username AS author FROM inclusive i
LEFT JOIN users u ON i.author_id = u.id