Skip to content

Commit

Permalink
Merge pull request #4 from skunichetty/posts
Browse files Browse the repository at this point in the history
Added extended support for posts
  • Loading branch information
skunichetty authored May 29, 2024
2 parents da559b3 + e3afd58 commit 39c10b0
Show file tree
Hide file tree
Showing 14 changed files with 895 additions and 27 deletions.
6 changes: 5 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ import Navbar, { NavbarItem } from "@/components/navbar";
import type { Metadata } from "next";
import { Inter_Tight } from "next/font/google";
import "./globals.css";
import "katex/dist/katex.min.css";

const inter_tight = Inter_Tight({ subsets: ["latin"] });

export const metadata: Metadata = {
title: "skunichetty.dev",
title: {
template: "%s | skunichetty.dev",
default: "skunichetty.dev",
},
description: "Sachchit Kunichetty's Personal Website",
};

Expand Down
6 changes: 3 additions & 3 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ function LineWithHeading({ heading, description }: LineWithHeadingProps) {
return (
<p>
{heading}:&nbsp;&nbsp;
<span className="text-gray-500 dark:text-gray-400">{description}</span>
<span className="text-gray-600 dark:text-gray-400">{description}</span>
</p>
);
}
Expand Down Expand Up @@ -146,12 +146,12 @@ export default function Home() {
<Dropdown icon="graduation" title="Education">
<div className="md:text-base sm:text-sm text-xs sm:max-w-md max-w-sm ">
<p>Bachelor of Science in Engineering, Computer Science</p>
<div className="md:text-sm text-xs text-gray-500 dark:text-gray-400">
<div className="md:text-sm text-xs text-gray-600 dark:text-gray-400">
<div className="flex flex-row justify-between">
<p>University of Michigan, Ann Arbor</p>
<p>Aug 2020 - Apr 2024</p>
</div>
<p className="text-gray-500 dark:text-gray-400">
<p className="text-gray-600 dark:text-gray-400">
Minors in Business Administration, Mathematics
</p>
</div>
Expand Down
14 changes: 14 additions & 0 deletions app/posts/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Metadata } from "next";

export const metadata: Metadata = {
title: "Posts",
description: "All Blog Posts by Sachchit Kunichetty",
};

interface LayoutProps {
children: React.ReactNode;
}

