import type { GetStaticPaths, GetStaticProps } from 'next' import { serialize } from 'next-mdx-remote/serialize' import fs from 'fs' import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote' import path from 'path' import Layout from '../src/templates' import remarkPlugins from '../plugins/index.mjs' import recordSection from '../meta/recordSections' import { sidebarUsageFlat } from '../meta/sidebarFlat' type ApiDetails = { stringName: string | null baseClass: { title: string slug: string } | null trainable: string | null } export type PropsPageBase = { /** * TODO: This is only here for legacy support of the old code base * It should be refactort to pass the file path and page path instead. */ slug: string sectionTitle: string | null theme: string | null section: string isIndex: boolean } export type PropsPage = PropsPageBase & { mdx: MDXRemoteSerializeResult apiDetails: ApiDetails } const PostPage = ({ mdx: mdx, ...props }: PropsPage) => { return ( ) } export default PostPage type ParsedUrlQuery = { listPathPage: Array } export const getStaticPaths: GetStaticPaths = async () => { // This function needs to be defined inside `getStaticPath` to be executed in executed in the correct context const loadFolder = (pathBase: Array = []): Array<{ params: ParsedUrlQuery }> => fs .readdirSync(path.join('docs', ...pathBase), { withFileTypes: true }) .flatMap((dirent: fs.Dirent) => { if (dirent.isDirectory()) { return loadFolder([...pathBase, dirent.name]) } if (!dirent.name.includes('.mdx') || dirent.name[0] === '_') { return [] } return { params: { listPathPage: dirent.name === 'index.mdx' ? pathBase : [...pathBase, dirent.name.replace('.mdx', '')], }, } }) return { paths: loadFolder(), fallback: false, } } const getPathFileWithExtension = (listPathFile: ReadonlyArray) => `${path.join(...listPathFile)}.mdx` export const getStaticProps: GetStaticProps = async (args) => { if (!args.params) { return { notFound: true } } const listPathFile = ['docs', ...args.params.listPathPage] const isIndex = fs.existsSync(getPathFileWithExtension(listPathFile)) !== true const listPathFileWithIndex = isIndex ? [...listPathFile, 'index'] : listPathFile const pathFileWithIndexAndExtension = getPathFileWithExtension(listPathFileWithIndex) const mdx = await serialize(fs.readFileSync(pathFileWithIndexAndExtension, 'utf-8'), { parseFrontmatter: true, mdxOptions: { remarkPlugins }, }) if (!mdx.frontmatter) { throw new Error(`Frontmatter missing for ${pathFileWithIndexAndExtension}`) } const parentFolder = listPathFileWithIndex.length > 1 ? listPathFileWithIndex[listPathFileWithIndex.length - 2] : null const section = mdx.frontmatter.section ?? parentFolder const sectionMeta = section ? recordSection[section] ?? null : null const baseClass = null const apiDetails: ApiDetails = { stringName: mdx.frontmatter.api_string_name ?? null, baseClass: baseClass ? { title: mdx.frontmatter.title, slug: mdx.frontmatter.api_base_class, } : null, trainable: mdx.frontmatter.api_trainable ?? null, } const slug = `/${args.params.listPathPage.join('/')}` const next = section === 'usage' ? sidebarUsageFlat.find((item, index) => { return ( index > 0 && sidebarUsageFlat[index - 1].url === slug && item.url[0] === '/' ) }) : undefined return { props: { ...mdx.frontmatter, slug, mdx, sectionTitle: sectionMeta?.title ?? null, theme: sectionMeta?.theme ?? null, section: section, apiDetails: apiDetails, isIndex, next: next ? { slug: next.url, title: next.text, } : null, }, } }