Remark и Rehype — это две ключевые библиотеки для обработки Markdown и HTML в экосистеме JavaScript. Remark отвечает за синтаксический разбор Markdown, предоставляя абстрактное синтаксическое дерево (MDAST), которое можно модифицировать с помощью плагинов. Rehype работает с HTML и HAST, позволяя производить трансформации, анализ и генерацию HTML-кода.
В контексте Next.js их используют вместе с MDX, чтобы расширять возможности Markdown и интегрировать компоненты React прямо в тексты документации, блогов или страниц. MDX использует Remark для парсинга Markdown, а Rehype — для генерации HTML и работы с DOM-подобными структурами.
Для начала нужно установить пакеты:
npm install remark remark-html rehype rehype-stringify next-mdx-remote
remark — ядро для работы с Markdown.remark-html — плагин для преобразования MDAST в
HTML.rehype — ядро для работы с HTML AST.rehype-stringify — преобразование HAST обратно в
HTML-строку.next-mdx-remote — позволяет рендерить MDX контент на
сервере и клиенте Next.js.Простейший пример обработки Markdown через Remark:
import { remark } from 'remark';
import html from 'remark-html';
import fs from 'fs';
import path from 'path';
const markdownPath = path.join(process.cwd(), 'content', 'example.md');
const fileContents = fs.readFileSync(markdownPath, 'utf8');
const processedContent = await remark()
.use(html)
.process(fileContents);
const contentHtml = processedContent.toString();
remark().use(html) подключает плагин, который
конвертирует Markdown в HTML.process(fileContents) возвращает объект с HTML в виде
строки, готовый для вставки в компонент Next.js.Rehype позволяет обрабатывать HTML, например, добавлять классы к тегам или интегрировать кастомные обработки.
import { rehype } from 'rehype';
import rehypeParse from 'rehype-parse';
import rehypeStringify from 'rehype-stringify';
import fs from 'fs';
import path from 'path';
const htmlPath = path.join(process.cwd(), 'content', 'example.html');
const htmlContent = fs.readFileSync(htmlPath, 'utf8');
const processedHtml = await rehype()
.data('settings', { fragment: true })
.use(rehypeParse, { fragment: true })
.use(() => (tree) => {
tree.children.forEach(node => {
if (node.tagName === 'p') {
node.properties = { className: ['custom-paragraph'] };
}
});
})
.use(rehypeStringify)
.process(htmlContent);
const finalHtml = processedHtml.toString();
rehypeParse преобразует HTML в HAST.rehypeStringify возвращает HTML в виде строки.MDX позволяет вставлять React-компоненты прямо в Markdown.
Конфигурация с next-mdx-remote:
import { serialize } from 'next-mdx-remote/serialize';
import { MDXRemote } from 'next-mdx-remote';
const mdxSource = `
# Заголовок
Нажми меня
`;
const mdxContent = await serialize(mdxSource, {
mdxOptions: {
remarkPlugins: [require('remark-gfm')],
rehypePlugins: [require('rehype-slug')]
}
});
remark-gfm добавляет поддержку GitHub Flavored Markdown
(таблицы, задачи).rehype-slug автоматически генерирует id
для заголовков.MDXRemote рендерит готовый контент как
React-компоненты:
Remark-плагины позволяют реализовать:
remark-prism),remark-toc),remark-autolink-headings).Rehype-плагины помогают:
rehype-minify),rehype-img-size),rehype-add-classes).Пример с плагинами для подсветки кода:
import remarkPrism from 'remark-prism';
const mdxContent = await serialize(mdxSource, {
mdxOptions: {
remarkPlugins: [remarkPrism],
rehypePlugins: []
}
});
getStaticProps или getServerSideProps) для
улучшения SEO и производительности.serialize или сохранять HTML в отдельной базе
данных.Для генерации страниц из Markdown:
export async function getStaticPaths() {
const files = fs.readdirSync(path.join(process.cwd(), 'content'));
const paths = files.map(filename => ({
params: { slug: filename.replace(/\.mdx$/, '') }
}));
return { paths, fallback: false };
}
export async function getStaticProps({ params }) {
const filePath = path.join(process.cwd(), 'content', `${params.slug}.mdx`);
const source = fs.readFileSync(filePath, 'utf8');
const mdxContent = await serialize(source, {
mdxOptions: {
remarkPlugins: [require('remark-gfm')],
rehypePlugins: [require('rehype-slug')]
}
});
return { props: { mdxContent } };
}
Такой подход позволяет создавать статические страницы с динамическим содержимым Markdown, используя всю мощь Remark и Rehype для кастомных преобразований и оптимизации HTML.