2022-02-23 09:06:12 +01:00
|
|
|
import fs from 'fs'
|
|
|
|
import path from 'path'
|
2021-11-08 15:10:26 +01:00
|
|
|
|
|
|
|
import type { MDXRemoteSerializeResult } from 'next-mdx-remote'
|
2022-02-23 00:38:50 +01:00
|
|
|
import { nodeTypes } from '@mdx-js/mdx'
|
|
|
|
import rehypeRaw from 'rehype-raw'
|
2021-11-08 15:10:26 +01:00
|
|
|
import { serialize } from 'next-mdx-remote/serialize'
|
|
|
|
import remarkGfm from 'remark-gfm'
|
2021-11-09 15:14:31 +01:00
|
|
|
import rehypeSlug from 'rehype-slug'
|
2021-11-08 15:10:26 +01:00
|
|
|
import matter from 'gray-matter'
|
2022-02-23 00:38:50 +01:00
|
|
|
import { getHighlighter } from 'shiki'
|
2021-11-08 15:10:26 +01:00
|
|
|
|
2022-02-23 00:38:50 +01:00
|
|
|
import { remarkSyntaxHighlightingPlugin } from './remarkSyntaxHighlightingPlugin'
|
|
|
|
|
|
|
|
export const POSTS_PATH = path.join(process.cwd(), 'posts')
|
2021-11-08 15:10:26 +01:00
|
|
|
|
|
|
|
export type MDXSource = MDXRemoteSerializeResult<Record<string, unknown>>
|
|
|
|
|
|
|
|
export interface FrontMatter {
|
|
|
|
title: string
|
|
|
|
description: string
|
|
|
|
isPublished: boolean
|
|
|
|
publishedOn: string
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface PostMetadata {
|
|
|
|
frontmatter: FrontMatter
|
|
|
|
slug: string
|
|
|
|
content: string
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface Post extends PostMetadata {
|
|
|
|
source: MDXSource
|
|
|
|
}
|
|
|
|
|
|
|
|
export const getPosts = async (): Promise<PostMetadata[]> => {
|
2022-02-23 00:38:50 +01:00
|
|
|
const posts = await fs.promises.readdir(POSTS_PATH)
|
2021-11-08 15:10:26 +01:00
|
|
|
const postsWithTime = await Promise.all(
|
|
|
|
posts.map(async (postFilename) => {
|
|
|
|
const [slug] = postFilename.split('.')
|
2022-02-23 00:38:50 +01:00
|
|
|
const blogPostPath = path.join(POSTS_PATH, `${slug}.mdx`)
|
2021-11-08 15:10:26 +01:00
|
|
|
const blogPostContent = await fs.promises.readFile(blogPostPath, {
|
|
|
|
encoding: 'utf8'
|
|
|
|
})
|
|
|
|
const { data, content } = matter(blogPostContent) as any
|
|
|
|
const date = new Date(data.publishedOn)
|
|
|
|
return {
|
|
|
|
slug,
|
|
|
|
content,
|
|
|
|
frontmatter: data,
|
|
|
|
time: date.getTime()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
)
|
|
|
|
const postsWithTimeSorted = postsWithTime
|
|
|
|
.filter((post) => post.frontmatter.isPublished)
|
|
|
|
.sort((a, b) => b.time - a.time)
|
|
|
|
return postsWithTimeSorted
|
|
|
|
}
|
|
|
|
|
|
|
|
export const getPostBySlug = async (
|
|
|
|
slug?: string | string[]
|
|
|
|
): Promise<Post | undefined> => {
|
|
|
|
const posts = await getPosts()
|
|
|
|
const post = posts.find((post) => post.slug === slug)
|
|
|
|
if (post == null) {
|
|
|
|
return undefined
|
|
|
|
}
|
2022-02-23 00:38:50 +01:00
|
|
|
const highlighter = await getHighlighter({
|
|
|
|
theme: 'dark-plus'
|
|
|
|
})
|
2021-11-08 15:10:26 +01:00
|
|
|
const source = await serialize(post.content, {
|
|
|
|
mdxOptions: {
|
2022-02-23 00:38:50 +01:00
|
|
|
remarkPlugins: [
|
|
|
|
remarkGfm as any,
|
|
|
|
[remarkSyntaxHighlightingPlugin, { highlighter }]
|
|
|
|
],
|
|
|
|
rehypePlugins: [
|
|
|
|
rehypeSlug as any,
|
|
|
|
[rehypeRaw, { passThrough: nodeTypes }]
|
|
|
|
]
|
2021-11-08 15:10:26 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
return { ...post, source }
|
|
|
|
}
|