Noveo

Наш блог Собственные правила для ESLint

Собственные правила для ESLint

Старший веб-разработчик Noveo Константин рассказывает, как сделать работу с одним из самых популярных линтеров еще эффективнее.

Noveo working with ESlint

Сложно представить современный проект на JavaScript без использования линтеров (средств автоматической проверки кода), потому что они упрощают работу разработчиков: позволяют выявлять и исправлять ошибки и поддерживать единый стиль кода. ESLint — один из самых популярных линтеров для JavaScript, о нем и пойдет речь в этой статье.

 

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

Задача

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

Для того, чтобы найти в коде все места, где нарушается формат ключей переводов, мы создали новое правило для ESLint. Для простоты будем искать все использования функции tr и проверять, что первый параметр этой функции (который является ключом перевода) — строка, содержащая минимум 3 (этот параметр можно будет настроить в конфигурации ESLint) слова, разделенных символом подчеркивания.

Конфигурация

Сначала создадим плагин со всеми необходимыми файлами и настроим его использование, а потом рассмотрим подробнее, как написать само правило.

 

1. Добавим в корень проекта директорию eslint-plugin-translation. Название плагина должно начинаться с eslint-plugin-.

 

2. Внутри этой директории создадим package.json следующего содержания:

{
  "name": "eslint-plugin-translation",
  "version": "1.0.0",
  "main": "index.js"
}

3. Создадим файл index.js — в нем мы будем описывать логику нашего правила (об этом подробнее в следующем разделе).

 

4. Добавляем плагин в проект. В нашем случае используется yarn. В корне проекта запускаем:

yarn add --dev file:./eslint-plugin-translation

 

Для npm должно сработать:

npm install -D ./eslint-plugin-translation

 

В результате в проектном файле package.json должна появиться запись о нашем плагине, а сам плагин должен появиться в директории node_modules.

 

5. Добавляем плагин в конфиг eslint.

a. Добавляем плагин.

b. Настраиваем правило. В плагине можно описать несколько правил, каждое из которых можно потом настроить отдельно. Для настройки используем идентификатор правила в следующем формате: <plugin-name>/<rule-name>. Наше правило имеет параметры, поэтому используем массив для конфигурации. Первый элемент массива — 2 — означает, что при проверке нарушение правила будет вызывать ошибку. Второй элемент массива — объект с настройками правила. В данном случае указываем, что минимальное количество слов в ключе перевода должно быть 3.

// .eslintrc.js
module.exports = {
  ...
  plugins: ["translation"],
  rules: {
    "translation/check-length": [2, { min: 3 }],
  }
  ...
};

Правило готово к работе!

Правило

Само правило описываем в файле index.js в нашем плагине.

// indes.js
module.exports = {
  rules: {
    'check-length': {
      meta: {
        // описание правила, параметров и т.д.
      },
      create(context) {
        return {
          // логика правила
        }
      },
    },
  },
}

rules — объект, содержащий правила. Можем перечислить несколько правил, относящихся к проверке переводов. Правило check-length включает в себя объект meta и функцию create.

Добавление параметров

Полный набор параметров, которые можно описать в meta, можно найти в документации ESlint: https://eslint.org/docs/developer-guide/working-with-rules#rule-basics. Добавим описание и параметр для количества слов.

meta: {
        type: 'suggestion',
        docs: {
          description: 'To avoid generic translation keys',
        },
        schema: [
          {
            type: 'object',
            properties: {
              min: {
                type: 'number',
              },
            },
            additionalProperties: false,
          },
        ],
      },
  • type — род правила («problem», «suggestion» или «layout»),
  • description — этот параметр может использоваться IDE, чтобы показать подсказку при возникновении ошибки,
  • schema — JSON-схема, описывающая объект параметров, с которым работает правило. Используем один числовой параметр — min.

Синтаксическое дерево

Для работы ESLint использует Абстрактное Синтаксическое Дерево (AST), оно же понадобится для написания правила.

 

Рассмотрим пример кода, в котором должна сработать проверка:

tr('error', 'Error');

 

Воспользуемся сайтом https://astexplorer.net/ для построения AST для этого кода.

Noveo Собственные правила для eslintВ представлении AST функция перевода — это CallExpression, с названием (callee.name) — tr и массивом аргументов, каждый из которых имеет тип и значение. Этой информации достаточно, чтобы написать правило.

create(context) {
        return {
          CallExpression(node) {
            const { callee } = node
            const { arguments } = node
            if (callee.name === 'tr' && arguments[0]?.type === 'Literal') {
              const translationKey = arguments[0].value
              const min = (context.options[0] && context.options[0].min) || 3
              const wordsCount = translationKey.split('_').length
              if (wordsCount < min) {
                context.report(
                  node,
                  `Short translation key "${translationKey}"`
                )
              }
            }
          },
        }
      },

Строка 3 — тип узла в синтаксическом дереве — такой же, как в AST explorer.

Строка 6 — проверяем, что название функции — tr, а первый параметр — литерал.

Строка 7 — получаем значение параметра.

Строка 8 — получаем значение опции min из контекста (если не указан, то используем 3)

Строка 10 — если количество слов в ключе перевода меньше, чем min…

Строка 11 — …сообщаем об ошибке.

 

Используя описанный механизм и AST explorer, можно написать более сложные и интересные правила, которые сделают проверку кода более эффективной.

 

Делайте ваши проекты лучше!

 

Ссылки:

  1. https://www.webiny.com/blog/create-custom-eslint-rules-in-2-minutes-e3d41cb6a9a0
  2. https://eslint.org/docs/developer-guide/working-with-rules
  3. https://astexplorer.net/
  4. https://blog.maximeheckel.com/posts/how-to-build-first-eslint-rule

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

НазадПредыдущий пост ВпередСледующий пост

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: