Spec-Zone.ru › ESLint

Пользовательские форматтеры

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

В ESLint также есть встроенные форматтеры, которые можно использовать.

Вы можете включить пользовательские форматтеры непосредственно в свой проект или создать npm-пакет для их отдельного распространения.

Создание пользовательского форматтера

Каждый форматтер — это функция, которая получает объект results и context в качестве аргументов и возвращает строку. Например, так реализован встроенный JSON-форматтер:

//my-awesome-formatter.js
module.exports = function (results, context) {
	return JSON.stringify(results, null, 2);
};

Форматтер также может быть асинхронной функцией (начиная с ESLint v8.4.0). Ниже приведён простой пример:

//my-awesome-formatter.js
module.exports = async function (results) {
	const formatted = await asyncTask();
	return formatted;
};

Чтобы запустить ESLint с этим форматтером, используйте флаг командной строки -f (или --format). Путь к локально определённому пользовательскому форматтеру должен начинаться с точки (.), например ./my-awesome-formatter.js или ../formatters/my-awesome-formatter.js.

eslint -f ./my-awesome-formatter.js src/

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

Аргумент results

Объект results, передаваемый форматтеру, представляет собой массив объектов LintResult, содержащих результаты проверки отдельных файлов. Вот пример вывода:

[
	{
		filePath: "/path/to/a/file.js",
		messages: [
			{
				ruleId: "curly",
				severity: 2,
				message: "Expected { after 'if' condition.",
				line: 2,
				column: 1,
			},
			{
				ruleId: "no-process-exit",
				severity: 2,
				message: "Don't use process.exit(); throw an error instead.",
				line: 3,
				column: 1,
			},
		],
		errorCount: 2,
		warningCount: 0,
		fixableErrorCount: 0,
		fixableWarningCount: 0,
		source: "var err = doStuff();\nif (err) console.log('failed tests: ' + err);\nprocess.exit(1);\n",
	},
	{
		filePath: "/path/to/Gruntfile.js",
		messages: [],
		errorCount: 0,
		warningCount: 0,
		fixableErrorCount: 0,
		fixableWarningCount: 0,
	},
];

Аргумент context

Функция форматтера получает объект context в качестве второго аргумента. У объекта есть следующие свойства:

  • color (необязательно): если задано --color, значение этого свойства — true. Если задано --no-color, значение — false. Если не задан ни один из параметров, это свойство отсутствует.
  • cwd: текущий рабочий каталог. Это значение передаётся через параметр конструктора cwd класса ESLint.
  • maxWarningsExceeded (необязательно): если задано --max-warnings и количество предупреждений превысило лимит, значение этого свойства представляет собой объект с двумя свойствами:
    • maxWarnings: значение параметра --max-warnings
    • foundWarnings: количество предупреждений проверки
  • rulesMeta: значения свойства meta правил. Дополнительную информацию о правилах см. на странице Пользовательские правила.

Например, вот как выглядел бы этот объект, если бы было запущено правило no-extra-semi:

{
    cwd: "/path/to/cwd",
    maxWarningsExceeded: {
        maxWarnings: 5,
        foundWarnings: 6
    },
    rulesMeta: {
        "no-extra-semi": {
            type: "suggestion",
            docs: {
                description: "disallow unnecessary semicolons",
                recommended: true,
                url: "https://eslint.org/docs/rules/no-extra-semi"
            },
            fixable: "code",
            schema: [],
            messages: {
                unexpected: "Unnecessary semicolon."
            }
        }
    },
}

Примечание: если проверка выполняется устаревшим классом CLIEngine, аргумент context может иметь другое значение, поскольку оно определяется пользователями API. Если вы хотите поддерживать устаревшие среды, проверьте, является ли аргумент context ожидаемым значением.

Передача аргументов форматтерам

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

Использование переменных среды

Пользовательские форматтеры имеют доступ к переменным среды и поэтому могут изменять своё поведение в зависимости от их значений.

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

module.exports = function (results) {
	var skipWarnings = process.env.FORMATTER_SKIP_WARNINGS === "true";

	var results = results || [];
	var summary = results.reduce(
		function (seq, current) {
			current.messages.forEach(function (msg) {
				var logMessage = {
					filePath: current.filePath,
					ruleId: msg.ruleId,
					message: msg.message,
					line: msg.line,
					column: msg.column,
				};

				if (msg.severity === 1) {
					logMessage.type = "warning";
					seq.warnings.push(logMessage);
				}
				if (msg.severity === 2) {
					logMessage.type = "error";
					seq.errors.push(logMessage);
				}
			});
			return seq;
		},
		{
			errors: [],
			warnings: [],
		},
	);

	if (summary.errors.length > 0 || summary.warnings.length > 0) {
		var warnings = !skipWarnings ? summary.warnings : []; // skip the warnings in that case

		var lines = summary.errors
			.concat(warnings)
			.map(function (msg) {
				return (
					"\n" +
					msg.type +
					" " +
					msg.ruleId +
					"\n  " +
					msg.filePath +
					":" +
					msg.line +
					":" +
					msg.column
				);
			})
			.join("\n");

		return lines + "\n";
	}
};

