add veryyyy basic docs renderer

This commit is contained in:
Lee 2024-04-20 00:34:42 +01:00
parent d0f926f330
commit 8169c08faa
11 changed files with 2011 additions and 11 deletions

11
documentation/landing.md Normal file

@ -0,0 +1,11 @@
---
title:
---
# Minecraft Utilities Documentation
Welcome to the Minecraft Utilities documentation! Here you can find information on how to use the various features of the plugin.
## Getting Started
This is still a work in progress, so please be patient as we continue to add more documentation.

@ -1,3 +1,5 @@
import createMDX from '@next/mdx'
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
output: "standalone", output: "standalone",
@ -17,4 +19,4 @@ const nextConfig = {
}, },
}; };
export default nextConfig; export default createMDX()(nextConfig)

@ -12,6 +12,9 @@
"@eslint/eslintrc": "^3.0.2", "@eslint/eslintrc": "^3.0.2",
"@heroicons/react": "^2.1.3", "@heroicons/react": "^2.1.3",
"@hookform/resolvers": "^3.3.4", "@hookform/resolvers": "^3.3.4",
"@mdx-js/loader": "^3.0.1",
"@mdx-js/react": "^3.0.1",
"@next/mdx": "^14.2.2",
"@radix-ui/react-context-menu": "^2.1.5", "@radix-ui/react-context-menu": "^2.1.5",
"@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-label": "^2.0.2", "@radix-ui/react-label": "^2.0.2",
@ -21,6 +24,7 @@
"@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-toast": "^1.1.5",
"@radix-ui/react-tooltip": "^1.0.7", "@radix-ui/react-tooltip": "^1.0.7",
"@types/mdx": "^2.0.13",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"clipboard-copy": "^4.0.1", "clipboard-copy": "^4.0.1",
"clsx": "^2.1.0", "clsx": "^2.1.0",
@ -35,6 +39,7 @@
"react-spinners": "^0.13.8", "react-spinners": "^0.13.8",
"react-syntax-highlighter": "^15.5.0", "react-syntax-highlighter": "^15.5.0",
"react-use-websocket": "4.8.1", "react-use-websocket": "4.8.1",
"remote-mdx": "^0.0.4",
"tailwind-merge": "^2.2.2", "tailwind-merge": "^2.2.2",
"tailwindcss-animate": "^1.0.7" "tailwindcss-animate": "^1.0.7"
}, },

1869
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,49 @@
import { getDocumentation } from "@/common/documentation";
import { CustomMDX } from "@/app/components/mx-components";
export async function generateStaticParams() {
let documentationPages = getDocumentation();
return documentationPages.map(page => ({
slug: [page.slug],
}));
}
type DocumentationPageParams = {
params: {
slug?: string;
};
};
export default function Page({ params: { slug } }: DocumentationPageParams) {
const documentationPages = getDocumentation();
let page = documentationPages.find(page => page.slug === slug);
// Fallback to the landing page
if (!page) {
page = documentationPages.find(page => page.slug === "landing");
}
// Fallback to a 404 page if we still can't find the page
if (!page) {
page = {
metadata: {
title: "404 - Not Found",
},
content: "If you are seeing this, it means that the documentation page you are looking for does not exist.",
slug: "empty",
};
}
return (
<div className="w-full px-4 flex flex-col gap-4">
{/* The documentation page title */}
{page.metadata.title && <h1 className="text-center">{page.metadata.title}</h1>}
{/* The content of the documentation page */}
<div className="text-left w-full">
<CustomMDX source={page.content} />
</div>
</div>
);
}

