Files
wr.do/contentlayer.config.ts
T
2024-07-26 22:08:57 +08:00

174 lines
3.8 KiB
TypeScript

import {
ComputedFields,
defineDocumentType,
makeSource,
} from "contentlayer2/source-files";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import rehypePrettyCode from "rehype-pretty-code";
import rehypeSlug from "rehype-slug";
import remarkGfm from "remark-gfm";
import { visit } from "unist-util-visit";
const defaultComputedFields: ComputedFields = {
slug: {
type: "string",
resolve: (doc) => `/${doc._raw.flattenedPath}`,
},
slugAsParams: {
type: "string",
resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/"),
},
images: {
type: "list",
resolve: (doc) => {
return (
doc.body.raw.match(/(?<=<Image[^>]*\bsrc=")[^"]+(?="[^>]*\/>)/g) || []
);
},
},
};
export const Doc = defineDocumentType(() => ({
name: "Doc",
filePathPattern: `docs/**/*.mdx`,
contentType: "mdx",
fields: {
title: {
type: "string",
required: true,
},
description: {
type: "string",
},
published: {
type: "boolean",
default: true,
},
},
computedFields: defaultComputedFields,
}));
export const Post = defineDocumentType(() => ({
name: "Post",
filePathPattern: `blog/**/*.mdx`,
contentType: "mdx",
fields: {
title: {
type: "string",
required: true,
},
description: {
type: "string",
},
date: {
type: "date",
required: true,
},
published: {
type: "boolean",
default: true,
},
image: {
type: "string",
required: true,
},
authors: {
type: "list",
of: { type: "string" },
required: true,
},
categories: {
type: "list",
of: {
type: "enum",
options: ["news", "education"],
default: "news",
},
required: true,
},
related: {
type: "list",
of: {
type: "string",
},
},
},
computedFields: defaultComputedFields,
}));
export const Page = defineDocumentType(() => ({
name: "Page",
filePathPattern: `pages/**/*.mdx`,
contentType: "mdx",
fields: {
title: {
type: "string",
required: true,
},
description: {
type: "string",
},
},
computedFields: defaultComputedFields,
}));
export default makeSource({
contentDirPath: "./content",
documentTypes: [Page, Doc, Post],
mdx: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
rehypeSlug,
() => (tree) => {
visit(tree, (node) => {
if (node?.type === "element" && node?.tagName === "pre") {
const [codeEl] = node.children;
if (codeEl.tagName !== "code") return;
node.__rawString__ = codeEl.children?.[0].value;
}
});
},
[
rehypePrettyCode,
{
theme: "github-dark",
keepBackground: false,
onVisitLine(node) {
// Prevent lines from collapsing in `display: grid` mode, and allow empty lines to be copy/pasted
if (node.children.length === 0) {
node.children = [{ type: "text", value: " " }];
}
},
},
],
() => (tree) => {
visit(tree, (node) => {
if (node?.type === "element" && node?.tagName === "figure") {
if (!("data-rehype-pretty-code-figure" in node.properties)) {
return;
}
const preElement = node.children.at(-1);
if (preElement.tagName !== "pre") {
return;
}
preElement.properties["__rawString__"] = node.__rawString__;
}
});
},
[
rehypeAutolinkHeadings,
{
properties: {
className: ["subheading-anchor"],
ariaLabel: "Link to section",
},
},
],
],
},
});