Directive нотация — это расширение синтаксиса Markdown, которое позволяет внедрять в документ семантические директивы, управлять структурой контента и создавать на его основе кастомные элементы при обработке через Remark и Rehype. Основное назначение директив — предоставлять способ добавления структурированной метаинформации в Markdown, которую потом можно преобразовать в HTML или другие форматы через AST (Abstract Syntax Tree).
Директивы бывают трёх основных типов:
Leaf directives (листовые директивы) Представляют собой одиночные элементы без вложенного контента. Их можно использовать для вставки ссылок, кнопок, иконок или других небольших блоков.
Пример синтаксиса:
:icon[star]{color="gold"}
Здесь icon — имя директивы, [star] —
аргумент, а {color="gold"} — набор атрибутов.
Container directives (контейнерные директивы) Используются для обрамления целых блоков контента, таких как карточки, предупреждения или секции с кодом.
Пример синтаксиса:
:::note{type="warning"}
Текст предупреждения внутри контейнера.
:::
В AST это создаёт узел containerDirective, содержащий
дочерние узлы Markdown.
Leaf-Block directives (гибридные листо-контейнерные директивы) Могут содержать текстовый контент, но обычно применяются для блоков с минимальной структурой. Они полезны для блоков типа цитат с параметрами или интерактивных элементов.
При парсинге Markdown через Remark директивы преобразуются в узлы типа:
{
type: 'leafDirective' | 'containerDirective' | 'textDirective',
name: 'имя_директивы',
attributes: {
ключ: значение
},
children: [ /* дочерние узлы Markdown */ ],
data: { hName, hProperties } // для Rehype, используется при трансформации в HTML
}
{}.Для работы с директивами в Remark используется плагин
remark-directive. Он расширяет стандартный парсер, добавляя
поддержку синтаксиса:
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkDirective from 'remark-directive';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
const processor = unified()
.use(remarkParse)
.use(remarkDirective)
.use(transformDirectives)
.use(remarkRehype)
.use(rehypeStringify);
function transformDirectives() {
return (tree) => {
visit(tree, (node) => {
if (node.type === 'leafDirective' || node.type === 'containerDirective') {
node.data = node.data || {};
node.data.hName = node.name; // пример преобразования в HTML-тег с именем директивы
node.data.hProperties = node.attributes || {};
}
});
};
}
Функция transformDirectives демонстрирует стандартный
способ преобразования директив в HTML-структуру через Rehype.
Атрибуты задаются через фигурные скобки {} и могут
включать:
{color="red"}{collapsed=true}{tags="js,remark,retext"}При трансформации в HTML они обычно конвертируются в свойства
элементов: hProperties.
Remark создаёт AST на основе Markdown с поддержкой директив. Rehype
берёт этот AST и конвертирует его в HTML. Поля data.hName и
data.hProperties обеспечивают точное соответствие тегов и
атрибутов:
<имя атрибуты/><имя атрибуты>...контент...имя>Такой подход обеспечивает гибкость, позволяя создавать кастомные HTML-элементы, управляемые через Markdown-синтаксис.
remark-directive.:::), иначе AST будет неполным.hName
и hProperties, иначе HTML-теги могут генерироваться
некорректно.Комбинация контейнерной и листовой директивы:
:::card{title="Пример карточки"}
Текст внутри карточки.
:icon[star]{color="gold"}
:::
В AST это создаёт контейнер card с дочерним текстом и
листовой директивой icon. При трансформации в HTML можно
получить:
Текст внутри карточки.
Такой подход позволяет строить сложные, интерактивные и семантически богатые страницы, полностью управляемые Markdown с директивами.