depot/web/lukegbcom/lib/posts.js

74 lines
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')
async function markdownToHtml(content) {
return unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeHighlight)
.use(rehypeStringify)
.process(content)
}
export async function getPostSlugs() {
return (await fsPromises.readdir(postsDirectory)).filter(fileName => fileName.match(/\.md$/)).map(fileName => {
return fileName.replace(/\.md$/, '')
})
}
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 })
const processedContent = await markdownToHtml(matterResult.content)
const processedExcerpt = await markdownToHtml(matterResult.excerpt)
return {
...matterResult.data,
slug,
date: matterResult.data.date.toISOString().substring(0, 10),
excerptHtml: processedExcerpt.toString(),
contentHtml: processedContent.toString(),
sortKey: matterResult.data.date,
}
}
export async function getPostBySlug(slug) {
const data = await _getPostBySlug(slug)
delete data.sortKey
return data
}
export async function getSortedPostsData() {
const allPostsData = await Promise.all((await getPostSlugs()).map(_getPostBySlug))
return 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.contentHtml
delete x.sortKey
return x
})
}