mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-26 06:23:35 -04:00
(search)(terms) add search for terms
This commit is contained in:
parent
ce682f75f9
commit
0257c55081
29
components/search/SearchItemTerm.vue
Normal file
29
components/search/SearchItemTerm.vue
Normal file
@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import type { SearchResultTerm } from '~/server/api/search.get.ts';
|
||||
|
||||
defineProps<{
|
||||
result: SearchResultTerm;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nuxt-link :to="result.url" class="text-dark">
|
||||
<div class="h3">
|
||||
<Icon v="flag" />
|
||||
<Spelling :text="result.title" />
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
<div class="col-2">
|
||||
<img
|
||||
v-if="result.image"
|
||||
:src="result.image"
|
||||
class="w-100 pe-2"
|
||||
loading="lazy"
|
||||
>
|
||||
</div>
|
||||
<div class="col">
|
||||
<Spelling :text="result.content" />
|
||||
</div>
|
||||
</div>
|
||||
</nuxt-link>
|
||||
</template>
|
@ -38,6 +38,7 @@ const searchInput = useTemplateRef('searchInput');
|
||||
<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" />
|
||||
<SearchItemTerm v-else-if="result.type === 'term'" :result="result" />
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
@ -9,6 +9,7 @@ import type { Config } from '~/locale/config.ts';
|
||||
import { getPosts, type PostMetadata } from '~/server/blog.ts';
|
||||
import { getNounEntries } from '~/server/express/nouns.ts';
|
||||
import { getSourcesEntries } from '~/server/express/sources.ts';
|
||||
import { getTermsEntries } from '~/server/express/terms.ts';
|
||||
import { loadSuml, loadSumlFromBase } from '~/server/loader.ts';
|
||||
import { rootDir } from '~/server/paths.ts';
|
||||
import { parsePronouns } from '~/src/buildPronoun.ts';
|
||||
@ -430,6 +431,77 @@ class SearchIndexBlog extends SearchIndex<SearchDocumentBlog, SearchResultBlog>
|
||||
}
|
||||
}
|
||||
|
||||
interface SearchDocumentTerm {
|
||||
id: number;
|
||||
type: SearchIndexTerm['TYPE'];
|
||||
url: string;
|
||||
title: string;
|
||||
image: string | undefined;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export type SearchResultTerm = SearchDocumentTerm;
|
||||
|
||||
class SearchIndexTerm extends SearchIndex<SearchDocumentTerm, SearchResultTerm> {
|
||||
TYPE = 'term' as const;
|
||||
|
||||
constructor() {
|
||||
super(['url', 'title', 'content']);
|
||||
}
|
||||
|
||||
async getDocuments(config: Config): Promise<SearchDocumentTerm[]> {
|
||||
if (!config.terminology.enabled) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const runtimeConfig = useRuntimeConfig();
|
||||
|
||||
const base = encodeURIComponent(config.terminology.route);
|
||||
|
||||
const db = useDatabase();
|
||||
const terms = await getTermsEntries(db, () => false);
|
||||
return terms.map((term, id): SearchDocumentTerm => {
|
||||
const title = term.term.replaceAll('|', ', ');
|
||||
|
||||
let content = '';
|
||||
if (term.original) {
|
||||
content += `${clearLinkedText(term.original.replaceAll('|', ';'), false)}`;
|
||||
}
|
||||
content += ` ${clearLinkedText(term.definition, false)}`;
|
||||
|
||||
let image = undefined;
|
||||
const flags = JSON.parse(term.flags);
|
||||
if (flags.length > 0) {
|
||||
image = `/flags/${flags[0]}.png`;
|
||||
} else if (term.images) {
|
||||
image = buildImageUrl(runtimeConfig.public.cloudfront, term.images.split(',')[0], 'flag');
|
||||
}
|
||||
|
||||
return {
|
||||
id,
|
||||
type: this.TYPE,
|
||||
url: `/${base}?filter=${term.key}`,
|
||||
title,
|
||||
image,
|
||||
content,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
override transform(result: SearchResult): SearchResultTerm {
|
||||
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),
|
||||
image: document.image,
|
||||
content: highlightMatches(document.content, termsByField.content, true),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const indices = Object.fromEntries(
|
||||
[
|
||||
@ -439,6 +511,7 @@ export default defineEventHandler(async (event) => {
|
||||
new SearchIndexLink(),
|
||||
new SearchIndexFaq(),
|
||||
new SearchIndexBlog(),
|
||||
new SearchIndexTerm(),
|
||||
].map((index) => [index.TYPE, index]),
|
||||
);
|
||||
await Promise.all(Object.values(indices).map((index) => index.init(config)));
|
||||
|
@ -71,7 +71,7 @@ const linkOtherVersions = async (db: Database, isGranted: Request['isGranted'],
|
||||
|
||||
const router = Router();
|
||||
|
||||
const getTermsEntries = defineCachedFunction(async (db: Database, isGranted: Request['isGranted']) => {
|
||||
export const getTermsEntries = defineCachedFunction(async (db: Database, isGranted: Request['isGranted']) => {
|
||||
return await linkOtherVersions(
|
||||
db,
|
||||
isGranted,
|
||||
|
Loading…
x
Reference in New Issue
Block a user