Remark и Rehype — это экосистема
инструментов для работы с Markdown и HTML в JavaScript, где Remark
отвечает за парсинг Markdown в абстрактное синтаксическое дерево (AST),
а Rehype — за работу с HTML-представлением. Для генерации оглавления
(Table of Contents, TOC) часто используют плагин
remark-toc, который строит дерево заголовков документа.
Управление глубиной оглавления позволяет указать, какие
уровни заголовков включать, обеспечивая читаемость и компактность
TOC.
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkStringify from 'remark-stringify';
import remarkToc from 'remark-toc';
import fs from 'fs';
const markdown = fs.readFileSync('example.md', 'utf8');
const processor = unified()
.use(remarkParse)
.use(remarkToc, { heading: 'Содержание', maxDepth: 3 }) // ограничение глубины
.use(remarkStringify);
processor.process(markdown).then(file => {
console.log(String(file));
});
Ключевой момент: опция maxDepth
определяет максимальный уровень заголовков, которые попадут в TOC.
Уровни заголовков в Markdown обозначаются символами #, где
# — первый уровень, ## — второй, и так далее.
Значение maxDepth: 3 включает заголовки до
###.
Для больших документов может потребоваться вычислять глубину оглавления динамически. Это можно реализовать через функцию:
import remarkToc from 'remark-toc';
const depth = (documentLength) => {
if (documentLength < 500) return 2;
if (documentLength < 2000) return 3;
return 4;
};
const processor = unified()
.use(remarkParse)
.use(remarkToc, { heading: 'Содержание', maxDepth: depth(markdown.length) })
.use(remarkStringify);
Пояснение: функция depth анализирует
длину документа и определяет оптимальный уровень вложенности TOC, чтобы
не перегружать оглавление.
После генерации AST Markdown с TOC можно преобразовать документ в HTML с помощью Rehype:
import rehypeStringify from 'rehype-stringify';
import remarkRehype from 'remark-rehype';
const htmlProcessor = unified()
.use(remarkParse)
.use(remarkToc, { heading: 'Содержание', maxDepth: 3 })
.use(remarkRehype)
.use(rehypeStringify);
htmlProcessor.process(markdown).then(file => {
console.log(String(file));
});
Особенности:
remarkRehype конвертирует Markdown AST в HTML AST.rehype-slug для генерации идентификаторов
заголовков или rehype-autolink-headings для автоматической
привязки ссылок.Плагин remark-toc позволяет фильтровать заголовки через
опцию filter:
.use(remarkToc, {
heading: 'Содержание',
maxDepth: 3,
filter: (node) => !node.children[0].value.includes('Пропустить')
})
Смысл: заголовки, содержащие определённые слова или метки, исключаются из TOC, что повышает гибкость при построении оглавления для больших учебных материалов.
После конвертации в HTML можно управлять внешним видом TOC через CSS:
.toc {
list-style: none;
padding-left: 0;
}
.toc li {
margin-left: 1em;
}
.toc li li {
margin-left: 2em;
}
Принцип: вложенность списков в TOC отражает уровни
заголовков. CSS позволяет визуально ограничить или расширить эту
вложенность без изменения maxDepth в Remark.
unist-util-visit для обхода AST и модификации узлов
перед генерацией TOC.rehype-highlight для подсветки кода в оглавлении или
rehype-toc для кастомных HTML-структур.Эти методы позволяют создавать гибкие, читаемые и масштабируемые оглавления, которые подстраиваются под структуру документа и требования к уровню вложенности.