Remark и Rehype работают с деревом синтаксиса Markdown и HTML, что позволяет гибко управлять визуальным представлением документа на фронтенде. Для реализации темной темы основным инструментом становится комбинация CSS-переменных и кастомных плагинов.
CSS-переменные для цветовой схемы:
:root {
--background-color: #ffffff;
--text-color: #000000;
--link-color: #1a0dab;
}
[data-theme="dark"] {
--background-color: #121212;
--text-color: #e0e0e0;
--link-color: #8ab4f8;
}
С помощью атрибута data-theme можно динамически
переключать тему, не перезапуская генерацию HTML. Remark и Rehype при
этом остаются источником чистой структуры, а CSS отвечает за
отображение.
Remark предоставляет мощные возможности для расширения функциональности Markdown с помощью плагинов. Каждый плагин может модифицировать AST (Abstract Syntax Tree), добавляя новые узлы или изменяя существующие.
Пример добавления кастомных блоков:
import { remark } from 'remark';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
function remarkCustomBlocks() {
return (tree) => {
visit(tree, 'paragraph', (node, index, parent) => {
if (node.children[0].value.startsWith('::note')) {
const content = node.children[0].value.replace('::note', '').trim();
parent.children[index] = {
type: 'html',
value: `<div class="custom-note">${content}</div>`
};
}
});
};
}
remark()
.use(remarkParse)
.use(remarkCustomBlocks)
.use(remarkRehype)
.use(rehypeStringify)
.processSync('# Заголовок\n\n::note Важная заметка');
В этом примере создается блок заметки, который затем можно стилизовать через CSS:
.custom-note {
border-left: 4px solid #ffcc00;
padding: 10px;
background-color: var(--background-color);
color: var(--text-color);
}
[data-theme="dark"] .custom-note {
border-left-color: #ffbb33;
}
Rehype работает с HTML-деревом и позволяет напрямую манипулировать тегами, атрибутами и структурой документа. При интеграции темной темы важно использовать Rehype-плагины для добавления классов и атрибутов, чтобы управлять стилями через CSS.
Добавление класса к тегам по типу контента:
import { visit } from 'unist-util-visit';
function rehypeAddThemeClasses() {
return (tree) => {
visit(tree, 'element', (node) => {
if (node.tagName === 'pre') {
node.properties.className = (node.properties.className || []).concat('code-block');
}
if (node.tagName === 'img') {
node.properties.className = (node.properties.className || []).concat('responsive-image');
}
});
};
}
Такой подход позволяет централизованно управлять отображением блоков кода, картинок и других элементов для светлой и темной темы через CSS:
.code-block {
background-color: #f5f5f5;
color: #212121;
}
[data-theme="dark"] .code-block {
background-color: #1e1e1e;
color: #d4d4d4;
}
.responsive-image {
max-width: 100%;
height: auto;
}
Для сайтов с клиентской частью можно использовать JavaScript для
динамического изменения атрибута data-theme на
<html> или <body>, что позволяет
моментально переключать светлую и темную тему без повторного рендера
Markdown через Remark/Rehype.
function toggleTheme() {
const currentTheme = document.documentElement.getAttribute('data-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', newTheme);
}
Remark/Rehype поддерживают плагины для подсветки синтаксиса
(например, rehype-prism или rehype-highlight).
Для темной темы важно, чтобы цвета подсветки адаптировались к выбранной
схеме:
import rehypePrism from '@mapbox/rehype-prism';
remark()
.use(remarkParse)
.use(remarkRehype)
.use(rehypePrism, { plugins: ['line-numbers'] })
.use(rehypeStringify)
.processSync(markdownContent);
Подсветка кода автоматически использует CSS, поэтому нужно подключать файлы стилей для каждой темы:
/* light theme */
pre code {
background: #f5f5f5;
color: #212121;
}
/* dark theme */
[data-theme="dark"] pre code {
background: #1e1e1e;
color: #d4d4d4;
}
Комбинация Remark и Rehype с продуманной CSS-структурой и кастомными плагинами позволяет реализовать полностью настраиваемые темы, включая темную, а также расширять функциональность Markdown через создание уникальных блоков, управление атрибутами и динамическую адаптацию визуального оформления под любые требования проекта.