Хук preprocess

Хук preprocess в Marked позволяет вмешиваться в процесс обработки Markdown до того, как библиотека начнет разбирать текст. Это мощный инструмент для модификации исходного Markdown, добавления собственных директив или выполнения любых подготовительных трансформаций. Он принимает текстовую строку Markdown и возвращает новую строку, которая будет передана на разбор.

Сигнатура и подключение

Хук задается через объект опций при инициализации Marked:

import { marked } from 'marked';

marked.use({
  hooks: {
    preprocess(markdown) {
      // возвращает модифицированный markdown
      return markdown;
    }
  }
});

Параметры:

  • markdown — исходная строка Markdown.
  • Возвращаемое значение должно быть строкой. Любое другое значение будет проигнорировано.

Основные сценарии использования

  1. Массовое исправление текста

    Часто требуется автоматически исправить или заменить определенные конструкции Markdown до его обработки. Например, замена всех фигурных скобок на квадратные для совместимости с внутренними конвенциями:

    marked.use({
      hooks: {
        preprocess(md) {
          return md.replace(/\{(.*?)\}/g, '[$1]');
        }
      }
    });

    В результате все вхождения {текст} будут заменены на [текст] перед разбором.

  2. Добавление кастомных директив

    Можно реализовать собственные макросы или плейсхолдеры. Например, вставка текущей даты:

    marked.use({
      hooks: {
        preprocess(md) {
          return md.replace(/\{\{DATE\}\}/g, new Date().toLocaleDateString());
        }
      }
    });

    Любая встречающаяся конструкция {{DATE}} заменяется на актуальную дату в момент парсинга.

  3. Фильтрация или удаление контента

    Для удаления определенных блоков Markdown можно использовать регулярные выражения или более сложную логику:

    marked.use({
      hooks: {
        preprocess(md) {
          // удаляем все HTML-комментарии
          return md.replace(/<!--[\s\S]*?-->/g, '');
        }
      }
    });

    Это позволяет предотвратить появление нежелательных элементов в финальном HTML.

Взаимодействие с другими хуками

preprocess всегда вызывается перед всеми остальными хуками, такими как tokenizer, renderer или walkTokens. Это делает его идеальным местом для любых изменений исходного Markdown, на которые должны опираться последующие этапы обработки.

Важно учитывать порядок применения хуков:

  1. preprocess — изменение исходного Markdown.
  2. tokenizer — создание токенов на основе модифицированного Markdown.
  3. walkTokens — обход токенов для дополнительных трансформаций.
  4. renderer — генерация итогового HTML.

Примеры продвинутого использования

  • Поддержка кастомных синтаксисов

    marked.use({
      hooks: {
        preprocess(md) {
          // конвертируем @username в ссылку на профиль
          return md.replace(/@(\w+)/g, '[@$1](https://example.com/users/$1)');
        }
      }
    });

    Все упоминания @username автоматически превращаются в ссылки.

  • Динамическая локализация текста

    const translations = {
      hello: 'Привет',
      bye: 'Пока'
    };
    
    marked.use({
      hooks: {
        preprocess(md) {
          return md.replace(/\{\{(\w+)\}\}/g, (_, key) => translations[key] || key);
        }
      }
    });

    Конструкции {{hello}} заменяются на перевод, заданный в объекте translations.

Практические рекомендации

  • Хук preprocess должен быть максимально быстрым. Все операции выполняются синхронно перед токенизацией, поэтому тяжелые вычисления могут замедлить разбор Markdown.
  • Использовать регулярные выражения с осторожностью. Сложные паттерны могут нарушить разбор, если изменяют структуру Markdown некорректно.
  • Всегда возвращать строку. Любое значение, отличное от строки, не будет обработано библиотекой.

Отличие от walkTokens и tokenizer

  • preprocess работает до разборa, поэтому полезен для модификации исходного текста.
  • tokenizer работает на этапе создания токенов, позволяя создавать новые типы токенов.
  • walkTokens обход токенов после токенизации, удобен для изменения контента без изменения исходного Markdown.

Заключение по функциональности

preprocess — это универсальный инструмент для подготовки Markdown к разбору: исправление текста, внедрение динамического контента, поддержка макросов и фильтрация нежелательных элементов. Его сила заключается в возможности изменять исходный Markdown до того, как библиотека Marked создаст токены и сгенерирует HTML, что делает его ключевым хуком при кастомизации обработки Markdown.