search-index.ts 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import { readFile } from "fs/promises";
  2. import { join } from "path";
  3. import { docsNavigation } from "./docs-navigation";
  4. import { mdxToCleanMarkdown } from "./mdx-to-markdown";
  5. export type IndexEntry = {
  6. title: string;
  7. href: string;
  8. section: string;
  9. content: string;
  10. };
  11. let cached: IndexEntry[] | null = null;
  12. function stripMarkdown(md: string): string {
  13. return (
  14. md
  15. // Remove fenced code blocks entirely
  16. .replace(/```[\s\S]*?```/g, "")
  17. // Remove inline code
  18. .replace(/`[^`]+`/g, "")
  19. // Remove markdown links, keep text
  20. .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
  21. // Remove heading markers
  22. .replace(/^#{1,6}\s+/gm, "")
  23. // Remove bold/italic markers
  24. .replace(/\*{1,3}([^*]+)\*{1,3}/g, "$1")
  25. // Remove HTML tags
  26. .replace(/<[^>]+>/g, "")
  27. // Collapse whitespace
  28. .replace(/\n{3,}/g, "\n\n")
  29. .trim()
  30. );
  31. }
  32. function mdxFileForSlug(slug: string): string {
  33. const docsRoot = join(process.cwd(), "app", "(main)", "docs");
  34. if (slug === "/docs") {
  35. return join(docsRoot, "page.mdx");
  36. }
  37. const rest = slug.replace(/^\/docs\/?/, "");
  38. return join(docsRoot, ...rest.split("/"), "page.mdx");
  39. }
  40. export async function getSearchIndex(): Promise<IndexEntry[]> {
  41. if (cached) return cached;
  42. const entries: IndexEntry[] = [];
  43. for (const section of docsNavigation) {
  44. for (const item of section.items) {
  45. if (item.external) continue;
  46. try {
  47. const raw = await readFile(mdxFileForSlug(item.href), "utf-8");
  48. const md = mdxToCleanMarkdown(raw);
  49. const content = stripMarkdown(md);
  50. entries.push({
  51. title: item.title,
  52. href: item.href,
  53. section: section.title,
  54. content,
  55. });
  56. } catch {
  57. entries.push({
  58. title: item.title,
  59. href: item.href,
  60. section: section.title,
  61. content: "",
  62. });
  63. }
  64. }
  65. }
  66. cached = entries;
  67. return entries;
  68. }