Руководство по созданию пользовательского правила
В этом руководстве рассказывается, как создать пользовательское правило для ESLint и распространять его с помощью плагина.
Вы можете создавать пользовательские правила, чтобы проверять, соответствует ли ваш код определённым требованиям, и определять, что делать, если он им не соответствует. Плагины объединяют пользовательские правила и другие настройки, позволяя легко делиться ими и повторно использовать их в разных проектах.
Подробнее о пользовательских правилах и плагинах читайте в следующей документации:
Зачем создавать пользовательское правило?
Создайте пользовательское правило, если встроенные правила ESLint и опубликованные сообществом пользовательские правила не отвечают вашим потребностям. Вы можете создать пользовательское правило, чтобы обеспечить соблюдение передовой практики в вашей компании или проекте, предотвратить повторное возникновение определённой ошибки или гарантировать соответствие руководству по стилю.
Прежде чем создавать пользовательское правило, не предназначенное специально для вашей компании или проекта, стоит поискать в интернете, не опубликовал ли кто-нибудь плагин с пользовательским правилом, решающим вашу задачу. Возможно, такое правило уже существует.
Предварительные требования
Прежде чем начать, убедитесь, что в вашей среде разработки установлены следующие компоненты:
Также предполагается, что вы обладаете базовыми знаниями об ESLint и правилах ESLint.
Пользовательское правило
Пользовательское правило из этого руководства требует, чтобы всем переменным const с именем foo присваивался строковый литерал "bar". Правило определено в файле enforce-foo-bar.js. Оно также предлагает заменить любое другое значение, присвоенное const foo, на "bar".
Например, предположим, что у вас есть следующий файл foo.js:
// foo.js
const foo = "baz123";
При запуске ESLint с этим правилом значение "baz123" будет отмечено как недопустимое для переменной foo. Если ESLint запущен в режиме автоматического исправления, он изменит файл следующим образом:
// foo.js
const foo = "bar";
Шаг 1. Настройте проект
Сначала создайте новый проект для пользовательского правила. Создайте каталог, инициализируйте в нём новый проект npm и создайте файл для пользовательского правила:
mkdir eslint-custom-rule-example # create directory
cd eslint-custom-rule-example # enter the directory
npm init -y # init new npm project
touch enforce-foo-bar.js # create file enforce-foo-bar.js
Шаг 2. Создайте заготовку файла правила
Добавьте в файл enforce-foo-bar.js каркас пользовательского правила enforce-foo-bar. Также добавьте объект meta с основной информацией о правиле.
// enforce-foo-bar.js
module.exports = {
meta: {
// TODO: add metadata
},
create(context) {
return {
// TODO: add callback function(s)
};
},
};
Шаг 3. Добавьте метаданные правила
Прежде чем писать правило, добавьте метаданные в объект правила. ESLint использует эту информацию при запуске правила.
Для начала экспортируйте объект со свойством meta, содержащим метаданные правила, такие как тип правила, документация и возможность исправления. В данном случае тип правила — «problem», описание — «Требует, чтобы переменной с именем foo можно было присвоить только значение ‘bar’.», а правило можно исправить, изменив код.
Поскольку это правило предназначено для JavaScript, мы также добавим languages: ["js/js"], чтобы указать, что оно применяется только к встроенному языку JavaScript. ESLint выдаст ошибку, если это правило будет включено для языка, отличного от JavaScript.
// enforce-foo-bar.js
module.exports = {
meta: {
type: "problem",
docs: {
description:
"Enforce that a variable named `foo` can only be assigned a value of 'bar'.",
},
fixable: "code",
schema: [],
languages: ["js/js"],
},
create(context) {
return {
// TODO: add callback function(s)
};
},
};
Подробнее о метаданных правил см. в разделе Структура правила.
Шаг 4. Добавьте методы-обработчики правила
Определите функцию create правила. Она принимает объект context и возвращает объект со свойством для каждого типа синтаксического узла, который нужно обрабатывать. В данном случае нужно обрабатывать узлы VariableDeclarator. Можно выбрать любой тип узла ESTree или селектор.
В методе-обработчике VariableDeclarator проверьте, представляет ли узел объявление переменной const, имеет ли её имя значение foo и не присвоена ли ей строка "bar". Для этого нужно проверить node, переданный методу VariableDeclaration.
Если объявлению const foo присвоено значение "bar", правило ничего не делает. Если переменной const foo не присвоено значение "bar", тогда context.report() сообщает ESLint об ошибке. Отчёт об ошибке содержит сведения об ошибке и способе её исправления.
// enforce-foo-bar.js
module.exports = {
meta: {
type: "problem",
docs: {
description: "Enforce that a variable named `foo` can only be assigned a value of 'bar'."
},
fixable: "code",
schema: [],
languages: ["js/js"]
},
create(context) {
return {
// Performs action in the function on every variable declarator
VariableDeclarator(node) {
// Check if a `const` variable declaration
if (node.parent.kind === "const") {
// Check if variable name is `foo`
if (node.id.type === "Identifier" && node.id.name === "foo") {
// Check if value of variable is "bar"
if (node.init && node.init.type === "Literal" && node.init.value !== "bar") {
/*
* Report error to ESLint. Error message uses
* a message placeholder to include the incorrect value
* in the error message.
* Also includes a `fix(fixer)` function that replaces
* any values assigned to `const foo` with "bar".
*/
context.report({
node,
message: 'Value other than "bar" assigned to `const foo`. Unexpected value: {{ notBar }}.',
data: {
notBar: node.init.value
},
fix(fixer) {
return fixer.replaceText(node.init, '"bar"');
}
});
}
}
}
}
};
}
};
Шаг 5. Настройте тестирование
После написания правила можно проверить, работает ли оно ожидаемым образом.
В ESLint есть встроенный класс RuleTester для тестирования правил. Для тестирования правил ESLint не нужно использовать сторонние библиотеки, но RuleTester без проблем работает с такими инструментами, как Mocha и Jest.
Затем создайте файл для тестов: enforce-foo-bar.test.js:
touch enforce-foo-bar.test.js
В файле тестов будет использоваться пакет eslint. Установите его как зависимость для разработки:
npm
npm install --save-dev eslint
yarn
yarn add --dev eslint
pnpm
pnpm add --save-dev eslint
bun
bun add --dev eslint
Добавьте в файл package.json скрипт для запуска тестов:
// package.json
{
// ...other configuration
"scripts": {
"test": "node enforce-foo-bar.test.js"
},
// ...other configuration
}
Шаг 6. Напишите тест
Чтобы написать тест с помощью RuleTester, импортируйте класс и пользовательское правило в файл enforce-foo-bar.test.js.
Метод RuleTester#run() проверяет правило на корректных и некорректных тестовых случаях. Если правило не пройдёт какой-либо сценарий тестирования, этот метод выдаст ошибку. RuleTester требует наличия как минимум одного корректного и одного некорректного сценария тестирования.
// enforce-foo-bar.test.js
const { RuleTester } = require("eslint");
const fooBarRule = require("./enforce-foo-bar");
const ruleTester = new RuleTester({
// Must use at least ecmaVersion 2015 because
// that's when `const` variables were introduced.
languageOptions: { ecmaVersion: 2015 },
});
// Throws error if the tests in ruleTester.run() do not pass
ruleTester.run(
"enforce-foo-bar", // rule name
fooBarRule, // rule code
{
// checks
// 'valid' checks cases that should pass
valid: [
{
code: "const foo = 'bar';",
},
],
// 'invalid' checks cases that should not pass
invalid: [
{
code: "const foo = 'baz';",
output: 'const foo = "bar";',
errors: 1,
},
],
},
);
console.log("All tests passed!");
Запустите тест следующей командой:
npm test
Если тест пройдёт успешно, в консоли появится следующее сообщение:
All tests passed!
Шаг 7. Добавьте пользовательское правило в плагин
Теперь, когда пользовательское правило написано и проверено, его можно включить в плагин. С помощью плагина можно распространять правило в пакете npm и использовать его в других проектах.
Создайте файл плагина:
touch eslint-plugin-example.js
Теперь напишите код плагина. Плагины представляют собой экспортируемые объекты JavaScript. Чтобы включить правило в плагин, добавьте его в объект rules плагина, содержащий пары «имя правила — исходный код».
Подробнее о создании плагинов см. в разделе Создание плагинов.
// eslint-plugin-example.js
const fooBarRule = require("./enforce-foo-bar");
const plugin = { rules: { "enforce-foo-bar": fooBarRule } };
module.exports = plugin;
Шаг 8. Используйте плагин локально
С помощью локально определённого плагина можно применять пользовательское правило в проекте. Чтобы использовать локальный плагин, укажите путь к нему в свойстве plugins файла конфигурации ESLint.
Локально определённый плагин может пригодиться в следующих случаях:
- Вы хотите протестировать плагин до публикации в npm.
- Вы хотите использовать плагин, но не хотите публиковать его в npm.
Прежде чем добавить плагин в проект, создайте для проекта конфигурацию ESLint с помощью файла плоской конфигурации eslint.config.js:
touch eslint.config.js
Затем добавьте следующий код в eslint.config.js:
// eslint.config.js
"use strict";
// Import the `defineConfig` helper function
const { defineConfig } = require("eslint/config");
// Import the ESLint plugin locally
const eslintPluginExample = require("./eslint-plugin-example");
module.exports = defineConfig([
{
files: ["**/*.js"],
languageOptions: {
sourceType: "commonjs",
ecmaVersion: "latest",
},
// Using the eslint-plugin-example plugin defined locally
plugins: { example: eslintPluginExample },
rules: {
"example/enforce-foo-bar": "error",
},
},
]);
Прежде чем тестировать правило, необходимо создать файл, на котором оно будет проверяться.
Создайте файл example.js:
touch example.js
Добавьте следующий код в example.js:
// example.js
function correctFooBar() {
const foo = "bar";
}
function incorrectFoo() {
const foo = "baz"; // Problem!
}
Теперь можно проверить пользовательское правило с помощью локально определённого плагина.
Запустите ESLint для файла example.js:
npm
npx eslint example.js
yarn
yarn dlx eslint example.js
pnpm
pnpm dlx eslint example.js
bun
bunx eslint example.js
В терминале появится следующий вывод:
/<path-to-directory>/eslint-custom-rule-example/example.js
8:11 error Value other than "bar" assigned to `const foo`. Unexpected value: baz example/enforce-foo-bar
✖ 1 problem (1 error, 0 warnings)
1 error and 0 warnings potentially fixable with the `--fix` option.
Шаг 9. Опубликуйте плагин
Чтобы опубликовать плагин с правилом в npm, необходимо настроить package.json. Заполните соответствующие поля следующим образом:
-
"name": Уникальное имя пакета. В npm не может быть другого пакета с таким же именем. -
"main": Относительный путь к файлу плагина. В данном примере путь —"eslint-plugin-example.js". -
"description": Описание пакета, которое будет отображаться на npm. -
"peerDependencies": Добавьте"eslint": ">=10.0.0"в качестве одноранговой зависимости. Для использования плагина необходима любая версия не ниже указанной. Объявлениеeslintодноранговой зависимостью означает, что пользователи должны добавить пакет в проект отдельно от плагина. -
"keywords": Добавьте стандартные ключевые слова["eslint", "eslintplugin", "eslint-plugin"], чтобы пакет было проще найти. При желании можно также указать другие ключевые слова, относящиеся к плагину.
Полный пример файла package.json плагина с пояснениями:
// package.json
{
// Name npm package.
// Add your own package name. eslint-plugin-example is taken!
"name": "eslint-plugin-example",
"version": "1.0.0",
"description": "ESLint plugin for enforce-foo-bar rule.",
"main": "eslint-plugin-example.js", // plugin entry point
"scripts": {
"test": "node enforce-foo-bar.test.js"
},
// Add eslint>=10.0.0 as a peer dependency.
"peerDependencies": {
"eslint": ">=10.0.0"
},
// Add these standard keywords to make plugin easy to find!
"keywords": [
"eslint",
"eslintplugin",
"eslint-plugin"
],
"author": "",
"license": "ISC",
"devDependencies": {
"eslint": "^10.0.0"
}
}
Чтобы опубликовать пакет, выполните команду npm publish и следуйте указаниям CLI.
Теперь пакет должен появиться на npm!
Шаг 10. Используйте опубликованное пользовательское правило
Теперь можно использовать опубликованный плагин.
Выполните в проекте следующую команду, чтобы загрузить пакет:
npm
# Add your package name here
npm install --save-dev eslint-plugin-example
yarn
# Add your package name here
yarn add --dev eslint-plugin-example
pnpm
# Add your package name here
pnpm add --save-dev eslint-plugin-example
bun
# Add your package name here
bun add --dev eslint-plugin-example
Измените eslint.config.js, чтобы использовать версию плагина из пакета:
// eslint.config.js
"use strict";
// Import the plugin downloaded from npm
const eslintPluginExample = require("eslint-plugin-example");
// ... rest of configuration
Теперь можно проверить пользовательское правило.
Запустите ESLint для файла example.js, созданного на шаге 8, используя загруженный плагин:
npm
npx eslint example.js
yarn
yarn dlx eslint example.js
pnpm
pnpm dlx eslint example.js
bun
bunx eslint example.js
В терминале появится следующий вывод:
/<path-to-directory>/eslint-custom-rule-example/example.js
8:11 error Value other than "bar" assigned to `const foo`. Unexpected value: baz example/enforce-foo-bar
✖ 1 problem (1 error, 0 warnings)
1 error and 0 warnings potentially fixable with the `--fix` option.
Как видно из сообщения выше, проблему можно исправить с помощью флага --fix, изменив присваиваемое переменной значение на "bar".
Снова запустите ESLint с флагом --fix:
npm
npx eslint example.js --fix
yarn
yarn dlx eslint example.js --fix
pnpm
pnpm dlx eslint example.js --fix
bun
bunx eslint example.js --fix
При запуске этой команды в терминале не будет вывода об ошибках, но вы увидите применённое исправление в файле example.js. Должно появиться следующее:
// example.js
// ... rest of file
function incorrectFoo() {
const foo = "bar"; // Fixed!
}
Итоги
В этом руководстве вы создали пользовательское правило, требующее присваивать всем переменным const с именем foo строку "bar" и предлагающее заменить любое другое значение, присвоенное const foo, на "bar". Вы также добавили правило в плагин и опубликовали плагин в npm.
В процессе вы освоили следующие приёмы, которые можно применить при создании других пользовательских правил и плагинов:
- Создание пользовательского правила ESLint
- Тестирование пользовательского правила
- Добавление правила в плагин
- Публикация плагина
- Использование правила из плагина
Просмотр кода руководства
Вы можете просмотреть исходный код руководства с пояснениями.
© OpenJS Foundation and other contributors
Licensed under the MIT License.
https://eslint.org/docs/latest/extend/custom-rule-tutorial