add docs searching

This commit is contained in:
Lee
2024-04-21 02:17:51 +01:00
parent dbed53efe4
commit ebdaf623d9
11 changed files with 234 additions and 31 deletions

View File

@ -1,12 +1,11 @@
import * as fs from "node:fs";
import path from "node:path";
const docsDir = path.join(process.cwd(), "documentation");
import Fuse from "fuse.js";
/**
* Metadata for documentation content.
*/
type DocsContentMetadata = MDXMetadata & {
export type DocsContentMetadata = MDXMetadata & {
/**
* The title of this content.
*/
@ -50,45 +49,96 @@ type MDXMetadata = {
*/
const METADATA_REGEX: RegExp = /---\s*([\s\S]*?)\s*---/;
/**
* The directory of the documentation.
*/
const docsDir = path.join(process.cwd(), "documentation");
/**
* The cached documentation content.
*/
const cachedDocs: DocsContentMetadata[] = getDocsContent();
/**
* The fuse index for searching
*/
const fuseIndex: Fuse<DocsContentMetadata> = new Fuse(cachedDocs, {
keys: ["title", "summary"],
includeScore: true,
threshold: 0.4,
});
/**
* Get the directories in the
* given directory.
*/
export function getDocsDirectories(dir: string) {
const dirs: string[] = [dir];
const paths = fs.readdirSync(dir);
function getDocsDirectories(dir: string): string[] {
const directories: string[] = [dir];
const paths: string[] = fs.readdirSync(dir);
for (const item of paths) {
const itemPath = path.join(dir, item);
const stat = fs.statSync(itemPath);
for (const sub of paths) {
const subPath: string = path.join(dir, sub);
const stat: fs.Stats = fs.statSync(subPath);
if (stat.isDirectory()) {
dirs.push(...getDocsDirectories(itemPath));
directories.push(...getDocsDirectories(subPath));
}
}
return dirs;
return directories;
}
/**
* Get the content to
* display in the docs.
*/
export function getDocsContent() {
const directories = getDocsDirectories(docsDir);
const content: DocsContentMetadata[] = [];
export function getDocsContent(): DocsContentMetadata[] {
const directories: string[] = getDocsDirectories(docsDir);
const page: DocsContentMetadata[] = [];
for (let directory of directories) {
content.push(...getMetadata<DocsContentMetadata>(directory));
page.push(...getMetadata<DocsContentMetadata>(directory));
}
return content;
return page;
}
export function getDocContent(path?: string[]) {
const docs = getDocsContent();
const slug = path ? path.join("/") : "landing";
/**
* Get the content of the
* documentation page.
*
* @param path the path to the content
*/
export function getDocContent(path?: string[]): DocsContentMetadata | undefined {
const slug: string = path ? path.join("/") : "home";
return docs.find(doc => doc.slug === slug);
return cachedDocs.find(doc => doc.slug === slug);
}
/**
* Search the documentation
* for the given query.
*
* @param query the query to search
* @param limit the maximum number of results
*/
export function searchDocs(
query: string,
limit?: number,
): {
title: string;
summary: string;
slug: string;
}[] {
if (!limit) {
limit = 5; // Default to 5 results
}
return fuseIndex.search(query, { limit }).map(result => {
return {
title: result.item.title,
summary: result.item.summary,
slug: result.item.slug,
};
});
}
/**