139 lines
3.6 KiB
TypeScript
139 lines
3.6 KiB
TypeScript
import { defineCollection, defineConfig } from "@content-collections/core";
|
|
import { compileMDX } from "@content-collections/mdx";
|
|
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
|
|
import rehypePrettyCode, { Options } from 'rehype-pretty-code';
|
|
import rehypeSlug from 'rehype-slug';
|
|
import { codeImport } from 'remark-code-import';
|
|
import remarkGfm from 'remark-gfm';
|
|
import { createHighlighter } from 'shiki';
|
|
import path from "path";
|
|
import { getBaseUrl } from "@/lib/urls/get-base-url";
|
|
|
|
/**
|
|
* Content Collections documentation
|
|
* 1. https://www.content-collections.dev/docs/quickstart/next
|
|
* 2. https://www.content-collections.dev/docs/configuration
|
|
* 3. https://www.content-collections.dev/docs/transform#join-collections
|
|
*/
|
|
|
|
/**
|
|
* Blog Author collection
|
|
*/
|
|
export const authors = defineCollection({
|
|
name: 'author',
|
|
directory: 'content',
|
|
include: '**/author/*.mdx',
|
|
schema: (z) => ({
|
|
slug: z.string(),
|
|
name: z.string(),
|
|
avatar: z.string()
|
|
}),
|
|
transform: async (data, context) => {
|
|
return {
|
|
...data,
|
|
avatar: getBaseUrl() + data.avatar
|
|
};
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Blog Category collection
|
|
*/
|
|
export const categories = defineCollection({
|
|
name: 'category',
|
|
directory: 'content',
|
|
include: '**/category/*.mdx',
|
|
schema: (z) => ({
|
|
slug: z.string(),
|
|
name: z.string(),
|
|
description: z.string()
|
|
})
|
|
});
|
|
|
|
/**
|
|
* Blog Post collection
|
|
*
|
|
* 1. For a blog post file at content/blog/2023/year-review.mdx:
|
|
* slug: /blog/2023/year-review
|
|
* slugAsParams: 2023/year-review
|
|
*
|
|
* 2. For a blog post at content/blog/first-post.mdx:
|
|
* slug: /blog/first-post
|
|
* slugAsParams: first-post
|
|
*/
|
|
export const posts = defineCollection({
|
|
name: 'post',
|
|
directory: 'content',
|
|
include: '**/blog/*.mdx',
|
|
schema: (z) => ({
|
|
title: z.string(),
|
|
description: z.string(),
|
|
image: z.string(),
|
|
date: z.string().datetime(),
|
|
published: z.boolean().default(true),
|
|
categories: z.array(z.string()),
|
|
author: z.string()
|
|
}),
|
|
transform: async (data, context) => {
|
|
const body = await compileMDX(context, data, {
|
|
remarkPlugins: [
|
|
remarkGfm,
|
|
codeImport
|
|
],
|
|
rehypePlugins: [
|
|
rehypeSlug,
|
|
rehypeAutolinkHeadings,
|
|
[rehypePrettyCode, prettyCodeOptions]
|
|
]
|
|
});
|
|
const blogAuthor = context
|
|
.documents(authors)
|
|
.find((a) => a.slug === data.author);
|
|
const blogCategories = context
|
|
.documents(categories)
|
|
.filter((c) => data.categories.includes(c.slug));
|
|
return {
|
|
...data,
|
|
author: blogAuthor,
|
|
categories: blogCategories,
|
|
image: getBaseUrl() + data.image,
|
|
slug: `/${data._meta.path}`,
|
|
slugAsParams: data._meta.path.split(path.sep).slice(1).join('/'),
|
|
body: {
|
|
raw: data.content,
|
|
code: body
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
const prettyCodeOptions: Options = {
|
|
theme: 'github-dark',
|
|
getHighlighter: (options) =>
|
|
createHighlighter({
|
|
...options
|
|
}),
|
|
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: ' ' }];
|
|
}
|
|
},
|
|
onVisitHighlightedLine(node) {
|
|
if (!node.properties.className) {
|
|
node.properties.className = [];
|
|
}
|
|
node.properties.className.push('line--highlighted');
|
|
},
|
|
onVisitHighlightedChars(node) {
|
|
if (!node.properties.className) {
|
|
node.properties.className = [];
|
|
}
|
|
node.properties.className = ['word--highlighted'];
|
|
}
|
|
};
|
|
|
|
export default defineConfig({
|
|
collections: [authors, categories, posts]
|
|
}); |