-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathblog.ts
More file actions
91 lines (75 loc) · 2.75 KB
/
Copy pathblog.ts
File metadata and controls
91 lines (75 loc) · 2.75 KB
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
86
87
88
89
90
91
import rehypePrettyCode from "rehype-pretty-code";
import rehypeStringify from "rehype-stringify";
import remarkRehype from "remark-rehype";
import remarkParse from "remark-parse";
import { unified } from "unified";
import matter from "gray-matter";
import { createHighlighter } from "shiki";
import { createJavaScriptRegexEngine } from "shiki/engine/javascript";
// Bundle posts at build time (Workers-safe, no fs).
const rawPosts = import.meta.glob("../../posts/*.{md,mdx}", {
eager: true,
query: "?raw",
import: "default",
}) as Record<string, string>;
function findRawBySlug(slug: string): string | null {
for (const [filePath, raw] of Object.entries(rawPosts)) {
if (filePath.endsWith(`/${slug}.mdx`) || filePath.endsWith(`/${slug}.md`)) {
return raw;
}
}
return null;
}
const metadataCache = new Map<string, Record<string, any>>();
const postCache = new Map<string, Promise<{ source: string; metadata: Record<string, any>; slug: string }>>();
let highlighterPromise: ReturnType<typeof createHighlighter> | null = null;
function getPostMetadata(slug: string) {
const cached = metadataCache.get(slug);
if (cached) return cached;
const raw = findRawBySlug(slug);
if (!raw) throw new Error(`Post not found: ${slug}`);
const { data: metadata } = matter(raw);
metadataCache.set(slug, metadata as Record<string, any>);
return metadata as Record<string, any>;
}
export async function getPost(slug: string) {
const cached = postCache.get(slug);
if (cached) return cached;
const postPromise = (async () => {
const raw = findRawBySlug(slug);
if (!raw) throw new Error(`Post not found: ${slug}`);
const { content: rawContent, data: metadata } = matter(raw);
const content = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypePrettyCode, {
// https://rehype-pretty.pages.dev/#usage
keepBackground: false,
theme: {
light: "min-light",
dark: "min-dark",
},
// IMPORTANT: avoid Shiki's default WASM Oniguruma engine on Cloudflare Workers
getHighlighter: (options) => {
if (!highlighterPromise) {
highlighterPromise = createHighlighter({
...options,
engine: createJavaScriptRegexEngine({ forgiving: true }),
});
}
return highlighterPromise;
},
})
.use(rehypeStringify)
.process(rawContent);
return { source: content.toString(), metadata, slug };
})();
postCache.set(slug, postPromise);
return postPromise;
}
export function getBlogPosts() {
const slugs = Object.keys(rawPosts).map((filePath) =>
filePath.split("/").pop()!.replace(/\.mdx?$/, ""),
);
return slugs.map((slug) => ({ metadata: getPostMetadata(slug), slug }));
}