import fs from 'fs' import path from 'path' import matter from 'gray-matter' import remarkGfm from 'remark-gfm' import rehypeHighlight from 'rehype-highlight' import rehypeSlug from 'rehype-slug' import remarkToc from 'remark-toc' import nix from 'highlight.js/lib/languages/nix' const fsPromises = fs.promises const postsDirectory = path.join(process.cwd(), 'posts') export const mdxOptions = { remarkPlugins: [ remarkGfm, [remarkToc, {tight: true}], ], rehypePlugins: [ [rehypeHighlight, {languages: {nix}}], rehypeSlug, ], }; 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)) }