Запустите ESLint с этим пользовательским форматтером и задайте переменную среды следующим образом:

FORMATTER_SKIP_WARNINGS=true eslint -f ./my-awesome-formatter.js src/

Результат будет таким:

error space-infix-ops
  src/configs/bundler.js:6:8

error semi
  src/configs/bundler.js:6:10

Передача сложных аргументов

Если шаблон пользовательского форматтера не предоставляет достаточно возможностей для желаемого форматирования результатов ESLint, лучше всего воспользоваться встроенным JSON-форматтером ESLint и передать его вывод другой программе. Например:

eslint -f json src/ | your-program-that-reads-JSON --option

В этом примере программа your-program-that-reads-json может принять необработанный JSON с результатами ESLint, обработать его и вывести результаты в собственном формате. Для настройки вывода можно передать этой программе любое необходимое количество аргументов командной строки.

Форматирование для терминалов

Современные терминалы, такие как iTerm2 или Guake, ожидают определённый формат результатов, чтобы автоматически открывать файлы при нажатии на их имена. Большинство терминалов поддерживает для этого следующий формат:

file:line:column

Упаковка пользовательского форматтера

Пользовательские форматтеры можно распространять через npm-пакеты. Для этого создайте npm-пакет с именем формата eslint-formatter-*, где * — имя вашего форматтера (например, eslint-formatter-awesome). Затем проектам следует установить пакет и использовать пользовательский форматтер с флагом -f (или --format), как показано ниже:

eslint -f awesome src/

Поскольку ESLint ищет пакеты, начинающиеся с eslint-formatter-, если указанный форматтер не начинается с точки, при использовании упакованного пользовательского форматтера вводить eslint-formatter- не нужно.

Советы по package.json пользовательского форматтера:

  • Точкой входа main должен быть файл JavaScript, реализующий ваш пользовательский форматтер.
  • Добавьте следующие keywords, чтобы пользователи могли найти ваш форматтер:
    • "eslint"
    • "eslint-formatter"
    • "eslintformatter"

См. все пользовательские форматтеры на npm.

Примеры

Форматтер сводки

Форматтер, который сообщает только об общем количестве ошибок и предупреждений, будет выглядеть так:

module.exports = function (results, context) {
	// accumulate the errors and warnings
	var summary = results.reduce(
		function (seq, current) {
			seq.errors += current.errorCount;
			seq.warnings += current.warningCount;
			return seq;
		},
		{ errors: 0, warnings: 0 },
	);

	if (summary.errors > 0 || summary.warnings > 0) {
		return (
			"Errors: " +
			summary.errors +
			", Warnings: " +
			summary.warnings +
			"\n"
		);
	}

	return "";
};

Запустите eslint с приведённым выше форматтером сводки:

eslint -f ./my-awesome-formatter.js src/

В результате будет выведено:

Errors: 2, Warnings: 4

Подробный форматтер

Более сложный отчёт может выглядеть так:

module.exports = function (results, context) {
	var results = results || [];

	var summary = results.reduce(
		function (seq, current) {
			current.messages.forEach(function (msg) {
				var logMessage = {
					filePath: current.filePath,
					ruleId: msg.ruleId,
					ruleUrl: context.rulesMeta[msg.ruleId].docs.url,
					message: msg.message,
					line: msg.line,
					column: msg.column,
				};

				if (msg.severity === 1) {
					logMessage.type = "warning";
					seq.warnings.push(logMessage);
				}
				if (msg.severity === 2) {
					logMessage.type = "error";
					seq.errors.push(logMessage);
				}
			});
			return seq;
		},
		{
			errors: [],
			warnings: [],
		},
	);

	if (summary.errors.length > 0 || summary.warnings.length > 0) {
		var lines = summary.errors
			.concat(summary.warnings)
			.map(function (msg) {
				return (
					"\n" +
					msg.type +
					" " +
					msg.ruleId +
					(msg.ruleUrl ? " (" + msg.ruleUrl + ")" : "") +
					"\n  " +
					msg.filePath +
					":" +
					msg.line +
					":" +
					msg.column
				);
			})
			.join("\n");

		return lines + "\n";
	}
};

При запуске ESLint с этим пользовательским форматтером:

eslint -f ./my-awesome-formatter.js src/

Вывод будет таким:

error space-infix-ops (https://eslint.org/docs/rules/space-infix-ops)
  src/configs/bundler.js:6:8
error semi (https://eslint.org/docs/rules/semi)
  src/configs/bundler.js:6:10
warning no-unused-vars (https://eslint.org/docs/rules/no-unused-vars)
  src/configs/bundler.js:5:6
warning no-unused-vars (https://eslint.org/docs/rules/no-unused-vars)
  src/configs/bundler.js:6:6
warning no-shadow (https://eslint.org/docs/rules/no-shadow)
  src/configs/bundler.js:65:32
warning no-unused-vars (https://eslint.org/docs/rules/no-unused-vars)
  src/configs/clean.js:3:6

© OpenJS Foundation and other contributors
Licensed under the MIT License.
https://eslint.org/docs/latest/extend/custom-formatters

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API