Skip to content

Commit

Permalink
feat: working reference projects in nextjs
Browse files Browse the repository at this point in the history
  • Loading branch information
darraghoriordan committed Mar 16, 2023
1 parent 7407855 commit 2ceca58
Show file tree
Hide file tree
Showing 47 changed files with 908 additions and 310 deletions.
3 changes: 0 additions & 3 deletions apps/frontend/src/learn-courses/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ const Home = () => {
return {
name: project.name,
path: `/open/code-doc/${project.key}`,
isCurrent:
location.pathname.includes(`/${project.key}/`) ||
location.pathname.endsWith(project.key),
} as MenuItem;
}) || [],
},
Expand Down
1 change: 1 addition & 0 deletions apps/marketing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@mapbox/rehype-prism": "0.8.0",
"@tailwindcss/forms": "0.5.3",
"@tailwindcss/typography": "0.5.9",
"@tanstack/react-query": "4.26.1",
"@use-miller/shared-api-client": "workspace:*",
"@use-miller/shared-frontend-tooling": "workspace:1.0.0",
"autoprefixer": "10.4.14",
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export function Footer() {
<p className="text-center text-3xl text-white">Miller</p>
<nav className="mt-10 text-sm" aria-label="quick links">
<div className="-my-1 flex justify-center gap-x-6">
<NavLink href="#features">Features</NavLink>
<NavLink href="#pricing">Pricing</NavLink>
<NavLink href="/#features">Features</NavLink>
<NavLink href="/#pricing">Pricing</NavLink>
<NavLink href="/get-started">Get Started</NavLink>
</div>
</nav>
Expand Down
18 changes: 18 additions & 0 deletions apps/marketing/src/docs/components/DocArticle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { FullDoc } from "../docParser.js";

export const DocArticle = ({ article }: { article: FullDoc }) => {
return (
<div className="ml-24 mt-[1em] mr-4">
<h1 className="text-white font-medium text-4xl mb-8">
{article?.title}
</h1>

<article
className="mb-4 prose prose-lg prose-invert"
dangerouslySetInnerHTML={{
__html: article?.html,
}}
></article>
</div>
);
};
69 changes: 69 additions & 0 deletions apps/marketing/src/docs/components/LeftMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { colorVariants } from "@use-miller/shared-frontend-tooling";
import clsx from "clsx";
import { useRouter } from "next/router.js";
import { LeftMenuItem } from "./LeftMenuItem.js";

export type MenuItem = {
name: string;
path: string;
};
export type MenuSection = {
name: string;
items: MenuItem[];
};

const isCurrentMenuItem = (path: string, item: MenuItem) => {
// special case for the docs route
if (path === "/docs" && item.path === "/docs/get-started-installation")
return true;

return item.path === path;
};

export function LeftMenu({ menuSections }: { menuSections: MenuSection[] }) {
const path = useRouter();

return (
<div className="flex">
<div className="flex flex-col flex-grow ml-4 pt-[1em]">
<h1
className={clsx(
`mb-8 font-bold uppercase`,
colorVariants["green"].foreground
)}
>
Docs
</h1>
{menuSections?.map((section) => (
<div key={section.name}>
<h3 className="mb-2 font-bold text-white uppercase">
{section.name}
</h3>
<ul className="mr-4">
{section.items.map((item) => (
<LeftMenuItem
key={item.path}
item={item}
isCurrent={isCurrentMenuItem(
path.asPath,
item
)}
/>
))}
</ul>
</div>
))}
</div>
<div className="flex flex-col">
<div
style={{
background: "linear-gradient(#56d364, #00bcd4)",
}}
className="h-full w-[2px]"
>
&nbsp;
</div>
</div>
</div>
);
}
34 changes: 34 additions & 0 deletions apps/marketing/src/docs/components/LeftMenuItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { colorVariants } from "@use-miller/shared-frontend-tooling";
import clsx from "clsx";
import Link from "next/link.js";
import { MenuItem } from "./LeftMenu.js";

export function LeftMenuItem({
item,
isCurrent,
}: {
item: MenuItem;
isCurrent: boolean;
}) {
return (
<li
key={item.path}
className={clsx(
"px-2 mb-2 ml-1 text-sm text-white whitespace-nowrap",
{
[colorVariants["green"].backgroundShade]: isCurrent,
["rounded-md"]: isCurrent,
}
)}
>
<Link
href={item.path}
className={clsx("cursor-pointer", {
[colorVariants["green"].foreground]: isCurrent,
})}
>
{item.name}
</Link>
</li>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import remarkRehype from "remark-rehype";
import remarkEmbedImages from "remark-embed-images";
import rehypeFormat from "rehype-format";
import rehypeStringify from "rehype-stringify";
import { getAllCourses } from "@use-miller/shared-frontend-tooling";
import { GetStaticPaths } from "next";

const fileDirectory = path.join(process.cwd(), "src", "docs");
const fileDirectory = path.join(process.cwd(), "src", "docs", "page-content");
export type SummaryDoc = PostMatter & {
slug: string;
};
Expand All @@ -26,39 +28,47 @@ export type PostMatter = {
export type FullDoc = SummaryDoc & {
html: string;
};
export const defaultArticleSlug = "get-started-installation";
export function getSortedPostsData(): SummaryDoc[] {
// Get file names under /posts
const fileNames = fs.readdirSync(fileDirectory);
const allPostsData = fileNames.map((fileName) => {
// Remove ".md" from file name to get slug
const slug = fileName.replace(/\.md$/, "");
const fileNames = fs.readdirSync(fileDirectory, { withFileTypes: true });
const allPostsData = fileNames
.filter((dirEntry) => dirEntry.isFile())
.map((fileName) => {
// Remove ".md" from file name to get slug
const slug = fileName.name.replace(/\.md$/, "");

// Read markdown file as string
const fullPath = path.join(fileDirectory, fileName);
const fileContents = fs.readFileSync(fullPath, "utf8");
// Read markdown file as string
const fullPath = path.join(fileDirectory, fileName.name);

// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents);
console.log(fileName, matterResult.data);
const fileContents = fs.readFileSync(fullPath, "utf8");

return {
slug,
...matterResult.data,
};
}) as unknown as SummaryDoc[];
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents);

return {
slug,
...matterResult.data,
};
}) as unknown as SummaryDoc[];
// Sort posts by date

return allPostsData.sort((a, b) => {
if (a.date < b.date) {
if (a.section < b.section) {
return 1;
} else {
return -1;
}
});
}

export async function getPostData(slug: string): Promise<FullDoc> {
const fullPath = path.join(fileDirectory, `${slug}.md`);
export async function getSinglePost(slug?: string): Promise<FullDoc> {
let renderSlug = slug;
if (!slug || slug === "index" || slug === "" || slug === "/") {
renderSlug = defaultArticleSlug;
}

const fullPath = path.join(fileDirectory, `${renderSlug}.md`);
const fileContents = fs.readFileSync(fullPath, "utf8");

// Use gray-matter to parse the post metadata section
Expand All @@ -70,7 +80,7 @@ export async function getPostData(slug: string): Promise<FullDoc> {
const markdownResult = await markdownToHtml(matterResult.content);
// Combine the data with the id
return {
slug,
slug: renderSlug!,
html: markdownResult,
...matterResult.data,
};
Expand All @@ -90,14 +100,28 @@ export async function markdownToHtml(markdownSection: any): Promise<string> {
return file.toString();
}

export function getAllPostIds() {
const fileNames = fs.readdirSync(fileDirectory);

return fileNames.map((fileName) => {
return {
params: {
slug: fileName.replace(/\.md$/, ""),
},
export async function getStaticDocsPageSlugs(): Promise<{
paths: {
params: {
slug: string;
};
});
}[];
fallback: boolean;
}> {
const allPosts = getSortedPostsData();

const paths = [
...allPosts.map((post) => {
return {
params: {
slug: post.slug,
},
};
}),
];

return {
paths,
fallback: false,
};
}
49 changes: 49 additions & 0 deletions apps/marketing/src/docs/leftMenu.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {
getAllCourses,
MenuItem,
MenuSection,
} from "@use-miller/shared-frontend-tooling";
import { getSortedPostsData } from "./docParser.js";

export async function createMenu(): Promise<MenuSection[]> {
if (fetch === undefined) {
throw new Error("fetch is undefined");
}
const projects = await getAllCourses({
apiBase: process.env.NEXT_PUBLIC_API_BASE_PATH,
fetchApi: fetch,
});
const allArticles = getSortedPostsData();

const menuSections: MenuSection[] = [
{
// get started first!
name: "Get Started",
items:
allArticles
.filter((p) => p.section === "Get Started")
.sort((a, b) => a.order - b.order)
.map((post) => {
return {
name: post.title,
path: `/docs/${post.slug}`,
} as MenuItem;
}) || [],
},
{
// then the project references
name: "Projects",
items:
projects.map((project) => {
return {
name: project.name,
path: `/docs/reference/${project.key}/${btoa(
"/README.md"
)}`,
} as MenuItem;
}) || [],
},
];

return menuSections;
}
Loading

0 comments on commit 2ceca58

Please sign in to comment.