Pipeline для HTML обработки

Remark и Rehype — это две взаимодополняющие библиотеки экосистемы unified, предназначенные для парсинга и трансформации Markdown и HTML соответственно. Создание pipeline (конвейера) для HTML-обработки позволяет последовательно выполнять операции над содержимым, начиная от разбора документа до его модификации и генерации итогового HTML.

Архитектура pipeline

Pipeline строится на принципах AST (Abstract Syntax Tree). Remark конвертирует Markdown в MDAST, Rehype — HTML в HAST. Для HTML-процессинга важна следующая последовательность:

  1. Парсинг HTML в AST Rehype использует rehype-parse, который превращает HTML-текст в HAST. Этот этап позволяет работать с элементами документа на уровне узлов дерева, без необходимости манипулировать строками напрямую.

    import { unified } from 'unified';
    import parse from 'rehype-parse';
    
    const processor = unified().use(parse, { fragment: true });
    const ast = processor.parse('<div><p>Hello</p></div>');
  2. Трансформация AST После парсинга дерево можно модифицировать с помощью плагинов. Трансформации могут включать:

    • Добавление или удаление атрибутов элементов (rehype-attr или кастомные плагины).
    • Преобразование тегов (rehype-rewrite).
    • Внедрение контента, изменение структуры документа.

    Пример добавления класса ко всем <p> элементам:

    import rehypeVisit from 'unist-util-visit';
    
    function addClassToParagraphs() {
      return (tree) => {
        rehypeVisit(tree, 'element', (node) => {
          if (node.tagName === 'p') {
            node.properties = node.properties || {};
            node.properties.className = (node.properties.className || []).concat('custom-paragraph');
          }
        });
      };
    }
  3. Генерация HTML из AST После всех трансформаций дерево можно преобразовать обратно в HTML с помощью rehype-stringify:

    import stringify from 'rehype-stringify';
    
    const html = await unified()
      .use(parse, { fragment: true })
      .use(addClassToParagraphs)
      .use(stringify)
      .process('<p>Test</p>');
    
    console.log(String(html));

    На выходе получится: <p class="custom-paragraph">Test</p>.

Использование цепочек плагинов

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

  • Парсинг и разбора: rehype-parse, remark-parse
  • Трансформация узлов: rehype-rewrite, rehype-add-classes, кастомные функции с unist-util-visit
  • Оптимизация и проверка: rehype-minify, rehype-lint
  • Генерация: rehype-stringify, remark-stringify

Пример полноценного HTML pipeline:

import { unified } from 'unified';
import parse from 'rehype-parse';
import stringify from 'rehype-stringify';
import rehypeLint from 'rehype-lint';
import rehypeMinify from 'rehype-preset-minify';

const processor = unified()
  .use(parse, { fragment: true })
  .use(rehypeLint)
  .use(addClassToParagraphs)
  .use(rehypeMinify)
  .use(stringify);

const html = await processor.process('<div><p>Content</p></div>');
console.log(String(html));

Интеграция с Remark

Remark и Rehype можно комбинировать через remark-rehype, что позволяет обрабатывать Markdown и сразу преобразовывать его в HTML с полным контролем над AST. Такой подход дает возможность:

  • Добавлять кастомные стили и атрибуты к HTML, сгенерированному из Markdown.
  • Выполнять линтинг и оптимизацию HTML перед финальным рендером.
  • Обрабатывать встроенный HTML в Markdown с использованием Rehype-плагинов.

Пример связки Markdown → HTML:

import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';

const pipeline = unified()
  .use(remarkParse)
  .use(remarkRehype)
  .use(addClassToParagraphs)
  .use(stringify);

const output = await pipeline.process('# Заголовок\n\nПараграф');
console.log(String(output));

Оптимизация работы pipeline

  • Минимизация AST-трансформаций: объединять мелкие плагины в один, чтобы уменьшить количество обходов дерева.
  • Фильтрация узлов: использовать точечные условия для работы только с нужными элементами.
  • Асинхронные плагины: для операций, требующих чтения файлов или сетевых запросов, поддерживается асинхронная обработка.

Pipeline в Remark/Rehype обеспечивает гибкую и мощную систему для автоматизированной обработки HTML и Markdown. Архитектура на основе AST позволяет контролировать каждый элемент документа и комбинировать многочисленные преобразования в единую последовательность операций.