next-windfonts/contentlayer.config.ts
bo.yu 1caa9448c0 feat: 初始化项目基础架构和核心功能
添加项目基础架构,包括字体管理、文档系统、API路由和UI组件。实现字体预览、收藏、搜索和文档浏览功能。

- 初始化Next.js项目结构和配置
- 添加字体管理API路由和数据库模型
- 实现字体预览和收藏功能
- 添加文档系统支持MDX内容
- 创建核心UI组件库
- 配置Redux状态管理和持久化
- 添加Storybook组件文档
- 实现响应式布局和主题系统
- 添加测试工具和CI配置
- 完善开发环境和构建配置
2025-08-11 18:01:43 +08:00

98 lines
2.9 KiB
TypeScript

import { ComputedFields, defineDocumentType, makeSource } from 'contentlayer2/source-files';
import {
remarkExtractFrontmatter,
remarkCodeTitles,
remarkImgToJsx,
} from 'pliny/mdx-plugins/index.js';
import path from 'path';
import { fromHtmlIsomorphic } from 'hast-util-from-html-isomorphic';
// Remark packages
import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
import { remarkAlert } from 'remark-github-blockquote-alert';
import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import rehypeKatex from 'rehype-katex';
import rehypeCitation from 'rehype-citation';
import rehypePrismPlus from 'rehype-prism-plus';
import rehypePresetMinify from 'rehype-preset-minify';
const root = process.cwd();
// heroicon mini link
const icon = fromHtmlIsomorphic(
`
<span class="content-header-link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-5 h-5 linkicon">
<path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z" />
<path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z" />
</svg>
</span>
`,
{ fragment: true }
);
const computedFields: ComputedFields = {
slug: {
type: 'string',
resolve: (doc) => doc._raw.flattenedPath.replace(/^.+?(\/)/, ''),
},
slugList: {
type: 'list',
resolve: (doc) => doc._raw.flattenedPath.replace(/^.+?(\/)/, '').split('/'),
},
path: {
type: 'string',
resolve: (doc) => doc._raw.flattenedPath,
},
filePath: {
type: 'string',
resolve: (doc) => doc._raw.sourceFilePath,
},
};
export const Doc = defineDocumentType(() => ({
name: 'Docs',
filePathPattern: 'docs/**/*.mdx',
contentType: 'mdx',
fields: {
title: { type: 'string', required: true },
section: { type: 'string' },
date: { type: 'date', required: true },
order: { type: 'number', required: true },
},
computedFields,
}));
export default makeSource({
contentDirPath: 'posts', // 根目录文件路径
documentTypes: [Doc],
mdx: {
cwd: process.cwd(),
remarkPlugins: [
remarkExtractFrontmatter,
remarkGfm,
remarkCodeTitles,
remarkMath,
remarkImgToJsx,
remarkAlert,
],
rehypePlugins: [
rehypeSlug,
[
rehypeAutolinkHeadings,
{
behavior: 'prepend',
headingProperties: {
className: ['content-header'],
},
content: icon,
},
],
rehypeKatex,
[rehypeCitation, { path: path.join(root, 'data') }],
[rehypePrismPlus, { defaultLanguage: 'js', ignoreMissing: true }],
rehypePresetMinify,
],
},
});