Для работы с библиотеками Remark и Rehype в браузере используется сборка через модули ES или подключение через CDN. Вариант с ES-модулями требует настройки сборщика вроде Vite или Webpack. Пример подключения через CDN:
<script type="module">
import { unified } from 'https://cdn.jsdelivr.net/npm/unified@11/+esm';
import { remarkParse } from 'https://cdn.jsdelivr.net/npm/remark-parse@10/+esm';
import { remarkRehype } from 'https://cdn.jsdelivr.net/npm/remark-rehype@10/+esm';
import { rehypeStringify } from 'https://cdn.jsdelivr.net/npm/rehype-stringify@10/+esm';
const processor = unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeStringify);
const markdown = '# Заголовок 1\n\nТекст с **жирным** выделением.';
const html = await processor.process(markdown);
console.log(String(html));
</script>
Этот пример показывает полную цепочку преобразования Markdown в HTML без серверной части.
1. Разбор Markdown remarkParse
превращает строку Markdown в AST (Abstract Syntax Tree) формата MDAST,
представляющий структуру документа. В этом дереве каждая нода описывает
тип контента: параграф, заголовок, список, ссылку, изображение.
2. Преобразование MDAST в HAST
remarkRehype переводит MDAST в HAST (HTML AST). Этот шаг
позволяет использовать возможности Rehype, включая модификацию тегов,
атрибутов и интеграцию с другими плагинами, например для добавления
классов к элементам или вставки пользовательских компонентов.
3. Генерация HTML rehypeStringify
превращает HAST обратно в HTML-строку. В браузере результат можно
вставлять в DOM с помощью innerHTML или создавать
виртуальные элементы для дальнейшей обработки.
Плагины расширяют функциональность библиотек:
remark-gfm добавляет поддержку GitHub Flavored Markdown,
включая таблицы и чекбоксы.rehype-highlight позволяет подсвечивать синтаксис кода, а
rehype-slug автоматически добавляет идентификаторы
заголовкам.Пример использования плагина:
import { remarkGfm } from 'https://cdn.jsdelivr.net/npm/remark-gfm@3/+esm';
import { rehypeHighlight } from 'https://cdn.jsdelivr.net/npm/rehype-highlight@6/+esm';
const processor = unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeHighlight)
.use(rehypeStringify);
const markdown = `
# Код с подсветкой
\`\`\`javascript
console.log('Hello World');
\`\`\`
`;
const html = await processor.process(markdown);
document.body.innerHTML = String(html);
Этот подход позволяет комбинировать множество плагинов для гибкой обработки Markdown и HTML прямо в браузере.
Некоторые плагины, особенно те, что загружают данные из внешних
источников или делают асинхронную обработку, требуют
await processor.process(). Важно использовать
await внутри асинхронной функции или then()
при цепочках промисов.
(async () => {
const html = await processor.process(markdown);
document.body.innerHTML = String(html);
})();
Remark и Rehype предоставляют API для программной модификации AST:
import { visit } from 'https://cdn.jsdelivr.net/npm/unist-util-visit@4/+esm';
const processor = unified()
.use(remarkParse)
.use(() => (tree) => {
visit(tree, 'heading', (node) => {
node.children.push({ type: 'text', value: ' ?' });
});
})
.use(remarkRehype)
.use(rehypeStringify);
const html = await processor.process('# Заголовок');
document.body.innerHTML = String(html);
В этом примере к каждому заголовку добавляется эмодзи. Использование
visit позволяет рекурсивно обходить дерево и изменять любые
ноды.
После преобразования Markdown в HTML результат можно вставлять в страницу динамически:
const container = document.getElementById('content');
container.innerHTML = String(await processor.process(markdown));
При этом можно комбинировать с динамическими данными, подставляя их в Markdown перед обработкой.
Пример использования Web Worker для Remark:
// worker.js
importScripts('https://cdn.jsdelivr.net/npm/unified@11/+esm',
'https://cdn.jsdelivr.net/npm/remark-parse@10/+esm',
'https://cdn.jsdelivr.net/npm/remark-rehype@10/+esm',
'https://cdn.jsdelivr.net/npm/rehype-stringify@10/+esm');
self.onmess age = async (e) => {
const processor = unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeStringify);
const html = await processor.process(e.data);
self.postMessage(String(html));
};
Главная страница передает Markdown в воркер и получает готовый HTML без задержек интерфейса.
Этот подход позволяет использовать Remark и Rehype полностью в браузере, обрабатывая Markdown, подключая плагины, модифицируя AST и динамически вставляя HTML в DOM.