* [#858,site][xl]: add Examples to the Navbar, rename gallery to showcases, remove examples from showcases, move github stars to the navbar, add view on github button to the hero section, reduce padding on buttons, add RHS image to the hero * [#858,site][xl]: make sidebar consistent on all pages * [site][xs]: fix ts error on GitHub button component * [site][xs]: fix external links on navbar needing two clicks to open * [site, hero][xs]: align RHS image to the top
182 lines
5.2 KiB
TypeScript
182 lines
5.2 KiB
TypeScript
import fs from 'fs';
|
|
|
|
import parse from '../lib/markdown.mjs';
|
|
|
|
import MDXPage from '../components/MDXPage';
|
|
import clientPromise from '@/lib/mddb';
|
|
import Layout from 'components/Layout';
|
|
import { useEffect, useState } from 'react';
|
|
import { useRouter } from 'next/router.js';
|
|
import { NavGroup, NavItem, collectHeadings } from '@flowershow/core';
|
|
import { GetStaticProps, GetStaticPropsResult } from 'next';
|
|
import { CustomAppProps } from './_app.jsx';
|
|
import computeFields from '@/lib/computeFields';
|
|
import { getAuthorsDetails } from '@/lib/getAuthorsDetails';
|
|
|
|
export default function Page({ source, meta, sidebarTree }) {
|
|
source = JSON.parse(source);
|
|
|
|
const router = useRouter();
|
|
|
|
const [tableOfContents, setTableOfContents] = useState([]);
|
|
|
|
useEffect(() => {
|
|
const headingNodes = document.querySelectorAll(
|
|
'h2,h3'
|
|
) as NodeListOf<HTMLHeadingElement>;
|
|
const toc = collectHeadings(headingNodes);
|
|
setTableOfContents(toc ?? []);
|
|
}, [router.asPath]); // update table of contents on route change with next/link
|
|
|
|
return (
|
|
<Layout
|
|
tableOfContents={tableOfContents}
|
|
title={meta.title}
|
|
sidebarTree={sidebarTree}
|
|
urlPath={meta.urlPath}
|
|
>
|
|
<MDXPage source={source} frontMatter={meta} />
|
|
</Layout>
|
|
);
|
|
}
|
|
|
|
interface SlugPageProps extends CustomAppProps {
|
|
source: any;
|
|
}
|
|
|
|
export const getStaticProps: GetStaticProps = async ({
|
|
params,
|
|
}): Promise<GetStaticPropsResult<SlugPageProps>> => {
|
|
const urlPath = params?.slug ? (params.slug as string[]).join('/') : '/';
|
|
|
|
const mddb = await clientPromise;
|
|
const dbFile = await mddb.getFileByUrl(urlPath);
|
|
const filePath = dbFile!.file_path;
|
|
const frontMatter = dbFile!.metadata ?? {};
|
|
|
|
// Temporary, so that blogs work properly
|
|
if (dbFile.metadata.filetype === 'blog') {
|
|
frontMatter.layout = 'blog';
|
|
frontMatter.authorsDetails = await getAuthorsDetails(
|
|
dbFile.metadata.authors
|
|
);
|
|
}
|
|
|
|
// Temporary, docs pages should present the LHS sidebar
|
|
if (dbFile.url_path.startsWith('docs')) {
|
|
frontMatter.showSidebar = true;
|
|
frontMatter.sidebarTreeFile = 'content/assets/sidebar.json';
|
|
}
|
|
|
|
const source = fs.readFileSync(filePath, { encoding: 'utf-8' });
|
|
const { mdxSource } = await parse(source, 'mdx', {});
|
|
|
|
// TODO temporary replacement for contentlayer's computedFields
|
|
const frontMatterWithComputedFields = await computeFields({
|
|
frontMatter,
|
|
urlPath,
|
|
filePath,
|
|
source,
|
|
});
|
|
|
|
let sidebarTree: Array<NavGroup | NavItem> = [];
|
|
|
|
if (frontMatterWithComputedFields?.showSidebar) {
|
|
let sidebarTreeFile = frontMatterWithComputedFields?.sidebarTreeFile;
|
|
|
|
// Added this file funcionality so that we can control
|
|
// which items appear in the sidebar and the order via
|
|
// a json file
|
|
if (sidebarTreeFile) {
|
|
const tree = fs.readFileSync(sidebarTreeFile, { encoding: 'utf-8' });
|
|
sidebarTree = JSON.parse(tree);
|
|
} else {
|
|
const allPages = await mddb.getFiles({ extensions: ['md', 'mdx'] });
|
|
const pages = allPages.filter((p) => !p.metadata?.isDraft);
|
|
pages.forEach((page) => {
|
|
addPageToSitemap(page, sidebarTree);
|
|
});
|
|
}
|
|
}
|
|
|
|
return {
|
|
props: {
|
|
source: JSON.stringify(mdxSource),
|
|
meta: frontMatterWithComputedFields,
|
|
sidebarTree,
|
|
},
|
|
};
|
|
};
|
|
|
|
export async function getStaticPaths() {
|
|
const mddb = await clientPromise;
|
|
let allDocuments = await mddb.getFiles({ extensions: ['md', 'mdx'] });
|
|
|
|
const paths = allDocuments
|
|
.filter((page) => page.metadata?.isDraft !== true)
|
|
.map((page) => {
|
|
const parts = page.url_path!.split('/');
|
|
return { params: { slug: parts } };
|
|
});
|
|
|
|
return {
|
|
paths,
|
|
fallback: false,
|
|
};
|
|
}
|
|
|
|
function capitalize(str: string) {
|
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
}
|
|
|
|
/* function addPageToGroup(page: MddbFile, sitemap: Array<NavGroup>) { */
|
|
function addPageToSitemap(page: any, sitemap: Array<NavGroup | NavItem>) {
|
|
const urlParts = page.url_path!.split('/').filter((part) => part);
|
|
// don't add home page to the sitemap
|
|
if (urlParts.length === 0) return;
|
|
// top level, root pages
|
|
if (urlParts.length === 1) {
|
|
sitemap.push({
|
|
name: page.metadata?.title || urlParts[0],
|
|
href: page.url_path,
|
|
});
|
|
} else {
|
|
// /blog/blogtest
|
|
const nestingLevel = urlParts.length - 1; // 1
|
|
let currArray: Array<NavItem | NavGroup> = sitemap;
|
|
|
|
for (let level = 0; level <= nestingLevel; level++) {
|
|
if (level === nestingLevel) {
|
|
currArray.push({
|
|
name: urlParts[level],
|
|
href: page.url_path,
|
|
});
|
|
continue;
|
|
}
|
|
|
|
const matchingGroup = currArray
|
|
.filter(isNavGroup)
|
|
.find(
|
|
(group) =>
|
|
group.path !== undefined && page.url_path.startsWith(group.path)
|
|
);
|
|
if (!matchingGroup) {
|
|
const newGroup: NavGroup = {
|
|
name: capitalize(urlParts[level]),
|
|
path: urlParts.slice(0, level + 1).join('/'),
|
|
level,
|
|
children: [],
|
|
};
|
|
currArray.push(newGroup);
|
|
currArray = newGroup.children;
|
|
} else {
|
|
currArray = matchingGroup.children;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function isNavGroup(item: NavItem | NavGroup): item is NavGroup {
|
|
return (item as NavGroup).children !== undefined;
|
|
}
|