blog.ts

1import fs from 'fs'
2import path from 'path'
3import matter from 'gray-matter'
4
5export type Metadata = {
6	title: string
7	publishedAt: string
8	summary: string
9	image?: string
10	imageCaption?: string
11}
12
13export type BlogPost = {
14	metadata: Metadata
15	slug: string
16	content: string
17}
18
19function parseFrontmatter(fileContent: string): {
20	metadata: Metadata
21	content: string
22} {
23	const { data, content } = matter(fileContent)
24	return {
25		metadata: {
26			title: data.title || '',
27			publishedAt: data.publishedAt || '',
28			summary: data.summary || '',
29			image: data.image,
30			imageCaption: data.imageCaption,
31		},
32		content: content.trim(),
33	}
34}
35
36function getMDXFiles(dir: string): string[] {
37	return fs
38		.readdirSync(dir)
39		.filter(
40			(file) => path.extname(file) === '.mdx' || path.extname(file) === '.md',
41		)
42}
43
44function readMDXFile(filePath: string) {
45	const rawContent = fs.readFileSync(filePath, 'utf-8')
46	return parseFrontmatter(rawContent)
47}
48
49function getMDXData(dir: string) {
50	const mdxFiles = getMDXFiles(dir)
51	return mdxFiles.map((file) => {
52		const { metadata, content } = readMDXFile(path.join(dir, file))
53		const slug = path.basename(file, path.extname(file))
54
55		return {
56			metadata,
57			slug,
58			content,
59		}
60	})
61}
62
63export function getBlogPosts(amount = 5, page = 1) {
64	const posts = getMDXData(path.join(process.cwd(), 'content', 'blog'))
65
66	const start = (page - 1) * amount
67	const end = start + amount
68
69	return posts.reverse().slice(start, end)
70}
71
72export function getAllBlogPosts() {
73	return getMDXData(path.join(process.cwd(), 'content', 'blog'))
74}
75
76export function getBlogPost(slug: string): BlogPost | undefined {
77	const posts = getMDXData(path.join(process.cwd(), 'content', 'blog'))
78	return posts.find((post) => post.slug === slug)
79}
80
81export function generateBlogTimetoRead(content: string) {
82	const wordsPerMinute = 200
83	const words = content.split(/\s/g).length
84	const minutes = words / wordsPerMinute
85	const readTime = Math.ceil(minutes)
86	return readTime
87}
88
89export function getBlogPages(limit: number) {
90	const posts = getMDXData(path.join(process.cwd(), 'content', 'blog'))
91	return Math.ceil(posts.length / limit)
92}
93