|
|
|
@ -1,17 +1,13 @@
|
|
|
|
|
import { serialize } from "next-mdx-remote/serialize";
|
|
|
|
|
import { MDXRemote, MDXRemoteSerializeResult } from "next-mdx-remote";
|
|
|
|
|
import { ReactElement, useEffect } from "react";
|
|
|
|
|
import { join, resolve } from "path";
|
|
|
|
|
import { resolve } from "path";
|
|
|
|
|
import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next";
|
|
|
|
|
import { removeExt, walkFiles } from "../../lib/files";
|
|
|
|
|
import { readFile, stat } from "fs/promises";
|
|
|
|
|
import { readdir } from "fs/promises";
|
|
|
|
|
import remarkGfm from "remark-gfm";
|
|
|
|
|
import TreeNode from "../../components/TreeItem";
|
|
|
|
|
import fm from "front-matter";
|
|
|
|
|
import DocWrapper from "../../components/DocWrapper";
|
|
|
|
|
import { findCurrentDir, TreeItem, TreeItemConstructor } from "../../lib/tree";
|
|
|
|
|
import { load } from "js-yaml";
|
|
|
|
|
import { findCurrentDir, ITreeItem } from "../../lib/tree";
|
|
|
|
|
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
|
|
|
|
import rehypeSlug from "rehype-slug";
|
|
|
|
|
import rehypeHighlight from "rehype-highlight";
|
|
|
|
@ -20,6 +16,7 @@ import { useRouter } from "next/router";
|
|
|
|
|
import Link from "next/link";
|
|
|
|
|
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
|
|
|
|
|
import TranslationInfo from "../../components/TranslationInfo";
|
|
|
|
|
import trees from "../../lib/trees";
|
|
|
|
|
|
|
|
|
|
export const getStaticPaths: GetStaticPaths = async ({ locales }) => {
|
|
|
|
|
const paths: GetStaticPathsResult["paths"] = [];
|
|
|
|
@ -54,67 +51,14 @@ export const getStaticProps: GetStaticProps = async ({ params, locale }) => {
|
|
|
|
|
"meta",
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
let path = ["_docs", locale, ...slug].join("/") + ".mdx";
|
|
|
|
|
let isDir: boolean = false;
|
|
|
|
|
|
|
|
|
|
const walk = async (node: TreeItemConstructor, dir: string, i = 0) => {
|
|
|
|
|
const dirents = await readdir(resolve(process.cwd(), dir), {
|
|
|
|
|
withFileTypes: true,
|
|
|
|
|
});
|
|
|
|
|
for (const dirent of dirents.filter(
|
|
|
|
|
(dirent) => !dirent.name.startsWith(".")
|
|
|
|
|
)) {
|
|
|
|
|
const current = slug[i] === removeExt(dirent.name) && node.current;
|
|
|
|
|
if (dirent.isDirectory()) {
|
|
|
|
|
node.addChild(
|
|
|
|
|
await walk(
|
|
|
|
|
new TreeItemConstructor(removeExt(dirent.name), current, null, 0),
|
|
|
|
|
resolve(dir, dirent.name),
|
|
|
|
|
i + 1
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const configFile = join(resolve(dir, dirent.name), ".config.yaml");
|
|
|
|
|
const config = await stat(configFile);
|
|
|
|
|
|
|
|
|
|
if (config.isFile()) {
|
|
|
|
|
const { title, weight } = load(
|
|
|
|
|
(await readFile(configFile)).toString(),
|
|
|
|
|
{}
|
|
|
|
|
) as FrontMatter;
|
|
|
|
|
if (title) node.children.at(-1)!.pretty = title;
|
|
|
|
|
if (weight) node.children.at(-1)!.weight = weight;
|
|
|
|
|
}
|
|
|
|
|
} catch (_) { }
|
|
|
|
|
|
|
|
|
|
if (current && i + 1 == slug.length && node.children.length > 0) {
|
|
|
|
|
isDir = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
const contents = (await readFile(resolve(dir, dirent.name))).toString();
|
|
|
|
|
|
|
|
|
|
const {
|
|
|
|
|
attributes: { title, weight },
|
|
|
|
|
} = fm<FrontMatter>(contents);
|
|
|
|
|
node.addChild(
|
|
|
|
|
new TreeItemConstructor(
|
|
|
|
|
removeExt(dirent.name),
|
|
|
|
|
current,
|
|
|
|
|
title ? title : null,
|
|
|
|
|
weight ? weight : 0
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return node;
|
|
|
|
|
};
|
|
|
|
|
const rootySlug = ["root", ...slug];
|
|
|
|
|
|
|
|
|
|
const tree = trees[locale!].copy();
|
|
|
|
|
tree.walkCurrents(rootySlug);
|
|
|
|
|
|
|
|
|
|
const tree = (
|
|
|
|
|
await walk(new TreeItemConstructor("root", true), `_docs/${locale}/`)
|
|
|
|
|
).sort();
|
|
|
|
|
const me = tree.find(rootySlug);
|
|
|
|
|
|
|
|
|
|
if (isDir || slug.length === 0) {
|
|
|
|
|
if (slug.length === 0 || me === undefined) {
|
|
|
|
|
const plain = tree.plain();
|
|
|
|
|
return {
|
|
|
|
|
props: {
|
|
|
|
@ -126,29 +70,24 @@ export const getStaticProps: GetStaticProps = async ({ params, locale }) => {
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const mdxSource = await serialize(
|
|
|
|
|
(await readFile(resolve(process.cwd(), path))).toString(),
|
|
|
|
|
{
|
|
|
|
|
parseFrontmatter: true,
|
|
|
|
|
mdxOptions: {
|
|
|
|
|
remarkPlugins: [remarkGfm],
|
|
|
|
|
rehypePlugins: [
|
|
|
|
|
rehypeSlug,
|
|
|
|
|
[
|
|
|
|
|
rehypeAutolinkHeadings,
|
|
|
|
|
{
|
|
|
|
|
behavior: "wrap",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
rehypeHighlight,
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
props: {
|
|
|
|
|
source: mdxSource,
|
|
|
|
|
source: await serialize(me.contents!, {
|
|
|
|
|
parseFrontmatter: true,
|
|
|
|
|
mdxOptions: {
|
|
|
|
|
remarkPlugins: [remarkGfm],
|
|
|
|
|
rehypePlugins: [
|
|
|
|
|
rehypeSlug,
|
|
|
|
|
[
|
|
|
|
|
rehypeAutolinkHeadings,
|
|
|
|
|
{
|
|
|
|
|
behavior: "wrap",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
rehypeHighlight,
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
tree: tree.plain(),
|
|
|
|
|
...translations,
|
|
|
|
|
},
|
|
|
|
@ -157,18 +96,19 @@ export const getStaticProps: GetStaticProps = async ({ params, locale }) => {
|
|
|
|
|
|
|
|
|
|
const DocPage: NextPageWithLayout<{
|
|
|
|
|
source: MDXRemoteSerializeResult | null;
|
|
|
|
|
tree: TreeItem;
|
|
|
|
|
dir: TreeItem | null;
|
|
|
|
|
tree: ITreeItem;
|
|
|
|
|
dir: ITreeItem | null;
|
|
|
|
|
}> = ({ source, tree, dir }) => {
|
|
|
|
|
const {
|
|
|
|
|
query: { slug }, push
|
|
|
|
|
query: { slug },
|
|
|
|
|
push,
|
|
|
|
|
} = useRouter();
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (slug === undefined) {
|
|
|
|
|
push("/docs/crystal-linux/getting-started")
|
|
|
|
|
push("/docs/crystal-linux/getting-started");
|
|
|
|
|
}
|
|
|
|
|
}, [push, slug])
|
|
|
|
|
}, [push, slug]);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="mx-auto min-h-screen max-w-8xl space-y-12 space-x-4 px-4 pb-16 pt-24 md:px-8 md:pb-28 lg:pt-28">
|
|
|
|
@ -182,13 +122,16 @@ const DocPage: NextPageWithLayout<{
|
|
|
|
|
{dir.pretty !== null && <h1>{dir.pretty}</h1>}
|
|
|
|
|
<TranslationInfo />
|
|
|
|
|
<ul>
|
|
|
|
|
{slug && dir.children.map((child) => (
|
|
|
|
|
<li key={child.value}>
|
|
|
|
|
<Link href={`${(slug as string[]).join("/")}/${child.value}`}>
|
|
|
|
|
<a>{child.pretty ? child.pretty : child.value}</a>
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
))}
|
|
|
|
|
{slug &&
|
|
|
|
|
dir.children.map((child) => (
|
|
|
|
|
<li key={child.value}>
|
|
|
|
|
<Link
|
|
|
|
|
href={`${(slug as string[]).join("/")}/${child.value}`}
|
|
|
|
|
>
|
|
|
|
|
<a>{child.pretty ? child.pretty : child.value}</a>
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
))}
|
|
|
|
|
</ul>
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|