HaoAws/lib/markdown.ts
2025-09-16 16:37:48 +08:00

126 lines
3.8 KiB
TypeScript
Raw Permalink 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.

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { Locale } from './i18n';
export interface NewsArticle {
id: string;
title: string;
category: string;
date: string;
excerpt: string;
author: string;
readTime: string;
tags: string[];
featured: boolean;
content: string;
locale: Locale;
}
const DOCS_PATH = path.join(process.cwd(), 'docs', 'news');
export async function getNewsArticle(id: string, locale: Locale): Promise<NewsArticle | null> {
try {
const filePath = path.join(DOCS_PATH, locale, `${id}.md`);
if (!fs.existsSync(filePath)) {
return null;
}
const fileContents = fs.readFileSync(filePath, 'utf8');
const { data, content } = matter(fileContents);
return {
id,
title: data.title,
category: data.category,
date: data.date,
excerpt: data.excerpt,
author: data.author,
readTime: data.readTime,
tags: data.tags || [],
featured: data.featured || false,
content,
locale,
};
} catch (error) {
console.error(`Error reading article ${id} for locale ${locale}:`, error);
return null;
}
}
export async function getAllNewsArticles(locale: Locale): Promise<NewsArticle[]> {
try {
const articlesDir = path.join(DOCS_PATH, locale);
if (!fs.existsSync(articlesDir)) {
return [];
}
const filenames = fs.readdirSync(articlesDir);
const articles: NewsArticle[] = [];
for (const filename of filenames) {
if (filename.endsWith('.md')) {
const id = filename.replace(/\.md$/, '');
const article = await getNewsArticle(id, locale);
if (article) {
articles.push(article);
}
}
}
// Sort by date (newest first)
// Handle Chinese date format (e.g., "2024年1月15日")
const parseChineseDate = (dateStr: string): Date => {
// Try to parse Chinese date format first
const chineseDateMatch = dateStr.match(/(\d{4})年(\d{1,2})月(\d{1,2})日/);
if (chineseDateMatch) {
const [, year, month, day] = chineseDateMatch;
return new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
}
// Fallback to regular Date parsing
return new Date(dateStr);
};
return articles.sort((a, b) => {
const dateA = parseChineseDate(a.date);
const dateB = parseChineseDate(b.date);
return dateB.getTime() - dateA.getTime();
});
} catch (error) {
console.error(`Error reading articles for locale ${locale}:`, error);
return [];
}
}
export async function getAvailableLocalesForArticle(id: string): Promise<Locale[]> {
const availableLocales: Locale[] = [];
const locales: Locale[] = ['zh-CN', 'zh-TW', 'en'];
for (const locale of locales) {
const filePath = path.join(DOCS_PATH, locale, `${id}.md`);
if (fs.existsSync(filePath)) {
availableLocales.push(locale);
}
}
return availableLocales;
}
export function checkArticleExists(id: string, locale: Locale): boolean {
const filePath = path.join(DOCS_PATH, locale, `${id}.md`);
return fs.existsSync(filePath);
}
/**
* 获取最新的新闻文章(用于首页显示)
* @param locale 语言
* @param limit 限制文章数量默认为3
* @returns 最新的新闻文章数组
*/
export async function getLatestNewsArticles(locale: Locale, limit: number = 3): Promise<NewsArticle[]> {
const allArticles = await getAllNewsArticles(locale);
return allArticles.slice(0, limit);
}