Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"reading-time": "^1.5.0",
"remark-toc": "^9.0.0",
"sanitize-html": "^2.11.0",
"tailwind-scrollbar": "^4.0.0",
"unplugin-icons": "^0.18.1"
}
}
36 changes: 20 additions & 16 deletions src/components/blog/PostInfo.astro
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
---
import type { BlogPost } from "~/content/config.ts";
import type { BlogPost } from "~/content.config";
import { formatPostDate, calcReadingTime, slugifyPostDate } from "~/lib/utils";

import { marked } from "marked";
import readingTime from "reading-time";
import { Icon } from "astro-icon/components";
interface Props {
post: BlogPost;
wordCount: number;
}
const { post, wordCount } = Astro.props as Props;

import { marked } from "marked";

const body = `${post.body
.split(" ")
.slice(0, wordCount + 1)
.join(" ")}...`;
const postBody = marked.parse(body);
const body = post?.body?.split(" ").slice(0, wordCount).join(" ") || "";
const content = marked(body);
---

<article class="py-3.5 grid md:grid-cols-[18rem_auto]">
Expand All @@ -24,13 +21,20 @@ const postBody = marked.parse(body);
</span>
<time
datetime={post.data.pubDate.toISOString()}
class="font-semibold text-sm text-gray-700 dark:text-gray-400"
class="font-semibold text-sm text-branding-gray-700 dark:text-gray-400"
>{formatPostDate(post.data.pubDate)}</time
>
<span
class="block mt-1 text-branding-gray-600 dark:text-branding-gray-400 text-sm font-semibold">
{calcReadingTime(post.body)}
</span>
{
post.body && (
<div class="block mt-1 text-branding-gray-600 dark:text-branding-gray-400 text-sm font-semibold ml-1">
<div class="inline-flex items-center justify-between">
<Icon name="mdi:clock" class="inline" />
<span class="ml-1">{readingTime(post.body).text}</span>
</div>
</div>
)
}

