Remark — это универсальный парсер Markdown, который превращает текст в абстрактное синтаксическое дерево (AST). AST представляет Markdown в виде структурированных объектов, что позволяет выполнять трансформации, анализ и генерацию новых форматов. Основной элемент работы с Remark — плагинная система: плагины могут модифицировать дерево, добавлять содержимое, конвертировать Markdown в другие форматы.
Rehype выполняет схожую роль для HTML. Он парсит HTML в AST, который можно обрабатывать, модифицировать и затем рендерить обратно в HTML. С помощью Rehype можно добавлять атрибуты, изменять структуру документа, вставлять дополнительные элементы и интегрировать данные из внешних источников.
Объединение Remark и Rehype позволяет создавать конвейеры обработки Markdown → AST → HTML, которые идеально подходят для генерации API-документации из исходных файлов, комментариев к коду или OpenAPI-спецификаций.
import fs from 'fs';
const markdownContent = fs.readFileSync('./api-description.md', 'utf-8');
import { unified } from 'unified';
import remarkParse from 'remark-parse';
const processor = unified().use(remarkParse);
const ast = processor.parse(markdownContent);
AST представляет каждый элемент документа в виде узлов:
heading, paragraph, list,
code. Для документации важно правильно идентифицировать
заголовки методов API, параметры и примеры запросов.
Remark-плагины могут автоматически добавлять аннотации или ссылки:
import remarkSlug from 'remark-slug';
import remarkAutolinkHeadings from 'remark-autolink-headings';
const processedAst = await unified()
.use(remarkParse)
.use(remarkSlug) // добавляет ID для заголовков
.use(remarkAutolinkHeadings) // превращает заголовки в ссылки
.process(markdownContent);
Эти шаги позволяют создать структуру, пригодную для генерации оглавления и ссылок на методы API.
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
const html = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeStringify)
.process(markdownContent);
remarkRehype преобразует Markdown-узлы в HTML-узлы,
сохраняя структуру документа, а rehypeStringify генерирует
итоговый HTML-код, который можно вставить в веб-приложение
документации.
Для автогенерации документации по методам API можно использовать структурированные комментарии или JSON-файлы, содержащие спецификации:
const apiSpec = [
{ method: 'GET', path: '/users', description: 'Получение списка пользователей' },
{ method: 'POST', path: '/users', description: 'Создание нового пользователя' }
];
Преобразование спецификации в Markdown AST:
import { visit } from 'unist-util-visit';
import { u } from 'unist-builder';
const ast = u('root', apiSpec.map(item =>
u('section', [
u('heading', { depth: 3 }, [u('text', `${item.method} ${item.path}`)]),
u('paragraph', [u('text', item.description)])
])
));
Использование AST позволяет:
AST позволяет вставлять блоки кода для демонстрации запросов:
u('code', { lang: 'javascript' }, `fetch('${item.path}')\n .then(res => res.json())`);
После конвертации через Rehype эти блоки будут корректно отображены с подсветкой синтаксиса, если подключить соответствующие CSS-стили.
Rehype-плагины позволяют модифицировать HTML перед финальной сборкой:
import rehypeHighlight from 'rehype-highlight';
import rehypeFormat from 'rehype-format';
const finalHtml = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeHighlight) // подсветка кода
.use(rehypeFormat) // форматирование HTML
.use(rehypeStringify)
.process(markdownContent);
Выводы по архитектуре конвейера:
Рекомендуется разделять исходные данные и процесс генерации:
/docs
/source
api.md
/build
api.html
/generators
generateApiDocs.js
generateApiDocs.js реализует весь конвейер: чтение
Markdown, трансформацию AST, генерацию HTML, вставку примеров запросов и
подсветку кода.
Эта архитектура позволяет масштабировать документацию для крупных проектов, поддерживая актуальность и единый стиль представления API.