Remark и Rehype представляют собой современные и модульные инструменты для работы с Markdown и HTML в экосистеме JavaScript. Переход с других Markdown процессоров, таких как Marked, markdown-it или Showdown, требует понимания архитектуры этих библиотек, их плагинной системы и подхода к AST (Abstract Syntax Tree).
Remark использует unist (Universal Syntax Tree), что позволяет унифицировать работу с различными синтаксическими деревьями. Это отличает его от традиционных процессоров, которые работают на уровне строк и регулярных выражений. AST Remark предоставляет доступ к каждой ноде Markdown, что делает возможной точную модификацию, анализ и трансформацию документа.
Rehype выполняет аналогичную роль для HTML: она оперирует HTML-деревом как AST, позволяя интегрировать Markdown с HTML-процессорами. Основная идея заключается в том, что Markdown сначала парсится Remark в AST, затем через remark-rehype конвертируется в HTML-дерево, и после этого Rehype применяет свои трансформации и плагины.
npm install remark remark-html remark-parse rehype rehype-stringify remark-rehype
Пример с Remark:
import {remark} from 'remark';
import remarkHtml from 'remark-html';
const markdown = `# Заголовок
Текст с **жирным выделением**.`;
const result = await remark()
.use(remarkHtml)
.process(markdown);
console.log(String(result));
При использовании других процессоров подобная операция часто
выполнялась одной функцией marked(markdown). Здесь же
процесс более модульный: сначала AST, потом конвертация в HTML.
import remarkFootnotes from 'remark-footnotes';
await remark()
.use(remarkFootnotes, {inlineNotes: true})
.use(remarkHtml)
.process(markdown);
Подобный подход сложнее реализовать в старых процессорах, где требуется прямое вмешательство в рендер-функцию.
import {remark} from 'remark';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import rehypeAddClasses from 'rehype-add-classes';
const htmlResult = await remark()
.use(remarkRehype)
.use(rehypeAddClasses, {h1: 'title'})
.use(rehypeStringify)
.process(markdown);
console.log(String(htmlResult));
Этот подход открывает возможности сложного кастомного HTML, чего традиционные Markdown процессоры не обеспечивают.
import {remark} from 'remark';
import remarkRehype from 'remark-rehype';
import remarkFootnotes from 'remark-footnotes';
import rehypeStringify from 'rehype-stringify';
import rehypeAddClasses from 'rehype-add-classes';
import rehypeHighlight from 'rehype-highlight';
const result = await remark()
.use(remarkFootnotes, {inlineNotes: true})
.use(remarkRehype)
.use(rehypeAddClasses, {h1: 'title', pre: 'code-block'})
.use(rehypeHighlight)
.use(rehypeStringify)
.process(markdown);
console.log(String(result));
Эта последовательность полностью покрывает основные сценарии миграции с других Markdown процессоров, позволяя сохранить совместимость с существующим контентом и одновременно получить преимущества модульного, расширяемого подхода Remark/Rehype.