feat: Add search functionality for documents

This commit is contained in:
Gauthier Daniels 2025-04-20 12:41:38 +02:00
parent 66bd48e55e
commit 9526b1ae9d
5 changed files with 47 additions and 8 deletions

View File

@ -12,7 +12,6 @@ import { Dialog, DialogPanel } from "terracotta";
import { useDebounce } from "@/hooks/useDebounce"; import { useDebounce } from "@/hooks/useDebounce";
import { Highlighter } from "solid-highlight-words"; import { Highlighter } from "solid-highlight-words";
import { navigate } from "vike/client/router"; import { navigate } from "vike/client/router";
import { onSearch } from "./Search.telefunc";
import { useId } from "@/hooks/useId"; import { useId } from "@/hooks/useId";
import clsx from "clsx"; import clsx from "clsx";
@ -270,6 +269,15 @@ export function Search() {
const debouncedQuery = useDebounce(query, 300); const debouncedQuery = useDebounce(query, 300);
const onSearch = async (query: string) => {
const response = await fetch(`/search?query=${query}`);
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();
return data;
};
createEffect(() => { createEffect(() => {
const platform = navigator.userAgentData?.platform || navigator.platform; const platform = navigator.userAgentData?.platform || navigator.platform;
setModifierKey(/(Mac|iPhone|iPod|iPad)/i.test(platform) ? "⌘" : "Ctrl "); setModifierKey(/(Mac|iPhone|iPod|iPad)/i.test(platform) ? "⌘" : "Ctrl ");
@ -288,9 +296,7 @@ export function Search() {
onSearch(query) onSearch(query)
.then(setResults) .then(setResults)
.finally(() => { .finally(() => setIsLoading(false));
setIsLoading(false);
});
}); });
return ( return (

View File

@ -2,15 +2,14 @@ import type { readingTime } from "reading-time-estimator";
import type { TableOfContents } from "./remarkHeadingId"; import type { TableOfContents } from "./remarkHeadingId";
import { createHandler } from "@universal-middleware/fastify"; import { createHandler } from "@universal-middleware/fastify";
import { telefuncHandler } from "./server/telefunc-handler";
import { vikeHandler } from "./server/vike-handler"; import { vikeHandler } from "./server/vike-handler";
import { createDevMiddleware } from "vike/server"; import { createDevMiddleware } from "vike/server";
import { docCache } from "./services/DocCache"; import { docCache } from "./services/DocCache";
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
import { search } from "./libs/search";
import { dirname } from "node:path"; import { dirname } from "node:path";
import { config } from "./config"; import { config } from "./config";
import Fastify from "fastify"; import Fastify from "fastify";
import { buildFlexSearch } from "./services/FlexSearchService";
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename); const __dirname = dirname(__filename);
@ -60,7 +59,17 @@ async function startServer() {
app.use(devMiddleware); app.use(devMiddleware);
} }
app.post<{ Body: string }>("/_telefunc", createHandler(telefuncHandler)()); app.get("/search", async (request, reply) => {
const { query } = request.query as { query: string };
if (!query) {
reply.status(400).send("Query parameter is required");
return;
}
const results = search(query);
reply.status(200).send(results);
});
/** /**
* Vike route * Vike route

View File

@ -1,4 +1,5 @@
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
import { search } from "./libs/search";
import { dirname } from "node:path"; import { dirname } from "node:path";
import { config } from "./config"; import { config } from "./config";
import Fastify from "fastify"; import Fastify from "fastify";
@ -31,6 +32,18 @@ async function startServer() {
reply.type("text/html").send(stream); reply.type("text/html").send(stream);
}); });
app.get("/search", async (request, reply) => {
const { query } = request.query as { query: string };
if (!query) {
reply.status(400).send("Query parameter is required");
return;
}
const results = search(query);
reply.status(200).send(results);
});
return app; return app;
} }
@ -44,3 +57,5 @@ app.listen({ port: config.PORT, host: "0.0.0.0" }, (error, address) => {
console.log(`Server listening on ${address}`); console.log(`Server listening on ${address}`);
}); });
export default app;

9
app/libs/search.ts Normal file
View File

@ -0,0 +1,9 @@
import { buildFlexSearch } from "@/services/FlexSearchService";
import { docCache } from "@/services/DocCache";
export function search(query: string) {
const docs = docCache.fetchDocs();
const search = buildFlexSearch(docs);
return search(query, 5);
}

View File

@ -23,5 +23,5 @@ export default {
prerender: true, prerender: true,
extends: vikeSolid, extends: [vikeSolid],
} satisfies Config; } satisfies Config;