depot/web/lukegbcom/lib/posts.js

82 lines
2.2 KiB
JavaScript

import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkGfm from 'remark-gfm'
import remarkRehype from 'remark-rehype'
import rehypeHighlight from 'rehype-highlight'
import rehypeStringify from 'rehype-stringify'
const fsPromises = fs.promises
const postsDirectory = path.join(process.cwd(), 'posts')
export const mdxOptions = {
remarkPlugins: [remarkGfm],
rehypePlugins: [rehypeHighlight],
};
export async function getPostSlugs() {
return (await fsPromises.readdir(postsDirectory)).filter(fileName => fileName.match(/\.md$/)).map(fileName => {
return fileName.replace(/\.md$/, '')
})
}
function mdxify(serialize) {
return async function mdxifyInner(post) {
if (post.excerptRaw) {
post.excerptMdx = await serialize(post.excerptRaw, { mdxOptions })
delete post.excerptRaw
}
if (post.contentRaw) {
post.contentMdx = await serialize(post.contentRaw, { mdxOptions })
delete post.contentRaw
}
return post
}
}
export async function _getPostBySlug(slug) {
const fileName = `${slug}.md`
const fullPath = path.join(postsDirectory, fileName)
const fileContents = await fsPromises.readFile(fullPath, 'utf8')
const matterResult = matter(fileContents, { excerpt: true })
return {
...matterResult.data,
slug,
date: matterResult.data.date.toISOString().substring(0, 10),
excerptRaw: matterResult.excerpt,
contentRaw: matterResult.content,
sortKey: matterResult.data.date,
}
}
export async function getPostBySlug(slug, serialize) {
const data = await _getPostBySlug(slug)
delete data.sortKey
delete data.excerptRaw
return mdxify(serialize)(data)
}
export async function getSortedPostsData(serialize) {
const mdxifyPost = mdxify(serialize)
const allPostsData = await Promise.all((await getPostSlugs()).map(_getPostBySlug))
return Promise.all(allPostsData.sort(({ sortKey: a }, { sortKey: b }) => {
[a, b] = [Date.parse(a), Date.parse(b)]
if (a < b) {
return 1
} else if (a > b) {
return -1
} else {
return 0
}
}).map((x) => {
delete x.sortKey
delete x.contentRaw
return x
}).map(mdxifyPost))
}