Skip to content

Commit

Permalink
Code refactor related to posts logic
Browse files Browse the repository at this point in the history
- Rename variables
- Reuse functionality

Signed-off-by: Randy <randymoralesg@gmail.com>
  • Loading branch information
randymorales committed Sep 10, 2024
1 parent 75d51c2 commit cd5fb63
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 80 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@

# production
/build
/public/rss-en.xml
/public/rss-es.xml
/public/rss.xml

# misc
.DS_Store
Expand Down
2 changes: 1 addition & 1 deletion cache/data.js

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

2 changes: 1 addition & 1 deletion components/BlogPostsSection.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PostCard from '@/components/PostCard'

export default function BlogPostsSection({ posts, title }) {
return (
<section className='py-8 flex flex-col items-center justify-center'>
<section className='py-8 flex flex-col justify-center'>
<div>
<h2 className='text-white text-2xl font-bold mb-6'>{title}</h2>

Expand Down
4 changes: 2 additions & 2 deletions lib/cache.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { readdirSync, mkdirSync, writeFile } from 'fs'

import { getSortedPostsData } from './posts'
import { getAllPostsMetadata } from './posts'

function getPostsAsJSON() {
const posts = getSortedPostsData()
const posts = getAllPostsMetadata()

return `export const posts = ${JSON.stringify(posts)}`
}
Expand Down
91 changes: 47 additions & 44 deletions lib/posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,17 @@ import matter from 'gray-matter'

const postsDirectory = path.join(process.cwd(), 'posts')

// Get directory names as posts IDs under /posts folder.
const postIds = fs.readdirSync(postsDirectory)

// Collects information from posts files and sorts them by date.
export function getSortedPostsData() {
// Get directory names as posts IDs under /posts folder.
const postIDs = fs.readdirSync(postsDirectory)

const allPostsData = postIDs
// Get markdown file names as posts IDs under /posts folder without the '.md' extension.
const postIDs = fs
.readdirSync(postsDirectory)
.map(file => file.replace(/\.md$/, ''))

// Collects the metadata from all posts files and sorts them by date.
export function getAllPostsMetadata() {
const allPostsMetadata = postIDs
.map(id => {
// Get file.
const filePath = getFilePath(id)
if (!fs.existsSync(filePath)) {
return
}

// Read markdown file as string.
const postContent = fs.readFileSync(filePath, 'utf8')

// Parse postContent.
const matterResult = matter(postContent)
// Parse post content to obtain the metadata.
const matterResult = getMatterResult(id)

return {
id,
Expand All @@ -34,7 +24,7 @@ export function getSortedPostsData() {
.filter(post => post)

// Sort posts by date.
return allPostsData.sort((a, b) => {
return allPostsMetadata.sort((a, b) => {
if (a.date < b.date) {
return 1
} else {
Expand All @@ -44,35 +34,34 @@ export function getSortedPostsData() {
}

// Return a list of post IDs.
export function getAllPostIds() {
export function getAllPostIDs() {
let paths = []

for (let id of postIds) {
for (let id of postIDs) {
paths.push({ params: { id } })
}

return paths
}

// Return the markdown content of a specific post ID.
// Return the markdown content and metadata of a specific post.
export async function getPostData(id) {
const filePath = getFilePath(id)
const fileContents = fs.readFileSync(filePath, 'utf8')
const fileContents = getMDFileContent(filePath)
const readTime = calculateReadTime(fileContents)

// Use gray-matter to parse the post metadata section.
// Parse the post metadata and content.
const { data, content } = matter(fileContents)

// Use remark to convert markdown into HTML string.
// Convert markdown into HTML string.
const remark = (await import('remark')).remark
const html = (await import('remark-html')).default
const processedContent = remark().use(html).processSync(content).toString()

const readTime = calculateReadTime(fileContents)

// Combine the data with the id and contentHtml
// Return the id, content, readTime and metadata
return {
id,
contentHtml: processedContent,
contentMD: processedContent,
readTime,
...data,
}
Expand All @@ -82,15 +71,11 @@ export async function getPostData(id) {
export function getAllPostTags() {
let paths = []

for (let id of postIds) {
let filePath = getFilePath(id)

// Read markdown file as string.
const postContent = fs.readFileSync(filePath, 'utf8')

// Use gray-matter to parse the post metadata section.
const matterResult = matter(postContent)
for (let id of postIDs) {
// Parse post content to obtain the metadata.
const matterResult = getMatterResult(id)

// Obtain tags from post metadata.
let tags = matterResult.data.tags.split(',')
for (let tag of tags) {
paths.push({ params: { tag } })
Expand All @@ -101,19 +86,37 @@ export function getAllPostTags() {
}

// Return the list of posts given a specific tag.
export async function getPostsByTag(tag) {
const allPostsData = getSortedPostsData()
return allPostsData.filter(post => post.tags && post.tags.includes(tag))
export async function getPostsMetadataByTag(tag) {
const allPostsMetadata = getAllPostsMetadata()
return allPostsMetadata.filter(post => post.tags && post.tags.includes(tag))
}

// Returns the file path like /posts/id
// Returns the file path like /posts/id.md
function getFilePath(id) {
return path.join(postsDirectory, id)
}

// Return the estimated post read time.
// Returns the markdown content from a given file.
function getMDFileContent(filePath) {
return fs.readFileSync(filePath + '.md', 'utf8')
}

// Returns the estimated post read time.
function calculateReadTime(content) {
const wordsPerMinute = 200
const wordCount = content.split(/\s+/).length
return Math.ceil(wordCount / wordsPerMinute)
}

// Returns the matter result data obtained from parsing
// a markdown file (metadata and markdown content).
function getMatterResult(postID) {
// Get file path.
const filePath = getFilePath(postID)

// Read markdown file as string.
const postContent = getMDFileContent(filePath)

// Parse the post metadata section.
return matter(postContent)
}
2 changes: 1 addition & 1 deletion pages/_document.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default class MyDocument extends Document {
rel='alternate'
type='application/rss+xml'
title='RSS feed for blog posts'
href='https://randymorales.dev/rss-en.xml'
href='https://randymorales.dev/rss.xml'
/>
<link rel='preconnect' href='https://fonts.googleapis.com' />
<link rel='preconnect' href='https://fonts.gstatic.com' />
Expand Down
4 changes: 2 additions & 2 deletions pages/api/search.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { getSortedPostsData } from '@/lib/posts'
import { getAllPostsMetadata } from '@/lib/posts'

const posts =
process.env.NODE_ENV === 'production'
? require('../../cache/data').posts
: getSortedPostsData()
: getAllPostsMetadata()

export default (req, res) => {
const results = req.query.q
Expand Down
6 changes: 3 additions & 3 deletions pages/blog/[id].js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import useSWR from 'swr'
import { serialize } from 'next-mdx-remote/serialize'

import { PostsDirectory, SiteBaseURL } from '@/lib/constants'
import { getAllPostIds, getPostData } from '@/lib/posts'
import { getAllPostIDs, getPostData } from '@/lib/posts'
import Layout from '@/components/Layout'
import BlogPost from '@/components/BlogPost'

Expand Down Expand Up @@ -35,7 +35,7 @@ export default function Post({ postData, source }) {

export async function getStaticPaths() {
// Return the list of posts.
const paths = getAllPostIds()
const paths = getAllPostIDs()
return {
paths,
fallback: false,
Expand All @@ -47,7 +47,7 @@ export async function getStaticProps({ params }) {
const postData = await getPostData(params.id)

// Serialize the content for MDXRemote.
const mdxSource = await serialize(postData.contentHtml)
const mdxSource = await serialize(postData.contentMD)

return {
props: {
Expand Down
20 changes: 10 additions & 10 deletions pages/blog/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { useCallback, useRef, useState } from 'react'
import Link from 'next/link'

import { PostsDirectory, SiteBaseURL } from '@/lib/constants'
import { getSortedPostsData } from '@/lib/posts'
import { getAllPostsMetadata } from '@/lib/posts'
import BlogPostsSection from '@/components/BlogPostsSection'
import Layout from '@/components/Layout'
import styles from '@/styles/blog.module.css'

export default function BlogIndex({ allPostsData }) {
export default function BlogIndex({ allPostsMetadata }) {
const pageInfo = {
url: SiteBaseURL + PostsDirectory,
title: 'Blog',
Expand Down Expand Up @@ -66,7 +66,7 @@ export default function BlogIndex({ allPostsData }) {

{/* Tags */}
<div>
{getAllTags(allPostsData).map(tag => (
{getAllTags(allPostsMetadata).map(tag => (
<Link
href={`/tags/${tag}/`}
key={tag}
Expand All @@ -83,7 +83,7 @@ export default function BlogIndex({ allPostsData }) {
) : (
<BlogPostsSection
title='Latest Posts'
posts={getPostsSource(searchInputResult, allPostsData)}
posts={getPostsSource(searchInputResult, allPostsMetadata)}
/>
)}
</div>
Expand All @@ -92,20 +92,20 @@ export default function BlogIndex({ allPostsData }) {
}

export const getStaticProps = async () => {
let allPostsData = getSortedPostsData()
let allPostsMetadata = getAllPostsMetadata()

return {
props: {
allPostsData,
allPostsMetadata,
},
}
}

// Return the list of all tags.
function getAllTags(allPostsData) {
function getAllTags(allPostsMetadata) {
const tagsList = []

allPostsData.map(({ tags }) =>
allPostsMetadata.map(({ tags }) =>
tags
.split(',')
.map(tag => tagsList.indexOf(tag) === -1 && tagsList.push(tag)),
Expand All @@ -115,6 +115,6 @@ function getAllTags(allPostsData) {
}

// Return the list of posts according to the input searchInputResult.
function getPostsSource(searchInputResult, allPostsData) {
return searchInputResult.length == 0 ? allPostsData : searchInputResult
function getPostsSource(searchInputResult, allPostsMetadata) {
return searchInputResult.length == 0 ? allPostsMetadata : searchInputResult
}
12 changes: 6 additions & 6 deletions pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import fs from 'fs'

import { SiteBaseURL } from '@/lib/constants'
import generateRSS from '@/lib/rss'
import { getSortedPostsData } from '@/lib/posts'
import { getAllPostsMetadata } from '@/lib/posts'
import BlogPostsSection from '@/components/BlogPostsSection'
import Intro from '@/components/Intro'
import Layout from '@/components/Layout'

export default function Home({ allLocalePostsData }) {
export default function Home({ allPostsMetadata }) {
const pageInfo = {
url: SiteBaseURL,
title: 'Home',
Expand All @@ -16,7 +16,7 @@ export default function Home({ allLocalePostsData }) {
}

// Get the last 3 posts
const lastBlogEntries = allLocalePostsData.slice(0, 3)
const lastBlogEntries = allPostsMetadata.slice(0, 3)

return (
<Layout pageInfo={pageInfo} large={true}>
Expand All @@ -30,15 +30,15 @@ export default function Home({ allLocalePostsData }) {

export const getStaticProps = async () => {
// Get posts.
let allLocalePostsData = getSortedPostsData()
let allPostsMetadata = getAllPostsMetadata()

// Write RSS feed files.
const rss = generateRSS(allLocalePostsData)
const rss = generateRSS(allPostsMetadata)
fs.writeFileSync(`./public/rss.xml`, rss)

return {
props: {
allLocalePostsData,
allPostsMetadata,
},
}
}
4 changes: 2 additions & 2 deletions pages/tags/[tag].js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PostsDirectory, SiteBaseURL } from '@/lib/constants'
import { getAllPostTags, getPostsByTag } from '@/lib/posts'
import { getAllPostTags, getPostsMetadataByTag } from '@/lib/posts'
import Layout from '@/components/Layout'
import PostCard from '@/components/PostCard'
import blogStyles from '@/styles/blog.module.css'
Expand Down Expand Up @@ -56,7 +56,7 @@ export async function getStaticPaths() {
export async function getStaticProps({ params }) {
// Return a list of posts by tag.
const tag = params.tag
const posts = await getPostsByTag(tag)
const posts = await getPostsMetadataByTag(tag)
return {
props: {
posts,
Expand Down
12 changes: 6 additions & 6 deletions public/rss.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,25 @@
<atom:link href="https://randymorales.dev/rss.xml" rel="self" type="application/rss+xml"/>

<item>
<guid>https://randymorales.dev/blog/show-page-views-with-google-analytics-nextjs.md</guid>
<guid>https://randymorales.dev/blog/show-page-views-with-google-analytics-nextjs</guid>
<title>Show Page Views in Next.js with Google Analytics</title>
<link>https://randymorales.dev/blog/show-page-views-with-google-analytics-nextjs.md</link>
<link>https://randymorales.dev/blog/show-page-views-with-google-analytics-nextjs</link>
<description>Configure Google Analytics for page views count</description>
<pubDate>Sun, 15 Aug 2021 00:00:00 GMT</pubDate>
</item>

<item>
<guid>https://randymorales.dev/blog/adding-code-highlighting-to-nextjs.md</guid>
<guid>https://randymorales.dev/blog/adding-code-highlighting-to-nextjs</guid>
<title>Adding Code Highlighting to a NextJS Blog with Prism</title>
<link>https://randymorales.dev/blog/adding-code-highlighting-to-nextjs.md</link>
<link>https://randymorales.dev/blog/adding-code-highlighting-to-nextjs</link>
<description>Setup Code Highlighting in a NextJS blog with Prism</description>
<pubDate>Mon, 05 Jul 2021 00:00:00 GMT</pubDate>
</item>

<item>
<guid>https://randymorales.dev/blog/adding-comments-to-my-blog.md</guid>
<guid>https://randymorales.dev/blog/adding-comments-to-my-blog</guid>
<title>Adding Comments to a NextJS Blog</title>
<link>https://randymorales.dev/blog/adding-comments-to-my-blog.md</link>
<link>https://randymorales.dev/blog/adding-comments-to-my-blog</link>
<description>Setup Utterances in a NextJS blog</description>
<pubDate>Tue, 22 Dec 2020 00:00:00 GMT</pubDate>
</item>
Expand Down

0 comments on commit cd5fb63

Please sign in to comment.