添加项目基础架构,包括字体管理、文档系统、API路由和UI组件。实现字体预览、收藏、搜索和文档浏览功能。 - 初始化Next.js项目结构和配置 - 添加字体管理API路由和数据库模型 - 实现字体预览和收藏功能 - 添加文档系统支持MDX内容 - 创建核心UI组件库 - 配置Redux状态管理和持久化 - 添加Storybook组件文档 - 实现响应式布局和主题系统 - 添加测试工具和CI配置 - 完善开发环境和构建配置
98 lines
2.9 KiB
TypeScript
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,
|
|
],
|
|
},
|
|
});
|