This commit is contained in:
2026-06-18 10:36:41 +08:00 Unverified
parent 1a862adddc
commit 7c3679e885
41 changed files with 10544 additions and 163 deletions
+94
View File
@@ -0,0 +1,94 @@
type MarkdownModule = {
frontmatter: Record<string, unknown>;
Content: unknown;
rawContent?: () => string;
file?: string;
};
export type BlogPost = MarkdownModule & {
title: string;
slug: string;
date: Date;
dateText: string;
tags: string[];
categories: string[];
summary: string;
href: string;
};
const modules = import.meta.glob<MarkdownModule>('/source/_posts/**/*.md', { eager: true });
function asArray(value: unknown): string[] {
if (Array.isArray(value)) return value.map(String).filter(Boolean);
if (typeof value === 'string' && value.trim()) return [value.trim()];
return [];
}
function toDate(value: unknown): Date {
if (value instanceof Date) return value;
if (typeof value === 'string' || typeof value === 'number') {
const date = new Date(value);
if (!Number.isNaN(date.valueOf())) return date;
}
return new Date(0);
}
function formatDate(date: Date): string {
return new Intl.DateTimeFormat('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
}).format(date);
}
function fallbackSlug(path: string): string {
return path
.split('/')
.pop()
?.replace(/\.md$/, '')
.toLowerCase() ?? 'post';
}
function makeSummary(module: MarkdownModule): string {
const explicit = module.frontmatter.summary ?? module.frontmatter.description;
if (typeof explicit === 'string' && explicit.trim()) return explicit.trim();
const raw = module.rawContent?.() ?? '';
return raw
.replace(/```[\s\S]*?```/g, '')
.replace(/<[^>]+>/g, '')
.replace(/[#>*_`~\-\[\]\(\)]/g, '')
.replace(/\s+/g, ' ')
.trim()
.slice(0, 120);
}
export function getAllPosts(): BlogPost[] {
return Object.entries(modules)
.map(([path, module]) => {
const date = toDate(module.frontmatter.date);
const slug = String(module.frontmatter.abbrlink ?? fallbackSlug(path));
const title = String(module.frontmatter.title ?? slug);
return {
...module,
title,
slug,
date,
dateText: formatDate(date),
tags: asArray(module.frontmatter.tags),
categories: asArray(module.frontmatter.categories),
summary: makeSummary(module),
href: `/posts/${slug}/`,
};
})
.sort((a, b) => b.date.valueOf() - a.date.valueOf());
}
export function getAllTags(): string[] {
return [...new Set(getAllPosts().flatMap((post) => post.tags))].sort((a, b) => a.localeCompare(b, 'zh-CN'));
}
export function getAllCategories(): string[] {
return [...new Set(getAllPosts().flatMap((post) => post.categories))].sort((a, b) => a.localeCompare(b, 'zh-CN'));
}