1
1
mirror of https://github.com/theoludwig/theoludwig.git synced 2024-11-14 16:13:14 +01:00
.profile/utils/blog.ts

102 lines
2.6 KiB
TypeScript
Raw Normal View History

2022-07-01 23:12:47 +02:00
import fs from 'node:fs'
import path from 'node:path'
2021-11-08 15:10:26 +01:00
import type { MDXRemoteSerializeResult } from 'next-mdx-remote'
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'
import remarkMath from 'remark-math'
import rehypeKatex from 'rehype-katex'
2021-11-08 15:10:26 +01:00
import matter from 'gray-matter'
import { getHighlighter } from 'shiki'
2021-11-08 15:10:26 +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[]> => {
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) => {
2022-08-27 02:30:55 +02:00
const [slug, extension] = postFilename.split('.')
2023-01-10 23:56:46 +01:00
if (slug == null || extension == null) {
throw new Error('Invalid postFilename.')
}
2022-08-27 02:30:55 +02:00
const blogPostPath = path.join(POSTS_PATH, `${slug}.${extension}`)
2021-11-08 15:10:26 +01:00
const blogPostContent = await fs.promises.readFile(blogPostPath, {
encoding: 'utf8'
})
const { data, content } = matter(blogPostContent) as unknown as {
data: FrontMatter
content: string
}
2021-11-08 15:10:26 +01:00
const date = new Date(data.publishedOn)
return {
slug,
content,
frontmatter: data,
time: date.getTime()
}
})
)
const postsWithTimeSorted = postsWithTime
2022-09-04 20:40:58 +02:00
.filter((post) => {
return post.frontmatter.isPublished
})
.sort((a, b) => {
return b.time - a.time
})
2021-11-08 15:10:26 +01:00
return postsWithTimeSorted
}
export const getPostBySlug = async (
slug?: string | string[]
): Promise<Post | undefined> => {
const posts = await getPosts()
2022-09-04 20:40:58 +02:00
const post = posts.find((post) => {
return post.slug === slug
})
2021-11-08 15:10:26 +01:00
if (post == null) {
return undefined
}
const highlighter = await getHighlighter({
theme: 'dark-plus'
})
2021-11-08 15:10:26 +01:00
const source = await serialize(post.content, {
mdxOptions: {
remarkPlugins: [
remarkGfm,
[remarkSyntaxHighlightingPlugin, { highlighter }],
remarkMath
],
rehypePlugins: [
rehypeSlug,
[rehypeRaw, { passThrough: nodeTypes }],
rehypeKatex
]
2021-11-08 15:10:26 +01:00
}
})
return { ...post, source }
}