Skip to content

Commit

Permalink
refactor: polish posts tests and documentation (#531)
Browse files Browse the repository at this point in the history
Towards #267 and #492.
  • Loading branch information
iuioiua committed Sep 7, 2023
1 parent f6644c6 commit 9c5590f
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 44 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ needs.

### Create a Blog Post

1. Create a `.md` file in `/data/posts` with the filename as the slug of the
blog post URL. E.g. a file with path `/data/posts/hello-there.md` will have
1. Create a `.md` file in the [/posts](/posts) with the filename as the slug of
the blog post URL. E.g. a file with path `/posts/hello-there.md` will have
path `/blog/hello-there`.
1. Write the
[Front Matter](https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/)
Expand All @@ -143,7 +143,7 @@ needs.
````md
---
title: This is my first blog post!
published_at: 2022-11-04T15:00:00.000Z
publishedAt: 2022-11-04T15:00:00.000Z
summary: This is an excerpt of my first blog post.
---

Expand All @@ -162,7 +162,7 @@ needs.
1. Navigate to the URL of the newly created blog post. E.g.
`http://localhost:8000/blog/hello-there`.

See other examples of blog post files in `/data/posts`.
See other examples of blog post files in [/posts](/posts).

### Themes

Expand Down
2 changes: 1 addition & 1 deletion components/Head.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2023 the Deno authors. All rights reserved. MIT license.
import { Head as _Head } from "$fresh/runtime.ts";
import Meta, { type MetaProps } from "./Meta.tsx";
import { SITE_DESCRIPTION, SITE_NAME } from "../utils/constants.ts";
import { SITE_DESCRIPTION, SITE_NAME } from "@/utils/constants.ts";
import { ComponentChildren } from "preact";

/**
Expand Down
2 changes: 1 addition & 1 deletion data/posts/first-post.md → posts/first-post.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: This is my first blog post!
published_at: 2022-11-04T15:00:00.000Z
publishedAt: 2022-11-04T15:00:00.000Z
summary: This is an excerpt of my first blog post.
---

Expand Down
2 changes: 1 addition & 1 deletion data/posts/second-post.md → posts/second-post.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Second post
published_at: 2022-11-04T15:00:00.000Z
publishedAt: 2022-11-04T15:00:00.000Z
summary: Lorem Ipsum is simply dummy text of the printing and typesetting industry.
---

Expand Down
2 changes: 1 addition & 1 deletion routes/blog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function PostCard(props: Post) {
</h2>
{props.publishedAt.toString() !== "Invalid Date" && (
<time class="text-gray-500">
{new Date(props.publishedAt).toLocaleDateString("en-US", {
{props.publishedAt.toLocaleDateString("en-US", {
dateStyle: "long",
})}
</time>
Expand Down
77 changes: 58 additions & 19 deletions utils/posts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
import { extract } from "std/front_matter/yaml.ts";
import { join } from "std/path/mod.ts";

/**
* This code is based on the
* {@link https://deno.com/blog/build-a-blog-with-fresh|How to Build a Blog with Fresh}
* blog post.
*/

export interface Post {
slug: string;
title: string;
Expand All @@ -10,32 +16,65 @@ export interface Post {
summary: string;
}

export async function getPosts(): Promise<Post[]> {
const files = Deno.readDir("./data/posts");
const promises = [];
for await (const file of files) {
const slug = file.name.replace(".md", "");
promises.push(getPost(slug));
}
const posts = await Promise.all(promises) as Post[];
posts.sort((a, b) => b.publishedAt.getTime() - a.publishedAt.getTime());
return posts;
}

/**
* Returns a {@linkcode Post} object of by reading and parsing a file with the
* given slug in the `./posts` folder. Returns `null` if the given file is
* not a readable or parsable file.
*
* @see {@link https://deno.land/api?s=Deno.readTextFile}
*
* @example
* ```ts
* import { getPost } from "@/utils/posts.ts";
*
* const post = await getPost("first-post")!;
*
* post?.title; // Returns "This is my first blog post!"
* post?.publishedAt; // Returns 2022-11-04T15:00:00.000Z
* post?.slug; // Returns "This is an excerpt of my first blog post."
* post?.content; // Returns '# Heading 1\n\nHello, world!\n\n```javascript\nconsole.log("Hello World");\n```\n'
* ```
*/
export async function getPost(slug: string): Promise<Post | null> {
try {
const text = await Deno.readTextFile(
join("./data/posts", `${slug}.md`),
);
const { attrs, body } = extract(text);
const text = await Deno.readTextFile(join("./posts", `${slug}.md`));
const { attrs, body } = extract<Post>(text);
return {
...attrs,
slug,
title: attrs.title as string,
publishedAt: new Date(attrs.published_at as Date),
content: body,
summary: attrs.summary as string || "",
};
} catch {
return null;
}
}

/**
* Returns an array of {@linkcode Post} objects by reading and parsing files
* in the `./posts` folder.
*
* @see {@link https://deno.land/api?s=Deno.readDir}
*
* @example
* ```ts
* import { getPosts } from "@/utils/posts.ts";
*
* const posts = await getPosts();
*
* posts[0].title; // Returns "This is my first blog post!"
* posts[0].publishedAt; // Returns 2022-11-04T15:00:00.000Z
* posts[0].slug; // Returns "This is an excerpt of my first blog post."
* posts[0].content; // Returns '# Heading 1\n\nHello, world!\n\n```javascript\nconsole.log("Hello World");\n```\n'
* ```
*/
export async function getPosts(): Promise<Post[]> {
const files = Deno.readDir("./posts");
const promises = [];
for await (const file of files) {
const slug = file.name.replace(".md", "");
promises.push(getPost(slug));
}
const posts = await Promise.all(promises) as Post[];
posts.sort((a, b) => b.publishedAt.getTime() - a.publishedAt.getTime());
return posts;
}
19 changes: 2 additions & 17 deletions utils/posts_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,10 @@ Deno.test("[blog] getPost()", async () => {
assertEquals(post.publishedAt, new Date("2022-11-04T15:00:00.000Z"));
assertEquals(post.summary, "This is an excerpt of my first blog post.");
assertEquals(post.title, "This is my first blog post!");
assertEquals(await getPost("third-post"), null);
});

Deno.test("[blog] getPost() with missing frontmatter attributes", async () => {
const post = await getPost("second-post");
assert(post);
assertEquals(post.publishedAt, new Date("2022-11-04T15:00:00.000Z"));
assertEquals(
post.summary,
"Lorem Ipsum is simply dummy text of the printing and typesetting industry.",
);
assertEquals(post.title, "Second post");
});

Deno.test("[blog] getPost() for non-existent post", async () => {
const post = await getPost("third-post");
assertEquals(post, null);
});

Deno.test("[blog] getPosts() from data directory", async () => {
Deno.test("[blog] getPosts()", async () => {
const posts = await getPosts();
assert(posts);
assertEquals(posts.length, 2);
Expand Down

0 comments on commit 9c5590f

Please sign in to comment.