Remark и Rehype — это два мощных инструмента для работы с текстами в формате Markdown и HTML в экосистеме JavaScript. Remark отвечает за разбор, модификацию и генерацию Markdown, а Rehype — за HTML. Оба инструмента строятся на основе дерева синтаксического анализа (AST — Abstract Syntax Tree), что позволяет осуществлять точечные трансформации содержимого и интегрировать сторонние плагины для расширения функционала.
AST (Abstract Syntax Tree) — это иерархическая
структура данных, представляющая исходный текст как набор узлов. Каждый
узел содержит тип (type), свойства (data,
attributes) и дочерние элементы (children). В
Remark и Rehype выделяются основные типы узлов:
depth).lang).Пример создания узла кода с языком программирования:
const codeNode = {
type: 'code',
lang: 'javascript',
value: 'console.log("Hello, world!");'
};
В Markdown часто используются код-блоки, обозначаемые тройными обратными кавычками:
```javascript
console.log("Пример кода");
```
Remark сохраняет язык программирования в поле lang узла
типа code. Это позволяет выполнять:
rehype-prism).Пример обхода AST для извлечения всех узлов с языком
javascript:
import { visit } from 'unist-util-visit';
visit(tree, 'code', (node) => {
if (node.lang === 'javascript') {
console.log(node.value);
}
});
Remark может быть использован совместно с Rehype через плагин
remark-rehype, который преобразует MDAST в HAST. Это
необходимо для рендеринга Markdown в HTML с последующей обработкой:
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
const processor = unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeStringify);
const html = await processor.process('```javascript\nconsole.log("Hello");\n```');
console.log(String(html));
Ключевые моменты:
remark-parse преобразует Markdown в MDAST.remark-rehype конвертирует MDAST в HAST.rehype-stringify генерирует HTML из HAST.lang пустое.Пример фильтрации и подсветки JavaScript-кода:
import { visit } from 'unist-util-visit';
import { highlight } from 'rehype-prism-plus';
visit(tree, 'code', (node) => {
if (node.lang === 'javascript') {
node.type = 'html';
node.value = highlight(node.value, { lang: 'javascript' });
}
});
Heading с разными уровнями для логической
структуры.lang облегчают интеграцию с
системами документации.Root
├─ Heading (depth: 1)
├─ Paragraph
├─ Code (lang: javascript)
├─ Heading (depth: 2)
├─ List
│ ├─ ListItem
│ └─ ListItem
└─ Code (lang: python)
Такое представление позволяет:
Для проектов, включающих несколько языков:
lang каждого блока кода.