mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-26 14:32:04 -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" />
|
<SearchItemLink v-else-if="result.type === 'link'" :result="result" />
|
||||||
<SearchItemFaq v-else-if="result.type === 'faq'" :result="result" />
|
<SearchItemFaq v-else-if="result.type === 'faq'" :result="result" />
|
||||||
<SearchItemBlog v-else-if="result.type === 'blog'" :result="result" />
|
<SearchItemBlog v-else-if="result.type === 'blog'" :result="result" />
|
||||||
|
<SearchItemTerm v-else-if="result.type === 'term'" :result="result" />
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
@ -9,6 +9,7 @@ import type { Config } from '~/locale/config.ts';
|
|||||||
import { getPosts, type PostMetadata } from '~/server/blog.ts';
|
import { getPosts, type PostMetadata } from '~/server/blog.ts';
|
||||||
import { getNounEntries } from '~/server/express/nouns.ts';
|
import { getNounEntries } from '~/server/express/nouns.ts';
|
||||||
import { getSourcesEntries } from '~/server/express/sources.ts';
|
import { getSourcesEntries } from '~/server/express/sources.ts';
|
||||||
|
import { getTermsEntries } from '~/server/express/terms.ts';
|
||||||
import { loadSuml, loadSumlFromBase } from '~/server/loader.ts';
|
import { loadSuml, loadSumlFromBase } from '~/server/loader.ts';
|
||||||
import { rootDir } from '~/server/paths.ts';
|
import { rootDir } from '~/server/paths.ts';
|
||||||
import { parsePronouns } from '~/src/buildPronoun.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) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const indices = Object.fromEntries(
|
const indices = Object.fromEntries(
|
||||||
[
|
[
|
||||||
@ -439,6 +511,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
new SearchIndexLink(),
|
new SearchIndexLink(),
|
||||||
new SearchIndexFaq(),
|
new SearchIndexFaq(),
|
||||||
new SearchIndexBlog(),
|
new SearchIndexBlog(),
|
||||||
|
new SearchIndexTerm(),
|
||||||
].map((index) => [index.TYPE, index]),
|
].map((index) => [index.TYPE, index]),
|
||||||
);
|
);
|
||||||
await Promise.all(Object.values(indices).map((index) => index.init(config)));
|
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 router = Router();
|
||||||
|
|
||||||
const getTermsEntries = defineCachedFunction(async (db: Database, isGranted: Request['isGranted']) => {
|
export const getTermsEntries = defineCachedFunction(async (db: Database, isGranted: Request['isGranted']) => {
|
||||||
return await linkOtherVersions(
|
return await linkOtherVersions(
|
||||||
db,
|
db,
|
||||||
isGranted,
|
isGranted,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user