MultiSite/lib/content.ts

92 lines
2.7 KiB
TypeScript
Raw Permalink Normal View History

2025-09-12 17:03:28 +08:00
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
export interface ContentMetadata {
title: string;
description: string;
date: string;
author: string;
category: string;
tags: string[];
draft?: boolean;
featured?: boolean;
}
export interface ContentItem {
slug: string;
metadata: ContentMetadata;
content: string;
}
const contentDirectory = path.join(process.cwd(), 'content');
export function getContentData(lang: string, slug: string): ContentItem {
const fullPath = path.join(contentDirectory, lang, `${slug}.md`);
if (!fs.existsSync(fullPath)) {
throw new Error(`Content not found: ${fullPath}`);
}
const fileContents = fs.readFileSync(fullPath, 'utf8');
const { data, content } = matter(fileContents);
return {
slug,
metadata: data as ContentMetadata,
content,
};
}
export function getAllContent(lang: string): ContentItem[] {
const langDirectory = path.join(contentDirectory, lang);
if (!fs.existsSync(langDirectory)) {
return [];
}
const files = fs.readdirSync(langDirectory);
return files
.filter((file) => file.endsWith('.md'))
.map((file) => {
const slug = file.replace('.md', '');
return getContentData(lang, slug);
})
.filter((item) => !item.metadata.draft)
.sort((a, b) => new Date(b.metadata.date).getTime() - new Date(a.metadata.date).getTime());
}
export function getContentByCategory(lang: string, category: string): ContentItem[] {
const allContent = getAllContent(lang);
return allContent.filter((item) => item.metadata.category === category);
}
export function getContentByTag(lang: string, tag: string): ContentItem[] {
const allContent = getAllContent(lang);
return allContent.filter((item) => item.metadata.tags && item.metadata.tags.includes(tag));
}
export function searchContent(lang: string, query: string): ContentItem[] {
const allContent = getAllContent(lang);
const searchQuery = query.toLowerCase();
return allContent.filter((item) => {
const searchText =
`${item.metadata.title} ${item.metadata.description} ${item.content}`.toLowerCase();
return searchText.includes(searchQuery);
});
}
export function getAllCategories(lang: string): string[] {
const allContent = getAllContent(lang);
const categories = allContent.map((item) => item.metadata.category);
return [...new Set(categories)].filter(Boolean);
}
export function getAllTags(lang: string): string[] {
const allContent = getAllContent(lang);
const tags = allContent.flatMap((item) => item.metadata.tags || []);
return [...new Set(tags)].filter(Boolean);
}