Применение процессора к типам файлов

Процессор в ESLint представляет собой механизм предварительной обработки файлов, позволяющий преобразовывать исходный текст в набор виртуальных JavaScript-фрагментов, которые затем проходят стандартный цикл линтинга. Такая модель необходима в ситуациях, когда исходный файл содержит не чистый JavaScript, а смешанный или контейнерный формат.

Ключевая задача процессора заключается в двух этапах:

  • preprocess — разбиение входного файла на фрагменты, пригодные для анализа ESLint
  • postprocess — объединение и нормализация результатов анализа обратно в контекст исходного файла

Таким образом ESLint получает возможность анализировать структуры, которые формально не являются JavaScript-файлами, но содержат JS-код внутри.


Применение процессоров к типам файлов

Сопоставление процессоров с типами файлов строится через конфигурацию ESLint и механизм выбора правил по расширению или шаблону пути.

Основной принцип:

  • тип файла определяется по маске (*.md, *.vue, *.html)
  • для каждой группы файлов назначается соответствующий процессор
  • процессор трансформирует содержимое в набор JS-код-блоков

Такой подход позволяет единообразно применять правила ESLint к разнородным источникам кода.


Логика обработки файлов внутри ESLint

При запуске анализа ESLint выполняет несколько стадий:

  1. Определение набора файлов через glob-паттерны
  2. Сопоставление каждого файла конфигурации (rules, parser, processor)
  3. При наличии процессора — запуск preprocess
  4. Линтинг полученных виртуальных блоков как обычного JavaScript
  5. Запуск postprocess для агрегации результатов

Важно, что ESLint не «понимает» структуру контейнерных файлов без процессора — он работает только с уже извлечённым JavaScript.


Применение через legacy-конфигурацию (overrides)

В классической конфигурации ESLint (eslintrc) процессоры применяются через поле processor внутри overrides.

Принцип работы:

  • каждый override привязывается к набору файлов
  • для этих файлов назначается процессор
  • процессор может быть строкой (из плагина) или функцией

Пример логики конфигурации:

  • *.md → markdown-процессор
  • *.vue → vue-процессор
  • *.html → html-процессор

Важный момент: процессор всегда применяется на уровне файла, а не отдельного правила.


Flat config и современный способ подключения процессоров

В flat-конфигурации ESLint (используемой в новых версиях) процессоры задаются напрямую в объекте конфигурации через поле processor.

Структура:

  • конфигурация описывает массив объектов
  • каждый объект содержит files и processor
  • процессор может быть функцией или ссылкой на плагин

Это устраняет необходимость в overrides и делает конфигурацию более линейной.

Особенность flat-конфигурации:

  • порядок объектов имеет значение
  • более специфичные правила перекрывают общие
  • процессор применяется до выполнения правил

Внутренний механизм preprocess и postprocess

preprocess

Функция preprocess получает на вход:

  • содержимое файла
  • путь к файлу

Результатом является массив виртуальных файлов:

  • каждый элемент — строка JavaScript-кода
  • каждому фрагменту присваивается виртуальное имя

Пример логики:

  • извлечь <script> блоки из HTML
  • извлечь fenced code blocks из Markdown
  • извлечь <script> из Vue SFC

postprocess

После линтинга всех виртуальных блоков ESLint возвращает результаты в виде массива сообщений. Postprocess:

  • агрегирует ошибки из всех виртуальных файлов
  • привязывает их к исходному файлу
  • корректирует позиции (line/column mapping)

Без этого шага результаты были бы разрозненными и непривязанными к оригинальному документу.


Применение процессоров к различным типам файлов

Markdown

Markdown-файлы часто содержат JavaScript внутри блоков:

# Example

```js
const a = 1;
console.log(a);

Процессор:

- находит fenced code blocks
- извлекает содержимое JavaScript
- передаёт его ESLint как отдельные виртуальные файлы

Результат: ESLint анализирует только кодовые секции, игнорируя текст.

---

### Vue Single File Components

Vue-файлы содержат несколько секций:

- `<template>`
- `<script>`
- `<style>`

Процессор для Vue:

- извлекает `<script>` как JS или TS
- при необходимости преобразует Composition API
- связывает ошибки с оригинальными строками `.vue`

Особенность:

- один файл превращается в несколько виртуальных модулей
- линтинг происходит только для JS-части

---

### HTML

HTML может содержать встроенные скрипты:

```html
<script>
  const x = 10;
</script>

HTML-процессор:

  • извлекает содержимое <script>
  • может учитывать type="module"
  • игнорирует inline-атрибуты (если не предусмотрено иначе)

Создание собственного процессора

Процессор реализуется как объект с методами:

  • preprocess
  • postprocess
  • supportsAutofix (опционально)

Структура preprocess

function preprocess(text, filename) {
  return [
    { text: extractedCode, filename: filename + '#block1' }
  ];
}

Функция может:

  • разбивать файл на множество частей
  • нормализовать код
  • удалять не-JS контент

Структура postprocess

function postprocess(messages, filename) {
  return messages.flat();
}

Основная задача — восстановление контекста и корректировка позиций.


Сопоставление процессоров с расширениями файлов

ESLint не использует напрямую таблицу расширений для процессоров. Вместо этого применяется комбинация:

  • glob-паттернов (files)
  • конфигурационных блоков
  • плагинных процессоров

Типичная схема:

  • *.md → markdown processor
  • *.vue → vue processor
  • *.html → html processor

Фактическое сопоставление происходит на этапе разрешения конфигурации.


Ограничения и особенности поведения

Процессоры в ESLint имеют ряд архитектурных ограничений:

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

Дополнительная сложность возникает при:

  • вложенных языках (HTML внутри Markdown)
  • многоуровневых трансформациях
  • генерации виртуальных файлов без стабильных позиций

Расширенные сценарии применения

В сложных проектах процессоры используются для:

  • анализа документации с встроенными примерами кода
  • линтинга UI-компонентов в шаблонных файлах
  • проверки конфигурационных DSL с JavaScript-вставками
  • обработки генеративных файлов, содержащих смешанные языки

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