export default function PostLayout({ children }: LayoutProps) {
return <div className="lg:mx-96 sm:mx-32 mx-10 block">{children}</div>;
}
107 changes: 105 additions & 2 deletions app/posts/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,106 @@
export default function AboutMe() {
return <div className="px-10">No posts yet - check back later!</div>;
import { readFile, readdir, lstat } from "fs/promises";
import path from "path";
import Link from "next/link";
import { dateComparator } from "@/app/utils";
import { PostMetadata } from "@/components/post";
import { parse } from "yaml";

interface RawPostMetadata {
title: string;
date: string;
editDate?: string;
author: string;
slug: string;
keywords: string[];
description: string;
}

async function getPosts() {
const entries = await readdir("app/posts", { withFileTypes: true });
const folders = entries
.filter((entry) => entry.isDirectory())
.map((entry) => path.join(entry.parentPath, entry.name));

const raw_metadata: RawPostMetadata[] = await Promise.all(
folders.map(async (folder) => {
const filename = `${folder}/page.mdx`;
const main = await readFile(filename);
const content = main.toString().split("\n");

let index = 0;
if (content[index++] !== "---") {
console.error(`Invalid MDX file "${filename}": no frontmatter found`);
} else {
while (index < content.length && content[index] != "---") {
++index;
}
return parse(content.slice(1, index).join("\n"));
}
})
);

return raw_metadata
.map((post) => {
let entry: PostMetadata = {
...post,
date: new Date(post.date),
editDate: undefined,
};
if (post.editDate != undefined) {
entry.editDate = new Date(post.editDate);
}
return entry;
})
.sort((a, b) => {
return dateComparator(a.date, b.date, false);
});
}

function PostInfo({
title,
date,
editDate,
author,
slug,
description,
}: PostMetadata) {
return (
<div className="block py-2">
<Link
className="text-xl hover:text-blue-500 transition"
href={`/posts/${slug}`}
>
{title}
</Link>
<div className="flex flex-row gap-2 text-sm text-gray-600 dark:text-gray-400">
<p>{date.toLocaleDateString()}</p>
{editDate != undefined ? (
<p>(Edited {editDate.toLocaleDateString()})</p>
) : null}
</div>
<div className="text-gray-600 dark:text-gray-400 text-sm mt-1">
{description}
</div>
</div>
);
}

export default async function PostMainPage() {
const posts = await getPosts();
return (
<div>
<h1 className="text-2xl font-bold">Posts</h1>
{posts.length === 0 ? (
<p className="text-gray-600 dark:text-gray-400">
No posts yet - check back later!
</p>
) : (
<div className="flex flex-col divide-y-2">
{posts.map((post) => (
<PostInfo key={post.slug} {...post} />
))}
</div>
)}
</div>
);
}
9 changes: 9 additions & 0 deletions app/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function dateComparator(a: Date, b: Date, ascending: boolean) {
let number = 0;
if (a < b) {
number = -1;
} else if (a > b) {
number = 1;
}
return ascending ? number : number * -1;
}
15 changes: 5 additions & 10 deletions components/experience_list.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Link from "next/link";
import { dateComparator } from "@/app/utils";

interface ExperienceItemProps {
position: string;
Expand Down Expand Up @@ -38,7 +39,7 @@ export function ExperienceItem({
) : null}
{position}
</p>
<div className="text-gray-500 dark:text-gray-400 md:text-sm text-xs flex flex-row justify-between">
<div className="text-gray-600 dark:text-gray-400 md:text-sm text-xs flex flex-row justify-between">
<div className="flex flex-row">
{href == undefined ? (
<span>{company}</span>
Expand Down Expand Up @@ -72,15 +73,9 @@ export default function ExperienceList({ experiences }: ExperienceListProps) {
<ul className="sm:max-w-md max-w-sm divide-y-2 divide-gray-400">
{experiences
.sort((a, b) => {
const a_date = a.end_date == undefined ? Date.now() : a.end_date;
const b_date = b.end_date == undefined ? Date.now() : b.end_date;
if (a_date < b_date) {
return 1;
} else if (a_date > b_date) {
return -1;
} else {
return 0;
}
const a_date = a.end_date == undefined ? new Date() : a.end_date;
const b_date = b.end_date == undefined ? new Date() : b.end_date;
return dateComparator(a_date, b_date, false);
})
.map((experience) => (
<li className="py-2" key={experience.position}>
Expand Down
2 changes: 1 addition & 1 deletion components/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import SocialMediaLink from "./social";

export default function Footer() {
return (
<footer className="flex flex-row justify-center items-center gap-2 mt-auto p-10 text-gray-500 dark:text-gray-400 divide-x-2 divide-gray-400">
<footer className="flex flex-row justify-center items-center gap-2 mt-auto p-10 text-gray-600 dark:text-gray-400 divide-x-2 divide-gray-400">
<div className="flex flex-row justify-center items-center gap-2">
<SocialMediaLink
type="linkedin"
Expand Down
2 changes: 1 addition & 1 deletion components/location.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function Clock({ locale, timezone }: ClockProps) {

export default function Location() {
return (
<div className="flex flex-row gap-4 text-sm text-gray-500 dark:text-gray-400 mt-1">
<div className="flex flex-row gap-4 text-sm text-gray-600 dark:text-gray-400 mt-1">
<div className="flex flex-row items-center gap-1">
<Icon name="location" />
<h1>New York, NY, US</h1>
Expand Down
8 changes: 4 additions & 4 deletions components/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function NavbarRowItem({ title, href, active }: NavbarItemProps) {
return (
<Link
className={`font-bold ${
active ? "" : "text-gray-500 dark:text-gray-400"
active ? "" : "text-gray-600 dark:text-gray-400"
} hover:text-blue-500 transition`}
href={href}
>
Expand All @@ -41,7 +41,7 @@ function NavbarDropdownItem({ title, href, active }: NavbarItemProps) {
return (
<Link
className={`block w-full ${
active ? "font-bold" : "font-normal text-gray-500 dark:text-gray-400"
active ? "font-bold" : "font-normal text-gray-600 dark:text-gray-400"
} hover:text-blue-500 py-2 pl-3 transition flex flew-row items-center gap-2`}
href={href}
>
Expand All @@ -52,7 +52,7 @@ function NavbarDropdownItem({ title, href, active }: NavbarItemProps) {

function NavbarRow({ links, pathname }: NavbarSubtypeProps) {
return (
<ul className="flex-row sm:flex hidden divide-x-2 divide-gray-400 text-gray-500 dark:text-gray-400">
<ul className="flex-row sm:flex hidden divide-x-2 divide-gray-400 text-gray-600 dark:text-gray-400">
{links.map((item) => (
<li key={item.title} className="px-3 my-1">
<NavbarRowItem
Expand All @@ -68,7 +68,7 @@ function NavbarRow({ links, pathname }: NavbarSubtypeProps) {

function NavbarDropdown({ links, pathname }: NavbarSubtypeProps) {
return (
<ul className="flex-col sm:hidden visible mt-6 divide-y-2 divide-gray-400 border-y-2 text-gray-500 dark:text-gray-400">
<ul className="flex-col sm:hidden visible mt-6 divide-y-2 divide-gray-400 border-y-2 text-gray-600 dark:text-gray-400">
{links.map((item) => (
<li key={item.title}>
<NavbarDropdownItem
Expand Down
74 changes: 74 additions & 0 deletions components/post.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"use client";
import katex from "katex";
import { MutableRefObject, useEffect, useRef } from "react";

export interface PostMetadata {
title: string;
date: Date;
editDate?: Date;
author: string;
slug: string;
keywords: string[];
description: string;
}

interface PostHeaderProps {
title: string;
date: Date;
}

interface CalloutProps {
emoji: string;
children: React.ReactNode;
}

interface ExampleProps {
emoji: string;
children: React.ReactNode;
}

interface BlockEquationProps {
latex: string;
}

export function PostHeader({ title, date }: PostHeaderProps) {
return (
<div className="mb-4">
<h1 className="text-5xl font-bold">{title}</h1>
<h4 className="text-sm text-gray-600 dark:text-gray-400">
{date.toLocaleDateString()}
</h4>
</div>
);
}

export function Callout({ emoji, children }: CalloutProps) {
return (
<div className="flex flex-row items-center px-6 pb-5 pt-2 border-2 border-stone-900 dark:border-stone-100 my-4 mx-8 bg-stone-300 dark:bg-stone-900">
<p className="text-2xl">{emoji}</p>
<div className="px-5 col-span-2">{children}</div>
</div>
);
}

export function Example({ children }: ExampleProps) {
return (
<div className="px-6 py-5 border-2 border-blue-500 my-4 mx-8 bg-stone-300 dark:bg-stone-900">
<p className="font-bold">Example:</p>
{children}
</div>
);
}

export function BlockEquation({ latex }: BlockEquationProps) {
const body = useRef<HTMLDivElement>(null);

useEffect(() => {
if (body.current != null) {
katex.render(latex, body.current, {
displayMode: true,
});
}
});
return <div ref={body} className="mt-3 flex flex-row justify-center"></div>;
}
35 changes: 34 additions & 1 deletion mdx-components.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,42 @@
import type { MDXComponents } from "mdx/types";
import Link from "next/link";

export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
h1: ({ children }) => (
<h1 className="text-4xl font-medium mb-1">{children}</h1>
<h1 className="text-3xl font-bold mt-5 mb-1">{children}</h1>
),
h2: ({ children }) => (
<h2 className="text-2xl font-bold mt-3 mb-1">{children}</h2>
),
h3: ({ children }) => <h3 className="text-2xl mt-3 mb-1">{children}</h3>,
h4: ({ children }) => (
<h4 className="text-xl font-medium mt-2 mb-1">{children}</h4>
),
ul: ({ children }) => <ul className="list-disc ml-5 mb-3">{children}</ul>,
ol: ({ children }) => <ol className="list-decimal ml-5 mb-3">{children}</ol>,
em: ({ children }) => <em className="mr-[0.125rem]">{children}</em>,
p: ({ children }) => (
<p className=" sm:text-base text-sm mt-3">{children}</p>
),
a: (props) => (
<Link
className="underline font-semibold hover:text-blue-500 transition"
href={props.href || ""}
{...props}
>
{props.children}
</Link>
),
code: ({ children }) => (
<code className="text-sm p-1 bg-stone-850 dark:bg-stone-800 rounded-md text-blue-500">
{children}
</code>
),
blockquote: ({ children }) => (
<blockquote className="border-l-4 pl-4 dark:text-gray-400 text-gray-600 border-stone-900 dark:border-stone-100">
{children}
</blockquote>
),
...components,
};
Expand Down
Loading

0 comments on commit 39c10b0

Please sign in to comment.