Плагины-фабрики с опциями

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

Принцип работы плагина-фабрики

Плагин-фабрика — это функция, которая возвращает сам плагин. Стандартная форма выглядит так:

function myPlugin(options) {
  return function transformer(tree, file) {
    // трансформация AST
  };
}
  • options — объект с конфигурацией плагина. Он может содержать любые параметры: фильтры узлов, настройки форматирования, ключи для добавления метаданных.
  • transformer(tree, file) — функция, которая выполняет основную работу по обходу и модификации AST (Abstract Syntax Tree).

Фабричная функция может быть вызвана с разными параметрами, создавая несколько версий одного и того же плагина, что удобно для масштабных проектов с разнообразными требованиями к обработке контента.

Передача и использование опций

Опции передаются непосредственно при подключении плагина:

import remark fr om 'remark';
import myPlugin from './myPlugin.js';

const processor = remark().use(myPlugin, {
  enableLinks: true,
  headingDepth: 2
});

Внутри плагина доступ к опциям осуществляется через аргумент фабрики:

function myPlugin(options) {
  return function transformer(tree) {
    const { enableLinks, headingDepth } = options;

    visit(tree, 'link', node => {
      if (!enableLinks) node.type = 'text';
    });

    visit(tree, 'heading', node => {
      if (node.depth > headingDepth) node.depth = headingDepth;
    });
  };
}

Таким образом, фабрика обеспечивает динамическую конфигурацию поведения AST-трансформации.

Совместимость с Rehype

Rehype работает аналогично, но на уровне HTML AST (hast). Фабрика принимает опции и возвращает функцию-трансформер:

function rehypePlugin(options) {
  return function transformer(tree) {
    visit(tree, 'element', node => {
      if (options.addClass) {
        node.properties = node.properties || {};
        node.properties.className = (node.properties.className || []).concat('custom-class');
      }
    });
  };
}

Опции позволяют создавать универсальные плагины, которые можно применять к разным проектам без изменения кода плагина.

Рекомендации по проектированию плагинов-фабрик

  1. Минимизация побочных эффектов: Плагин должен изменять только AST, не трогая внешние объекты.
  2. Явное указание опций: Предусмотреть значения по умолчанию, чтобы плагин был предсказуемым.
  3. Документирование опций: Каждое поле объекта опций должно иметь четкое описание.
  4. Поддержка функций обратного вызова: Иногда полезно передавать callback для кастомных действий при обходе AST.
  5. Валидация опций: Проверка типа и допустимых значений повышает надежность плагина.

Пример универсального плагина-фабрики

function transformHeadings(options = {}) {
  const { prefix = '', maxDepth = 3 } = options;

  return function transformer(tree) {
    visit(tree, 'heading', node => {
      if (node.depth <= maxDepth) {
        node.children.unshift({ type: 'text', value: prefix });
      }
    });
  };
}

const processor = remark()
  .use(transformHeadings, { prefix: 'Chapter: ', maxDepth: 2 });

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

Интеграция нескольких плагинов с опциями

Remark и Rehype позволяют комбинировать несколько плагинов с разными опциями:

remark()
  .use(pluginA, { flag: true })
  .use(pluginB, { lim it: 5 })
  .use(pluginC, { transform: node => node.value.toUpperCase() });

Каждый плагин обрабатывает AST независимо, при этом опции позволяют адаптировать поведение под конкретные требования без модификации исходного кода.

Важные детали реализации

  • Immutable подход: При необходимости можно создавать копии узлов AST, чтобы избежать нежелательных мутаций.
  • Асинхронные фабрики: Плагины могут возвращать async function transformer, если требуется работа с внешними ресурсами.
  • Совместимость с unified: Все фабрики построены на едином интерфейсе unified, что упрощает интеграцию Remark и Rehype в одну цепочку обработки.

Фабрики с опциями — ключевой инструмент для создания настраиваемых, масштабируемых и переиспользуемых плагинов, которые обеспечивают мощное управление AST и адаптацию под разнообразные требования проектов.