Сбор и отображение warning'ов

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

Типы предупреждений

Remark формирует предупреждения при обработке Markdown, например:

  • Неправильная структура заголовков — если уровень заголовков скачет, минуя промежуточный уровень.
  • Некорректные ссылки — когда ссылка ведёт на несуществующий якорь или внешний ресурс недоступен.
  • Ошибки синтаксиса Markdown — не закрытые блоки кода, неверно оформленные списки.

Rehype генерирует предупреждения при обработке HTML или при трансформации AST (Abstract Syntax Tree):

  • Невалидный HTML — теги без закрывающего элемента, неправильное вложение элементов.
  • Проблемы с атрибутами — атрибуты, не поддерживаемые стандартом или плагином.
  • Конфликты между плагинами — если один плагин изменяет структуру, а другой ожидает исходную форму.

Сбор предупреждений

Для сбора предупреждений используется объект VFile, который является центральной структурой для всех плагинов Remark и Rehype. Каждое предупреждение добавляется с помощью метода message():

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import { VFile } from 'vfile';

const file = new VFile({ path: 'example.md', value: '# Заголовок\nТекст' });

file.message('Некорректный заголовок', { line: 1, column: 1 });

console.log(file.messages);

Ключевые параметры message():

  • reason — текст сообщения.
  • position — объект с указанием строки и столбца.
  • fatal — если true, обработка должна завершиться ошибкой.

Встроенные механизмы предупреждений в плагины

Многие плагины Remark/Rehype автоматически формируют предупреждения. Например:

import remarkLint from 'remark-lint';
import remarkPresetLintRecommended from 'remark-preset-lint-recommended';

const processor = unified()
  .use(remarkParse)
  .use(remarkLint)
  .use(remarkPresetLintRecommended);

const file = await processor.process('# Заголовок\n\n\nТекст');

file.messages.forEach(msg => {
  console.log(msg.reason, msg.position);
});

В этом примере remark-lint собирает предупреждения о несоблюдении правил стиля и структуры документа.

Настройка уровня и фильтрация предупреждений

VFile позволяет фильтровать предупреждения по степени важности:

const warnings = file.messages.filter(msg => !msg.fatal);
const errors = file.messages.filter(msg => msg.fatal);

Можно также реализовать кастомный логгер:

file.messages.forEach(msg => {
  const { reason, position, fatal } = msg;
  if (fatal) {
    console.error(`Ошибка: ${reason} (${position.start.line}:${position.start.column})`);
  } else {
    console.warn(`Предупреждение: ${reason} (${position.start.line}:${position.start.column})`);
  }
});

Отображение предупреждений в удобной форме

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

import fs from 'fs';

const text = fs.readFileSync('example.md', 'utf-8');

file.messages.forEach(msg => {
  const { line, column } = msg.position.start;
  const lineContent = text.split('\n')[line - 1];
  console.log(`${line}:${column} ${msg.fatal ? 'Ошибка' : 'Предупреждение'}: ${msg.reason}`);
  console.log(`> ${lineContent}`);
});

Такой подход позволяет быстро локализовать проблемные участки и интегрировать обработку предупреждений в CI/CD пайплайны.

Расширенные возможности

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

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

  • Всегда использовать VFile как центральный объект для хранения и отображения предупреждений.
  • Настраивать фильтрацию по fatal и source для различения ошибок и предупреждений плагинов.
  • Интегрировать сбор предупреждений в автоматизированные проверки для поддержания качества Markdown и HTML-контента.

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