import type { ComponentType } from "react"; /** * Type guard to check if a value is a React component */ const isReactComponent = (value: unknown): value is ComponentType => { return typeof value === "function"; }; /** * Type guard to check if a value is an object with a default property */ const hasDefaultProperty = (value: unknown): value is { default: unknown } => { return ( value !== null && typeof value === "object" && "default" in value && value.default !== undefined ); }; /** * Extract MDX component from a module (for both .md and .mdx files) * Handles both direct component exports and default exports */ const extractMDXComponent = (module: unknown): ComponentType | null => { if (isReactComponent(module)) { return module; } if (hasDefaultProperty(module)) { const defaultExport = module.default; if (isReactComponent(defaultExport)) { return defaultExport; } } return null; }; /** * Auto-discovered markdown and MDX files as MDX components * Both .md and .mdx files are processed by the MDX plugin * Lazy loading enabled for better performance */ const mdxModules = import.meta.glob("../../content/**/*.{md,mdx}", { eager: false, }); /** * Get the MDX component for a given documentation slug * * Normalizes the slug and searches for matching files in the content directory. * Handles README files as index files (e.g., "api/readme" matches slug "api"). * Returns a promise that resolves to the component for lazy loading. * * @param slug - The documentation slug (e.g., "docs/architecture", "components/button") * @returns Promise that resolves to the React component for the documentation page, or null if not found */ export const getDocComponent = async ( slug: string, ): Promise => { const normalizedSlug = slug.toLowerCase().replace(/^\/+|\/+$/g, ""); for (const [path, moduleLoader] of Object.entries(mdxModules)) { const normalizedPath = path .replace(/^\.\.\/\.\.\/content\//, "") .replace(/\.(md|mdx)$/, "") .toLowerCase(); let matches = normalizedPath === normalizedSlug; if (!matches && normalizedPath.endsWith("/readme")) { const dirPath = normalizedPath.replace(/\/readme$/, ""); matches = dirPath === normalizedSlug || dirPath === `${normalizedSlug}/readme`; } if (!matches && normalizedPath === `${normalizedSlug}/readme`) { matches = true; } if (matches) { const module = await moduleLoader(); const component = extractMDXComponent(module); if (component) { return component; } } } return null; }; /** * Get a list of all available documentation slugs * * Extracts slugs from all discovered markdown and MDX files, * excluding README files and empty slugs. * * @returns Array of normalized documentation slugs */ export const getAvailableDocs = (): string[] => { return Object.keys(mdxModules) .map((path) => { const normalizedPath = path .replace(/^\.\.\/\.\.\/content\//, "") .replace(/\.(md|mdx)$/, ""); return normalizedPath.toLowerCase(); }) .filter((slug) => { const filename = slug.split("/").pop() ?? ""; return filename !== "readme" && slug.length > 0; }); };