summary refs log tree commit diff
path: root/utils/post.ts
blob: b2dd328f2681c9d764903bc916028f8010c53420 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import { promises as fs } from 'fs'
import path from 'path'

import frontmatter from 'front-matter'

export interface Post {
  slug: string,
  date: Date,
  title: string,
  subtitle?: string,
  author: string,
  body: string
}

const POST_FILE_PATTERN = /^(?<date>[0-9]{4}-[0-9]{2}-[0-9]{2}(-[0-9]{1,2})?)_(?<slug>[^\.]+)\.md$/

export async function getPostSlugs(): Promise<string[]> {
  const postsDir = path.join(process.cwd(), 'posts')
  const postPaths = await fs.readdir(postsDir)
  return postPaths.map(getSlugFromFilePath).filter(slug => slug !== null)
}

export function getSlugFromFilePath(postPath: string): string | null {
  const regexResult = POST_FILE_PATTERN.exec(postPath)
  if (!regexResult) return null
  return regexResult.groups.slug
}

export async function loadSinglePage(slug: string): Promise<Post | null> {
  const postsDir = path.join(process.cwd(), 'posts')
  const postPaths = await fs.readdir(postsDir)
  const postMatch: RegExpExecArray | null = postPaths
    .map((postFile: string) => POST_FILE_PATTERN.exec(postFile))
    .filter((regexResult: RegExpExecArray | null) => regexResult !== null)
    .find((regexResult: RegExpExecArray) => regexResult.groups.slug === slug)

  if (!postMatch) return null;

  const fileName = `${postMatch.groups.date}_${postMatch.groups.slug}.md`
  const fileContents = (await fs.readFile(path.join(process.cwd(), 'posts', fileName))).toString('utf8')
  const { attributes, body } = frontmatter(fileContents)

  type Attributes = { [key: string]: string }
  const data: Attributes = attributes as Attributes

  if (!data.title) return null;

  return {
    slug: postMatch.groups.slug,
    date: new Date(postMatch.groups.date),
    title: data.title,
    subtitle: data.subtitle,
    author: data.author,
    body
  }
}