{
post.data.series && (
<div class="text-gray-700 dark:text-gray-400 text-sm mt-1 break-words">
Expand All @@ -46,10 +50,10 @@ const postBody = marked.parse(body);
</h2>
<div
class="prose prose-neutral dark:prose-invert max-w-[80ch] prose-branding-blue"
set:html={postBody}
set:html={content}
/>
<a
href={`/blog/${slugifyPostDate(post.data.pubDate)}/${post.slug}`}
href={`/blog/${slugifyPostDate(post.data.pubDate)}/${post.id}`}
class="block rounded-sm text-sm bg-branding-navy-600 w-fit text-white h-fit px-2 py-1 mt-1 dark:hover:bg-branding-navy-500 duration-100 transition-colors hover:bg-branding-navy-700"
>Read More</a
>
Expand Down
12 changes: 6 additions & 6 deletions src/content.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { z, defineCollection, type CollectionEntry } from "astro:content";
import { glob } from "astro/loaders";

const blogSchema = defineCollection({
type: "content",
const blog = defineCollection({
loader: glob({ pattern: "**/*.{md,mdx}", base: "src/content/blog" }),
schema: ({ image }) =>
z.object({
title: z.string({
Expand Down Expand Up @@ -48,8 +49,8 @@ export type BlogPost = CollectionEntry<"blog">;

//export type BlogPost = CollectionEntry<"blog">;

const projectSchema = defineCollection({
type: "content",
const projects = defineCollection({
loader: glob({ pattern: "**/*.{md,mdx}", base: "src/content/projects" }),
schema: z.object({
title: z.string({ required_error: "A title is required for a project." }),
draft: z
Expand Down Expand Up @@ -106,6 +107,5 @@ const projectSchema = defineCollection({
export type Project = CollectionEntry<"projects">;

export const collections = {
blog: blogSchema,
projects: projectSchema,
blog, projects
};
111 changes: 0 additions & 111 deletions src/content/config.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/layouts/BaseLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const { title, description } = Astro.props;
<Header />
<FixedSidebar />
<main
class="grid-area-main overflow-y-scroll scrollbar-thin scroll-smooth motion-reduce:scroll-auto">
class="grid-area-main overflow-y-scroll scrollbar-thin scroll-smooth motion-reduce:scroll-auto scrollbar-h-32">
<slot />
</main>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ export function toTitleCase(str: string): string {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
}

4 changes: 2 additions & 2 deletions src/pages/blog/[...page].astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import PostInfo from "~/components/blog/PostInfo.astro";
import { getCollection, type CollectionEntry } from "astro:content";
import Pagination from "~/components/Pagination.astro";
import { RECENT_POST_COUNT } from "~/consts";
import type { BlogPost } from "~/content/config.ts";
import type { BlogPost } from "~/content.config";
export const getStaticPaths = (async ({ paginate }) => {
const posts: CollectionEntry<"blog">[] = await getCollection(
"blog",
Expand All @@ -22,7 +22,7 @@ const { page } = Astro.props;

<BaseLayout title="Blog" description="All the blog posts on my site.">
<section
class="min-h-full grid grid-rows-[1fr_auto] container mx-auto px-5 overflow-hidden">
class="min-h-full grid grid-rows-(1fr_auto) container mx-auto px-5 overflow-hidden">
<div class="divide-y-2 divide-gray-500">
{
page.data.map((post: BlogPost) => (
Expand Down
6 changes: 3 additions & 3 deletions src/pages/blog/[...slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import type {
InferGetStaticPropsType,
GetStaticPaths,
} from "astro";
import { getCollection } from "astro:content";
import { getCollection, render } from "astro:content";
import BlogPostLayout from "~/layouts/BlogPostLayout.astro";
import { slugifyPostDate } from "~/lib/utils";

export const getStaticPaths = (async () => {
const posts = await getCollection("blog");
return posts.map((post) => {
return {
params: { slug: `${slugifyPostDate(post.data.pubDate)}/${post.slug}` },
params: { slug: `${slugifyPostDate(post.data.pubDate)}/${post.id}` },
props: { post },
};
});
Expand All @@ -24,7 +24,7 @@ type Props = InferGetStaticPropsType<typeof getStaticPaths>;
// eslint-disable-next-line
const { slug } = Astro.params as Params;
const { post } = Astro.props;
const { Content } = await post.render();
const { Content } = await render(post);
---

<BlogPostLayout frontmatter={post.data}>
Expand Down
48 changes: 46 additions & 2 deletions src/pages/categories/[category]/[...page].astro
Original file line number Diff line number Diff line change
@@ -1,8 +1,52 @@
---
import type { GetStaticPaths } from "astro";

import { getCollection } from "astro:content";
import { slugifyUrl, toTitleCase } from "~/lib/utils";
import type { BlogPost } from "~/content.config";

import BaseLayout from "~/layouts/BaseLayout.astro";
import PostInfo from "~/components/blog/PostInfo.astro";
import Pagination from "~/components/Pagination.astro";

import { getCollection } from "astro:content";
import { slugifyUrl, toTitleCase } from "~/lib/utils";
export async function getStaticPaths({ paginate }) {
const allPosts = await getCollection("blog");
const uniqueCats = [
...new Set(allPosts.map((post) => post.data?.categories).flat()),
].filter((category) => category !== undefined);

return uniqueCats.flatMap((category) => {
const filteredPosts = allPosts.filter((post) =>
post.data.categories?.includes(category!),
);
return paginate(filteredPosts, {
params: { category: slugifyUrl(category) },
props: { category, slug: slugifyUrl(category) },
pageSize: 4,
});
});
}

const { category } = Astro.params;
const { page } = Astro.props;
---

<BaseLayout
title=`Category: ${toTitleCase(category)}`
description={`All blog posts categorized with ${category}`}>
<article class="p-2 prose prose-neutral dark:prose-invert prose-h1:mb-2">
<h1>Category: {toTitleCase(category)}</h1>
</article>
<section class="min-h-screen text-gray-600">
<div class="container mx-auto px-5 h-screen">
<div class="divide-y-2 divide-gray-500">
{
page.data.map((post: BlogPost) => (
<PostInfo post={post} wordCount={35} />
))
}
</div>
<Pagination prevUrl={page.url.prev} nextUrl={page.url.next} />
</div>
</section>
</BaseLayout>
Loading
Loading