Files
darkwave/lib/posts.ts

90 lines
2.9 KiB
TypeScript
Raw Normal View History

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { remark } from 'remark';
import html from 'remark-html';
2026-01-20 03:11:12 +03:00
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeRaw from 'rehype-raw';
import rehypeStringify from 'rehype-stringify';
const postsDirectory = path.join(process.cwd(), 'posts');
export interface PostData {
slug: string;
title: string;
date: string;
tags: string[];
contentHtml: string;
description: string;
}
export function getAllPostSlugs(): string[] {
const fileNames = fs.readdirSync(postsDirectory);
return fileNames.map((fileName) => fileName.replace(/\.md$/, ''));
}
export function getSortedPostsData(): Omit<PostData, 'contentHtml'>[] {
const fileNames = fs.readdirSync(postsDirectory);
const allPostsData = fileNames.map((fileName) => {
const slug = fileName.replace(/\.md$/, '');
const fullPath = path.join(postsDirectory, fileName);
const fileContents = fs.readFileSync(fullPath, 'utf8');
const matterResult = matter(fileContents);
return {
slug,
title: matterResult.data.title,
date: matterResult.data.date,
tags: matterResult.data.tags || [],
description: matterResult.data.description || '',
};
});
return allPostsData.sort((a, b) => {
if (a.date < b.date) {
return 1;
} else {
return -1;
}
});
}
2026-01-20 03:11:12 +03:00
export async function getPostData(slug: string): Promise<PostData | null> {
try {
const fullPath = path.join(postsDirectory, `${slug}.md`);
if (!fs.existsSync(fullPath)) {
console.error(`Файл не найден: ${fullPath}`);
return null;
}
const fileContents = fs.readFileSync(fullPath, 'utf8');
const matterResult = matter(fileContents);
// Используем unified pipeline для более полной поддержки Markdown
const processedContent = await unified()
.use(remarkParse) // парсим Markdown
.use(remarkGfm) // добавляем поддержку GFM (таблицы, задачи и т.д.)
.use(remarkRehype, { allowDangerousHtml: true }) // конвертируем в HTML
.use(rehypeRaw) // разрешаем raw HTML
.use(rehypeStringify) // сериализуем в строку
.process(matterResult.content || '');
const contentHtml = processedContent.toString();
2026-01-20 03:11:12 +03:00
return {
slug,
contentHtml,
title: matterResult.data.title || 'Без названия',
date: matterResult.data.date || new Date().toISOString().split('T')[0],
tags: matterResult.data.tags || [],
description: matterResult.data.description || '',
};
} catch (error) {
console.error(`Ошибка при загрузке поста ${slug}:`, error);
return null;
}
}