@ -32,8 +32,8 @@ type Button = {
const buttons: Button[] = [ const buttons: Button[] = [
{ {
title: "Get Started", title: "Get Started",
tooltip: "Click to view get started!", tooltip: "Click to get started!",
url: "/player", url: "/documentation",
}, },
{ {
title: "Postman Collection", title: "Postman Collection",

@ -93,7 +93,8 @@ export async function generateMetadata({ params: { platform, hostname } }: Param
description += "Click to view more information about the server."; description += "Click to view more information about the server.";
return generateEmbed({ return generateEmbed({
title: `${capitalizeFirstLetter(platform)} Server: ${serverHostname}`, title: `${serverHostname} ${capitalizeFirstLetter(platform)} Server`,
embedTitle: `${capitalizeFirstLetter(platform)} Server: ${serverHostname}`,
description: description, description: description,
image: favicon, image: favicon,
}); });

@ -0,0 +1,10 @@
import { MDXRemote } from "remote-mdx/rsc";
const components = {
h1: (props: any) => <h1 className="text-2xl font-semibold pb-2" {...props} />,
h2: (props: any) => <h1 className="text-xl font-semibold pb-2 pt-4" {...props} />,
};
export function CustomMDX(props: any) {
return <MDXRemote {...props} components={{ ...components, ...(props.components || {}) }} />;
}

@ -32,6 +32,7 @@ const pages: Page[] = [
{ name: "Server", url: "/server/java" }, { name: "Server", url: "/server/java" },
{ name: "Mojang", url: "/mojang/status" }, { name: "Mojang", url: "/mojang/status" },
{ name: "API", url: "https://api.mcutils.xyz", openInNewTab: true }, { name: "API", url: "https://api.mcutils.xyz", openInNewTab: true },
{ name: "Docs", url: "/documentation", openInNewTab: true },
]; ];
export default function NavBar(): ReactElement { export default function NavBar(): ReactElement {

@ -0,0 +1,52 @@
import * as fs from "node:fs";
import path from "node:path";
type Metadata = {
title: string;
};
function parseFrontmatter(fileContent: string) {
let frontmatterRegex = /---\s*([\s\S]*?)\s*---/;
let match = frontmatterRegex.exec(fileContent);
let frontMatterBlock = match![1];
let content = fileContent.replace(frontmatterRegex, "").trim();
let frontMatterLines = frontMatterBlock.trim().split("\n");
let metadata: Partial<Metadata> = {};
frontMatterLines.forEach(line => {
let [key, ...valueArr] = line.split(": ");
let value = valueArr.join(": ").trim();
value = value.replace(/^['"](.*)['"]$/, "$1"); // Remove quotes
metadata[key.trim() as keyof Metadata] = value;
});
return { metadata: metadata as Metadata, content };
}
const documentationDirectory = path.join(process.cwd(), "documentation");
/**
* Gets the files for the documentation.
*/
function getDocumentationFiles() {
return fs.readdirSync(documentationDirectory);
}
function getDocumentationFileContent(file: string) {
return fs.readFileSync(path.join(documentationDirectory, file), "utf-8");
}
export function getDocumentation() {
const files = getDocumentationFiles();
return files.map(file => {
const { metadata, content } = parseFrontmatter(getDocumentationFileContent(file));
let slug = path.basename(file, path.extname(file));
return {
metadata,
content,
slug,
};
});
}

@ -6,6 +6,11 @@ type Embed = {
*/ */
title: string; title: string;
/**
* The title of the embed.
*/
embedTitle?: string;
/** /**
* The description of the embed. * The description of the embed.
*/ */
@ -21,10 +26,17 @@ type Embed = {
* Generates metadata for a embed. * Generates metadata for a embed.
* *
* @param title the title of the embed * @param title the title of the embed
* @param embedTitle the title of the embed
* @param description the description of the embed * @param description the description of the embed
* @param image the image to show as the thumbmail
* @returns the metadata for the embed * @returns the metadata for the embed
*/ */
export function generateEmbed({ title, description, image }: Embed): Metadata { export function generateEmbed({ title, embedTitle, description, image }: Embed): Metadata {
// Fall back to the title
if (!embedTitle) {
embedTitle = title;
}
const metadata: Metadata = { const metadata: Metadata = {
title: `${title}`, title: `${title}`,
openGraph: { openGraph: {