Эта история изначально была опубликована здесь.
Эта статья основана на ESLint v8.28.0.
ESLint — это инструмент линтинга по умолчанию в экосистеме JavaScript/TypeScript. ESLint постоянно запускает набор правил для обнаружения проблем и, в зависимости от правила, позволяет автоматически исправить проблему. Эти правила можно импортировать из других проектов или расширить в соответствии с вашими потребностями. В какой-то момент у вас может возникнуть случай, который не покрывается одним из уже существующих плагинов ESLint, тогда вам придется написать свой собственный плагин.
Эта статья о том, как вы можете написать свой собственный плагин для ESLint. Прежде чем начать, ознакомьтесь с кратким обзором — что такое линтинг.
Написание пользовательского правила ESLint
Чтобы использовать пользовательское правило в ESLint, вам нужно написать подключаемый модуль ESLint. Прежде чем приступить к написанию собственного плагина, проверьте уже существующие здесь. ESLint предлагает гибкую архитектуру для плагинов и полностью подключается. Парсер и правила являются подключаемыми, это означает, что вы можете настроить их под свои нужды. Если вы хотите использовать TypeScript или JavaScript или использовать различные плагины для именования функций и т. д. Возможности безграничны.
Прежде чем приступить к написанию пользовательского правила, мы должны понять, как работает ESLint и как мы можем проверить, работает ли правило. Любой линтер, TSLint или ESLint — это, по сути, базовый статический анализатор кода, он проверяет ваш исходный код на программные и стилистические ошибки (неправильный отступ, имена переменных и т. д.). ESLint использует AST (абстрактное синтаксическое дерево) для оценки шаблонов в коде. AST (Abstract Syntax Tree) используется для описания определенного синтаксического шаблона в вашем коде, см. пример AST ниже.
Итак, по сути, нам нужно найти узел нашего кода, который мы хотим проверить в AST, и вернуть его в ESLint. Следовательно, у нас есть план.
Три шага для создания пользовательского правила ESLint
- Создайте определение правила в проводнике AST
- Создать модуль с пользовательским правилом
- Импортировать пользовательский модуль в ESLint
1. Создайте пользовательское правило в проводнике AST
В демонстрационных целях мы напишем простое правило. Мы хотим запретить переменную с именем pizza
, isPizza
или любой другой комбинацией.
Открываем вкладку браузера и переходим в АСТ. Теперь нам нужно настроить парсер и преобразователь. В зависимости от конфигурации вашего проекта ESLint вам необходимо выбрать парсер, например @typescript-eslint/parser
, если вы используете typescript и используете этот парсер. Используйте параметр ESLint v8
в transform, так как мы не хотим использовать TypeScript в нашем правиле ESLint. Теперь у вас будет четыре окна вместо двух.
Верхний левый — это код для анализа, верхний правый — абстрактное синтаксическое дерево, нижний левый — определение вашего правила, а нижний правый — вывод правила.
Теперь давайте изучим AST, чтобы найти name: "pizza"
. Это свойство мы хотим проверить. Давайте консоль зарегистрируем это.
Скопируйте код в левом нижнем углу определения правила и откройте консоль инструментов разработчика. Результат должен быть пицца.
module.exports = {
create(context) {
return {
Identifier(node) {
console.log(node.name);
},
};
},
};
Теперь нам просто нужно проверить, является ли имя пиццей.
module.exports = {
create(context) {
return {
Identifier(node) {
if (node.name.toLowerCase() === 'pizza') {
console.log(
`Nope, the variable name '${node.name}' is reserved`,
);
} else {
console.log(`'${node.name}' is an amazing variable name`);
}
},
};
},
};
Теперь давайте добавим больше тестовых случаев, чтобы проверить правильность нашего кода. Скопируйте и вставьте код в верхнее левое окно.
const pizza = 'yummy';
const isPizza = true;
const pizzaSize = 'large';
Вывод в консоли должен быть ... is an amazing variable name
для isPizza
и pizzaSize
. Отлично. Мы определили шаблон, который нарушает наше пользовательское правило.
Чтобы сообщить о нарушении правила, мы должны использовать context.report()
, см. ESLint docs. Он публикует предупреждение или ошибку в зависимости от используемой конфигурации. Объект, принятый context.report()
, имеет обязательное свойство message
, которое содержит сообщение, о котором будет сообщено.
Теперь давайте расширим код.
module.exports = {
create(context) {
return {
Identifier(node) {
if (node.name.toLowerCase() === 'pizza') {
return context.report({
node,
message: 'Nope, the variable name "pizza" is reserved',
});
}
return null;
},
};
},
};
Вывод (внизу справа) должен быть примерно таким:
// Nope, the variable name "pizza" is reserved (at 1:7)
const pizza = 'yummy';
// ------^
// ...
Наше определение правила завершено. Кроме того, метод context.report()
также имеет необязательное свойство fix
, которое позволит нам определить функцию, применяющую исправление нарушения правила. Впрочем, об этом будет рассказано в другом посте в блоге. 😀
2. Создайте модуль с пользовательским правилом
Создайте проект с соответствующими папками и файлами и инициализируйте с помощью npm init -y
.
mkdir eslint-custom-rules
cd eslint-custom-rules
npm init -y
touch index.js
mkdir rules
cd rules
touch pizza-reserved.js
Это понадобится нам позже, чтобы загрузить модуль или импортировать его в наш проект.
Добавьте определение правила в файл pizza-reserved.js
.
module.exports = {
create(context) {
return {
Identifier(node) {
if (node.name.toLowerCase() === 'pizza') {
return context.report({
node,
message: 'Nope, the variable name "pizza" is reserved',
});
}
return null;
},
};
},
};
Существуют ограничения на имена для создания пользовательских правил eslint. Допускаются следующие форматы, где plugin-name
и scope
можно настроить:
- eslint-плагин-
plugin-name
- @
scope
/eslint-plugin-plugin-name
- @
scope
/eslint-плагин
В этом примере мы выбираем eslint-plugin-pizza-reserved
для модуля npm.
Мы должны обновить package.json
в нашем файле index.js
с именем eslint-plugin-pizza-reserved
.
Package.json должен выглядеть так:
{
"name": "eslint-plugin-pizza-reserved",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Теперь мы обновляем наши файлы index.js
, чтобы экспортировать правила.
module.exports = {
rules: {
'pizza-reserved': require('./rules/pizza-reserved'),
},
};
Теперь у нас есть работающее пользовательское правило eslint. Теперь мы можем опубликовать его в npm или использовать только локально в нашем проекте.
3. Импортируйте пользовательский модуль в ESLint
Импорт пользовательского правила в вашу конфигурацию ESLint зависит от того, опубликовали ли вы правило или хотите использовать его локально.
Если вы используете правило ESLint локально в своем проекте, вы можете просто расширить свой package.json devDependencies с помощью "<plugin-name>": "file:path/to/entrypoint"
.
Структура папок в этом примере:
.
├── eslint-custom-rules # Custom ESLint rules
| ├── rules
| | └── pizza-reserved.js
| └── index.js
|
└── my-project # Project folder, where we want to use custom rules
├── src # Source files
├── test # Automated tests
├── .eslintrc.js # Automated tests
├── ... # Automated tests
└── README.md
Следовательно, используйте "eslint-plugin-custom-rules": "file:eslint-custom-rules"
, чтобы добавить свой собственный плагин eslint в package.json, и запустите npm i
, чтобы установить его.
Последним шагом будет расширение конфигурации ESLint.
module.exports = {
plugins: [
'custom-rules',
// other plugins
],
rules: {
// other configs
'custom-rules/pizza-reserved': 'warn',
},
};
Вот и все. Вы написали пользовательское правило ESLint. Поздравляем.
TL;DR
- Чтобы создать собственное правило ESLint, вам необходимо создать собственный подключаемый модуль ESLint.
- Сначала вы должны определить определение правила с помощью проводника AST.
- Затем вам нужно создать модуль NPM с пользовательским правилом
- Наконец, вам нужно установить пользовательский модуль в свой проект и добавить его в конфигурацию ESLint.
Спасибо за внимание. Если у вас есть вопросы, используйте функцию комментариев или отправьте мне сообщение @mariokandut . Если вы хотите узнать больше о typescript, ознакомьтесь с этими Учебными пособиями по Typescript.
Рекомендации (и большое спасибо): ESLint, Darragh ORiordan, Carrie Reid-Knox, MEWS — Дарья