В экосистеме Remark и Rehype дочерние элементы (children) играют ключевую роль при создании и модификации AST (Abstract Syntax Tree) для Markdown и HTML соответственно. Понимание структуры и способов работы с детьми позволяет реализовывать сложные трансформации и расширять возможности парсинга.
Каждый узел AST в Remark и Rehype может содержать поле
children, представляющее массив подузлов. Эти подузлы могут
быть как текстовыми, так и элементарными, например, параграфы,
заголовки, списки и другие компоненты.
Пример структуры узла Markdown:
{
type: 'paragraph',
children: [
{ type: 'text', value: 'Пример текста в параграфе' },
{ type: 'emphasis', children: [{ type: 'text', value: 'выделенный текст' }] }
]
}
Здесь видно, что дочерние элементы могут содержать своих детей, формируя древовидную иерархию.
Для работы с дочерними элементами используется стандартная навигация
по массиву children. Например, для изменения текста всех
параграфов:
import { visit } from 'unist-util-visit';
visit(tree, 'paragraph', node => {
node.children.forEach(child => {
if (child.type === 'text') {
child.value = child.value.toUpperCase();
}
});
});
Функция visit из пакета unist-util-visit
позволяет рекурсивно обходить дерево и работать с каждым узлом
определённого типа.
Добавление дочернего элемента выполняется простым добавлением в
массив children:
node.children.push({
type: 'text',
value: 'Новый текстовый узел'
});
Удаление осуществляется с помощью методов массива:
node.children = node.children.filter(child => child.type !== 'emphasis');
Это позволяет динамически изменять структуру документа, удаляя или добавляя нужные элементы на любом уровне вложенности.
Для сложных преобразований часто требуется рекурсивная обработка, когда дочерние элементы могут содержать свои дочерние узлы. Например, чтобы собрать все текстовые значения в одном массиве:
function collectText(node) {
let texts = [];
if (node.type === 'text') {
texts.push(node.value);
}
if (node.children) {
node.children.forEach(child => {
texts = texts.concat(collectText(child));
});
}
return texts;
}
const allText = collectText(tree);
Такой подход гарантирует, что текст будет извлечён из любой глубины вложенности.
Remark работает с Markdown AST (mdast), а Rehype — с
HTML AST (hast). Для передачи структуры между ними
используется конвертация:
import { remark } from 'remark';
import { rehype } from 'rehype';
import remarkToRehype from 'remark-rehype';
const processor = remark()
.use(remarkToRehype)
.use(rehypeStringify);
const html = await processor.process('# Заголовок с *выделением*');
При этом дочерние элементы Markdown автоматически преобразуются в соответствующие дочерние элементы HTML, сохраняя иерархию и вложенность.
В Rehype каждый дочерний элемент может содержать поля
type, tagName, properties и
children:
{
type: 'element',
tagName: 'a',
properties: { href: 'https://example.com' },
children: [
{ type: 'text', value: 'Ссылка' }
]
}
Управление этими свойствами позволяет создавать сложные компоненты, изменять атрибуты ссылок, изображений и других элементов без потери структуры документа.
children перед обходом,
чтобы избежать ошибок undefined.unist-util-visit
или unist-util-visit-parents для доступа к родителям.children
использовать splice вместо push.Работа с дочерними элементами — основа гибкой обработки Markdown и HTML в экосистеме Remark/Rehype, позволяющая создавать динамические, модифицируемые и высоко структурированные документы.