-
Notifications
You must be signed in to change notification settings - Fork 1
/
post-loader.js
85 lines (74 loc) · 2.13 KB
/
post-loader.js
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import coreFs from 'fs'
import path from 'path'
import { format } from 'date-fns'
import markdownIt from 'markdown-it'
import hljs from 'highlight.js'
const markdown = markdownIt({
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value
} catch { }
return ''
}
}
})
const fs = coreFs.promises
const metaSeparator = '---META---'
class PostLoader {
constructor() {
this.cachedPosts = {
all: [],
byName: {}
}
this.isLoaded = false
}
async load() {
const postsDir = await fs.readdir('assets/posts')
for (const fileName of postsDir) {
const postName = path.basename(fileName, '.md')
const post = {
name: postName,
...await this.readPost(fileName)
}
this.cachedPosts.all.push(post)
this.cachedPosts.byName[postName] = post
}
this.isLoaded = true
}
async getAll() {
if (this.isLoaded) {
return this.cachedPosts.all
}
await this.load()
return this.cachedPosts.all
}
async getMappedByName() {
if (this.isLoaded) {
return this.cachedPosts.byName
}
await this.load()
return this.cachedPosts.byName
}
async readPost(fileName) {
const post = await fs.readFile(`assets/posts/${fileName}`)
const [meta, contents] = post.toString().split(`${metaSeparator}\n`)
const parsedMeta = JSON.parse(meta)
return {
...parsedMeta,
...this.prettyDates(parsedMeta),
contents: markdown.render(contents.trim())
}
}
prettyDates(meta) {
const formatDate = date => format(new Date(date), 'MMM do, yyyy')
const formatted = {
createdAtPretty: formatDate(meta.createdAt)
}
if (meta.updatedAt) {
formatted.updatedAtPretty = formatDate(meta.updatedAt)
}
return formatted
}
}
export const postLoader = new PostLoader()