Специфика плагинов для HTML

Remark и Rehype — это мощные инструменты для работы с Markdown и HTML в экосистеме JavaScript. Remark преобразует Markdown в AST (Abstract Syntax Tree), а Rehype работает с HTML-документами в виде дерева узлов. Плагины являются основным механизмом расширения их функциональности и позволяют модифицировать контент на уровне AST, добавлять или удалять элементы, обрабатывать атрибуты и применять пользовательские трансформации.

Архитектура плагинов

Remark-плагины работают с деревом mdast (Markdown AST). Каждая нода имеет тип (type) и свойства (children, value, lang, и др.). Плагины получают объект дерева и могут:

  • обходить дерево с помощью функций обхода (visit, unist-util-visit);
  • модифицировать или удалять узлы;
  • добавлять новые узлы, изменяя структуру документа.

Пример типовой структуры узла MDAST:

{
  "type": "paragraph",
  "children": [
    {
      "type": "text",
      "value": "Пример текста"
    }
  ]
}

Rehype-плагины оперируют деревом hast (HTML AST). Узлы hast имеют типы element, text, comment и содержат:

  • tagName — имя тега HTML (div, p, h1);
  • properties — объект атрибутов (className, id, src);
  • children — массив дочерних узлов.

Пример структуры HAST-узла:

{
  "type": "element",
  "tagName": "p",
  "properties": {},
  "children": [
    {
      "type": "text",
      "value": "Пример параграфа"
    }
  ]
}

Механизм подключения плагинов

Плагины подключаются при конфигурации процессора через метод use:

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import myPlugin from './myPlugin.js';

const processor = unified()
  .use(remarkParse)
  .use(remarkRehype)
  .use(myPlugin)
  .use(rehypeStringify);

Важно, что порядок подключения плагинов критичен: изменения, внесённые одним плагином, могут повлиять на работу следующих.

Типы плагинов и их задачи

  1. Обработка текста и контента Плагины могут автоматически преобразовывать текст: подчёркивать, заменять ключевые слова, конвертировать эмодзи в Unicode и создавать интерактивные элементы.

  2. Манипуляции с узлами HTML Rehype-плагины часто используются для добавления атрибутов к элементам, оборачивания тегов в дополнительные контейнеры, удаления нежелательных тегов или внедрения скриптов.

  3. Синтаксические трансформации Некоторые плагины анализируют Markdown или HTML и создают новые ноды, преобразуя структуры документа, например, автоматическое создание оглавлений на основе заголовков.

  4. Интеграция с внешними инструментами Плагины могут включать сторонние библиотеки: для подсветки кода, вставки диаграмм, обработки ссылок и генерации таблиц контента.

Важные нюансы разработки плагинов

  • Чистота AST: необходимо поддерживать валидную структуру дерева. Некорректная модификация может привести к ошибкам рендеринга.
  • Асинхронные операции: плагины могут возвращать промисы. Remark и Rehype поддерживают асинхронные плагины через async/await.
  • Контроль глубины обхода: при рекурсивной обработке узлов важно избегать бесконечных циклов. Используются функции visit и visitParents для безопасного обхода.
  • Совместимость с другими плагинами: при создании собственного плагина необходимо учитывать, что другие плагины могут изменять дерево в неожиданных местах.

Пример создания плагина для Rehype

Создание плагина, который добавляет CSS-класс ко всем заголовкам:

import { visit } from 'unist-util-visit';

export default function rehypeAddClass() {
  return (tree) => {
    visit(tree, 'element', (node) => {
      if (/^h[1-6]$/.test(node.tagName)) {
        node.properties = node.properties || {};
        node.properties.className = [
          ...(node.properties.className || []),
          'custom-heading'
        ];
      }
    });
  };
}

Ключевые моменты:

  • Использование visit для обхода элементов дерева.
  • Проверка типа узла через tagName.
  • Корректное добавление класса без перезаписи существующих.

Передача опций в плагины

Большинство плагинов поддерживают конфигурацию через параметры:

.use(myPlugin, { prefix: 'custom-' })

Это позволяет:

  • изменять поведение плагина без изменения кода;
  • создавать универсальные решения для разных проектов;
  • минимизировать дублирование логики.

Инструменты для отладки

Для разработки плагинов удобно использовать:

  • unist-util-visit — безопасный обход узлов;
  • unist-util-is — проверка типа узла;
  • unist-util-inspect — вывод дерева для визуальной проверки;
  • rehype-parse и rehype-stringify — для промежуточного тестирования модификаций HTML.

Эти инструменты упрощают отладку и позволяют быстро видеть, как изменения плагина влияют на конечный результат.

Лучшие практики

  • Избегать глобальных мутаций дерева; предпочтительнее возвращать новые узлы.
  • Структурировать плагины так, чтобы каждая функция выполняла одну конкретную задачу.
  • Использовать TypeScript или JSDoc для типизации узлов AST, что уменьшает ошибки при доступе к свойствам.