unist-util-select — это библиотека для работы с
деревьями синтаксиса, совместимая с экосистемой unist,
включая remark и rehype. Она позволяет
выбирать узлы в дереве с помощью синтаксиса, напоминающего
CSS-селекторы. Этот подход значительно упрощает навигацию по дереву
Markdown или HTML, делая операции фильтрации и извлечения данных более
декларативными.
select — возвращает первый найденный
узел, соответствующий селектору.selectAll — возвращает массив всех
узлов, удовлетворяющих селектору.matches — проверяет, удовлетворяет ли
узел заданному селектору.Селекторы в unist-util-select используют CSS-подобную
нотацию, включая:
Тип узла: указывается именем типа, например
paragraph, heading, link.
selectAll(tree, 'paragraph'); // выбирает все параграфыID и классы: поддерживается синтаксис
#id и .class, если узлы имеют соответствующие
свойства.
sel ect(tree, 'heading#main'); // заголовок с id "main"
selectAll(tree, 'list.item.special'); // элементы списка с классом "special"Атрибуты: можно использовать селекторы вида
[name=value].
selectAll(tree, 'link[href="https://example.com"]');Комбинации и иерархия: селекторы могут
использовать пробелы для обозначения потомков и > для
прямых потомков.
selectAll(tree, 'list > listItem'); // прямые дочерние элементы списка
selectAll(tree, 'heading paragraph'); // параграфы внутри заголовковremarkПри работе с Markdown дерево разбивается на узлы
paragraph, heading, link,
image и другие. unist-util-select позволяет
извлекать нужные части документа без ручной рекурсии по дереву.
Пример: извлечение всех ссылок из Markdown:
import { unified } fr om 'unified';
import remarkParse from 'remark-parse';
import { selectAll } from 'unist-util-select';
const markdown = `
# Заголовок
Текст с [ссылкой](https://example.com)
`;
const tree = unified().use(remarkParse).parse(markdown);
const links = selectAll(tree, 'link');
console.log(links.map(node => node.url));
// ['https://example.com']
rehypeДля HTML-деревьев rehype узлы содержат типы
element и text. Атрибуты HTML
(id, class, href) доступны в
объекте properties. unist-util-select
позволяет делать выборки по этим атрибутам, аналогично CSS.
Пример: извлечение всех изображений с определённым классом:
import { unified } from 'unified';
import rehypeParse from 'rehype-parse';
import { selectAll } from 'unist-util-select';
const html = `
<div>
<img src="image1.jpg" class="thumbnail">
<img src="image2.jpg">
</div>
`;
const tree = unified().use(rehypeParse, { fragment: true }).parse(html);
const thumbnails = selectAll(tree, 'img.thumbnail');
console.log(thumbnails.map(node => node.properties.src));
// ['image1.jpg']
unist-util-select поддерживает сложные выражения:
Объединение селекторов: , позволяет
выбрать узлы, удовлетворяющие любому из селекторов.
selectAll(tree, 'paragraph, heading'); // параграфы или заголовкиКомбинаторы: + выбирает следующий
соседний узел, ~ — любой следующий сосед.
selectAll(tree, 'heading + paragraph'); // параграф сразу после заголовкаПсевдоклассы: поддерживаются
:first-child, :last-child,
:nth-child(n).
select(tree, 'listItem:first-child'); // первый элемент спискаВ дополнение к строковым селекторам можно использовать функции фильтрации:
selectAll(tree, node => node.type === 'link' && node.url.includes('example'));
Этот метод даёт максимальную гибкость при выборе узлов по сложным условиям, когда стандартный CSS-подобный синтаксис недостаточен.
paragraph, heading)
быстрее, чем по атрибутам, поскольку не требуется проверка объекта
properties.selectAll с
конкретными селекторами, чтобы минимизировать количество обходов.list > listItem)
эффективны при правильной структуре дерева, так как обход ограничивается
поддеревьями.unist-util-select легко интегрируется с плагинами
remark и rehype. Это позволяет:
unist:
type, children, value или
properties.rehype рекомендуется всегда использовать
{ fragment: true } при разборе кусков кода, чтобы избежать
ошибок парсера.class или id приведёт к пустой
выборке.unist-util-select объединяет удобство CSS-селекторов с
мощью обработки деревьев unist, делая навигацию, фильтрацию
и трансформацию данных в Markdown и HTML интуитивной и эффективной.