newechoes/src/content.config.ts
lsy f110beb5dc 1.全部改成参数式部件
2.可以用脚本创建文章
2025-03-10 17:22:18 +08:00

151 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 1. 从 `astro:content` 导入工具函数
import { defineCollection, z, getCollection, type CollectionEntry } from 'astro:content';
import { glob } from 'astro/loaders';
// 2. 定义内容结构接口
export interface ContentStructure {
articles: string[];
sections: SectionStructure[];
}
export interface SectionStructure {
name: string;
path: string;
articles: string[];
sections: SectionStructure[];
}
// 辅助函数获取相对于content目录的路径
export function getRelativePath(fullPath: string, basePath = './src/content'): string {
const normalizedPath = fullPath.replace(/\\/g, '/');
const normalizedBasePath = basePath.replace(/\\/g, '/');
let relativePath = normalizedPath;
if (normalizedPath.includes(normalizedBasePath)) {
relativePath = normalizedPath.replace(normalizedBasePath, '');
}
relativePath = relativePath.startsWith('/') ? relativePath.substring(1) : relativePath;
if (relativePath.startsWith('articles/')) {
relativePath = relativePath.substring('articles/'.length);
}
return relativePath;
}
// 辅助函数:从文件路径中提取文件名(不带扩展名)
export function getBasename(filePath: string): string {
const normalizedPath = filePath.replace(/\\/g, '/');
const parts = normalizedPath.split('/');
const fileName = parts[parts.length - 1];
return fileName.replace(/\.(md|mdx)$/, '');
}
// 辅助函数:从文件路径中提取目录路径
export function getDirPath(filePath: string, basePath = './src/content'): string {
const basename = getBasename(filePath);
const relativePath = getRelativePath(filePath, basePath);
return relativePath.replace(`${basename}.(md|mdx)`, '').replace(/\/$/, '');
}
// 辅助函数:获取特殊文件路径
export function getSpecialPath(originalPath: string): string {
const parts = originalPath.split('/');
const fileName = parts[parts.length - 1];
const dirName = parts.length > 1 ? parts[parts.length - 2] : '';
// 如果文件名与目录名相同,添加下划线前缀
if (dirName && fileName.toLowerCase() === dirName.toLowerCase()) {
const newFileName = fileName.startsWith('_') ? fileName : `_${fileName}`;
return [...parts.slice(0, -1), newFileName].join('/');
}
return originalPath;
}
// 3. 定义目录结构处理函数
async function getContentStructure(): Promise<ContentStructure> {
// 获取所有文章
const allArticles = await getCollection('articles');
const articlePaths = allArticles.map((entry: CollectionEntry<'articles'>) => entry.id);
// 构建目录树
const sections = new Map<string, SectionStructure>();
// 处理每个文章路径
for (const articlePath of articlePaths) {
const parts = articlePath.split('/');
const dirPath = parts.slice(0, -1);
// 为每一级目录创建或更新节点
let currentPath = '';
for (const part of dirPath) {
const parentPath = currentPath;
currentPath = currentPath ? `${currentPath}/${part}` : part;
if (!sections.has(currentPath)) {
sections.set(currentPath, {
name: part,
path: currentPath,
articles: [],
sections: []
});
}
// 将当前节点添加到父节点的子节点列表中
if (parentPath) {
const parentSection = sections.get(parentPath);
if (parentSection && !parentSection.sections.find(s => s.path === currentPath)) {
parentSection.sections.push(sections.get(currentPath)!);
}
}
}
// 将文章添加到其所在目录
if (dirPath.length > 0) {
const dirFullPath = dirPath.join('/');
const section = sections.get(dirFullPath);
if (section) {
section.articles.push(articlePath);
}
}
}
// 获取顶级目录
const topLevelSections = Array.from(sections.values())
.filter(section => !section.path.includes('/'));
// 获取顶级文章(不在任何子目录中的文章)
const topLevelArticles = articlePaths.filter((path: string) => !path.includes('/'));
return {
articles: topLevelArticles,
sections: topLevelSections
};
}
// 4. 定义你的集合
const articles = defineCollection({
loader: glob({
pattern: "**/*.{md,mdx}",
base: "./src/content"
}),
schema: z.object({
title: z.string(),
date: z.date(),
tags: z.array(z.string()).optional(),
summary: z.string().optional(),
image: z.string().optional(),
author: z.string().optional(),
draft: z.boolean().optional().default(false),
section: z.string().optional(),
weight: z.number().optional(),
}),
});
// 5. 导出一个 `collections` 对象来注册你的集合
export const collections = { articles };
// 6. 导出内容结构
export const contentStructure = await getContentStructure();