Files
darkwave/lib/posts.ts

96 lines
3.0 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.

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { remark } from 'remark';
import html from 'remark-html';
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';
import rehypePrism from 'rehype-prism-plus';
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;
}
});
}
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 с подсветкой синтаксиса
const processedContent = await unified()
.use(remarkParse) // парсим Markdown
.use(remarkGfm) // добавляем поддержку GFM (таблицы и т.д.)
.use(remarkRehype) // конвертируем в HTML AST
.use(rehypePrism, {
// Настройки подсветки
showLineNumbers: true, // показывать номера строк
ignoreMissing: true, // игнорировать неизвестные языки
})
.use(rehypeStringify) // сериализуем в строку
.process(matterResult.content || '');
const contentHtml = processedContent.toString();
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;
}
}