@@ -0,0 +1,126 @@
1+import Head from "next/head";
2+import Link from "next/link";
3+import { useRouter } from "next/router";
4+import { useState } from "react";
5+import classnames from "classnames";
6+import { join } from "path";
7+import { getDocs, formatDate, buildPageTree, getPage } from "../../lib/lib";
8+import Markdown from "../../components/Markdown";
9+import ContentArea from "../../components/ContentArea";
10+import Sidebar from "../../components/Sidebar";
11+import markdownStyles from "../../styles/markdown.module.css";
12+import { decode } from "html-entities";
13+
14+const breadcrumbs = (posts, paths) => {
15+ const results = [
16+ <Link href="/">Urbit</Link>,
17+ <span className="px-1">/</span>,
18+ <Link href="/community">Community</Link>,
19+ ];
20+ let thisLink = "/community";
21+ for (const path of paths) {
22+ posts = posts.children[path];
23+ thisLink = join(thisLink, path);
24+ results.push(
25+ <span className="px-1">/</span>,
26+ <Link href={thisLink}>{posts.title}</Link>
27+ );
28+ }
29+ return results;
30+};
31+
32+const childPages = (thisLink, children, level = 0) => (
33+ <ul className="pl-1">
34+ {children?.map((child) => (
35+ <li>{pageTree(join(thisLink, child.slug), child, level)}</li>
36+ ))}
37+ </ul>
38+);
39+
40+const pageTree = (thisLink, tree, level = 0) => {
41+ const router = useRouter();
42+
43+ const isThisPage = router.asPath === thisLink;
44+
45+ const pageItemClasses = classnames({
46+ "pl-4 text-black text-base hover:text-green": level === 0,
47+ "pl-8 text-black text-base hover:text-green": level === 1,
48+ "pl-12 text-black text-base hover:text-green": level === 2,
49+ "dot relative": isThisPage,
50+ "text-green": isThisPage,
51+ });
52+
53+ return (
54+ <>
55+ <Link href={thisLink}>
56+ <a className={`${pageItemClasses} cursor-pointer`}>{tree.title}</a>
57+ </Link>
58+ </>
59+ );
60+};
61+
62+export default function UsingLayout({ posts, data, params, search, markdown }) {
63+ return (
64+ <>
65+ <Head>
66+ <title>{data.title} / Community / urbit.org</title>
67+ </Head>
68+ <div className="flex w-screen h-screen min-h-screen w-screen">
69+ <Sidebar>{childPages("/community", posts.pages)}</Sidebar>
70+ <ContentArea
71+ breadcrumbs={breadcrumbs(posts, params.slug?.slice(0, -1) || "")}
72+ title={data.title}
73+ search={search}
74+ section={"Community"}
75+ >
76+ <div className={markdownStyles["markdown"]}>
77+ <article
78+ dangerouslySetInnerHTML={{ __html: decode(markdown) }}
79+ ></article>
80+ </div>
81+ </ContentArea>
82+ </div>
83+ </>
84+ );
85+}
86+
87+export async function getStaticProps({ params }) {
88+ const posts = buildPageTree(
89+ join(process.cwd(), "content/community"),
90+ "weight"
91+ );
92+
93+ const { data, content } = getPage(
94+ join(process.cwd(), "content/community", params.slug?.join("/") || "/")
95+ );
96+
97+ const markdown = await Markdown({ post: { content: content } });
98+
99+ return { props: { posts, data, markdown, params } };
100+}
101+
102+export async function getStaticPaths() {
103+ const posts = buildPageTree(
104+ join(process.cwd(), "content/community"),
105+ "weight"
106+ );
107+ const slugs = [];
108+
109+ const allHrefs = (thisLink, tree) => {
110+ slugs.push(thisLink, ...tree.pages.map((e) => join(thisLink, e.slug)));
111+ allHrefsChildren(thisLink, tree.children);
112+ };
113+
114+ const allHrefsChildren = (thisLink, children) => {
115+ Object.entries(children).map(([childSlug, child]) => {
116+ allHrefs(join(thisLink, childSlug), child);
117+ });
118+ };
119+
120+ allHrefs("/community", posts);
121+
122+ return {
123+ paths: slugs,
124+ fallback: false,
125+ };
126+}