-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontent-collections.ts
More file actions
126 lines (114 loc) · 3.68 KB
/
content-collections.ts
File metadata and controls
126 lines (114 loc) · 3.68 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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import { postCollectionSchema } from "@/lib/post/schema";
import { defineCollection, defineConfig } from "@content-collections/core";
import { compileMDX } from "@content-collections/mdx";
import GithubSlugger from "github-slugger";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import rehypePrettyCode, { type LineElement } from "rehype-pretty-code";
import rehypeSlug from "rehype-slug";
import remarkGfm from "remark-gfm";
const posts = defineCollection({
name: "posts",
directory: "content/posts",
include: "**/*.mdx",
schema: postCollectionSchema,
transform: async (document, context) => {
const mdx = await compileMDX(context, document, {
remarkPlugins: [remarkGfm],
rehypePlugins: [
rehypeSlug,
[
rehypeAutolinkHeadings,
{
behavior: "wrap",
properties: {
className: ["no-underline"],
},
},
],
[
rehypePrettyCode,
{
theme: "night-owl",
keepBackground: true,
onVisitLine(node: LineElement) {
if (node.children.length === 0) {
node.children = [{ type: "text", value: " " }];
}
const firstChild = node.children[0];
if (firstChild) {
let textValue = "";
if (firstChild.type === "text") {
textValue = firstChild.value;
} else if (
firstChild.type === "element" &&
firstChild.children?.[0]?.type === "text"
) {
textValue = firstChild.children[0].value;
}
if (textValue.startsWith("+")) {
node.properties["data-line"] = "add";
} else if (textValue.startsWith("-")) {
node.properties["data-line"] = "remove";
}
}
},
},
],
],
});
const slugger = new GithubSlugger();
const toc = Array.from(
document.content.matchAll(/^(#{2,6})\s+(.+)$/gm)
).map((match) => {
const level = match[1].length;
const raw = match[2].trim();
const title = raw
.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
.replace(/`([^`]+)`/g, "$1")
.replace(/\*\*([^*]+)\*\*/g, "$1")
.replace(/__([^_]+)__/g, "$1")
.replace(/\*([^*]+)\*/g, "$1")
.replace(/_([^_]+)_/g, "$1");
const slug = slugger.slug(title);
return { level, title, slug };
});
const type =
document._meta.directory === "archived"
? ("archived" as const)
: ("active" as const);
const { content, ...rest } = document;
const allDocs = (await context.collection.documents())
.filter((d) =>
type === "archived"
? d._meta.directory === "archived"
: d._meta.directory !== "archived",
)
.sort(
(a, b) =>
new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime(),
);
const idx = allDocs.findIndex(
(d) => d._meta.filePath === document._meta.filePath,
);
const pick = (d: (typeof allDocs)[number]) => ({
title: d.title,
slug: d._meta.fileName.replace(/\.mdx?$/, ""),
description: d.description,
publishedAt: d.publishedAt,
category: d.category,
type,
});
return {
...rest,
slug: document._meta.fileName.replace(/\.mdx?$/, ""),
type,
mdx,
toc,
prev: idx > 0 ? pick(allDocs[idx - 1]) : null,
next: idx < allDocs.length - 1 ? pick(allDocs[idx + 1]) : null,
};
},
});
export default defineConfig({
content: [posts],
});