自分用のESLint Shareable Configをつくり、npmパッケージとして公開しました。
なぜつくったのか
自分が管理しているJavaScript/TypeScriptのリポジトリにおいて、中身がほとんど同じESLintの設定ファイルがいくつか存在していました。
これではメンテナビリティ的によろしくないので、共通化できそうな部分をShareable Configとして公開することにしたのです。
事前調査
パッケージをつくるにあたり、JavaScript用パッケージとTypeScript用パッケージの依存関係をどのようにすべきか、事前調査をしました。
そのうえで、まずはJavaScript用パッケージをつくり、その後TypeScript用パッケージをつくる際にJavaScript用パッケージを依存に含めるかどうか考えることにしました。
結果的に、TypeScript用パッケージはJavaScript用パッケージに依存しないような構成になりました。
つくったパッケージ
JavaScript用とTypeScript用の2つのパッケージをつくりました。
また、それらのパッケージの依存となる以下の2つのパッケージもつくりました。
各パッケージの内容について説明していきます。
@eslint-recommended/eslint-config
@eslint-recommended/eslint-config
は、JavaScript用のESLint Shareable Configです。
内部的には以下のパッケージを使用しています。
このパッケージでは自分の好みはなるべく排除して、各パッケージの推奨設定をそのまま採用しています。
現在の設定:
module.exports = {
extends: [
'standard',
'plugin:unicorn/recommended',
'plugin:eslint-comments/recommended',
'plugin:jsdoc/recommended'
]
}
いまのところ@munierujp/eslint-config
でしか使っていませんが、今後他のOrganization用のShareable Configをつくる際、こちらを共通の親として使うことを想定しています。
@munierujp/eslint-config
@munierujp/eslint-config
は、JavaScript用のESLint Shareable Configです。
内部的には以下のパッケージを使用しています。
@eslint-recommended/eslint-config
では自分の好みはなるべく排除していますが、こちらは自分の好みを反映した設定にしてあります。
現在の設定:
const unicornRules = {
// ファイル名のケースはものによって異なる(関数はローワーキャメルケース、クラスはアッパーキャメルケースなど)ので無効化
'unicorn/filename-case': 'off',
// Array.prototype.forEach() を使うのは理にかなっているので無効化
'unicorn/no-array-for-each': 'off',
// undefinedを明示的に書くのは理にかなっているので無効化
'unicorn/no-useless-undefined': 'off',
// 数値を 1_000 のように書くと読みやすいケースもあるもののそうではないケースもあるので無効化
'unicorn/numeric-separators-style': 'off',
// 完全にESMにはできないので無効化
'unicorn/prefer-module': 'off',
// セレクタによって要素の取得メソッドを使いわけるのは理にかなっているので無効化
'unicorn/prefer-query-selector': 'off',
// Array.from() を使うのは理にかなっているので無効化
'unicorn/prefer-spread': 'off',
// TODO [engine:node@>=18]: Node.js v18以上になったら有効化
'unicorn/prefer-top-level-await': 'off',
// 一般的に定着しているような略語を省略せずに書くのは冗長なので無効化
'unicorn/prevent-abbreviations': 'off',
// switch文のcase節を常にブロックにするのは冗長なので必要なときのみブロックにする
'unicorn/switch-case-braces': ['error', 'avoid']
}
const importRules = {
// 標準のソートを無効化
'sort-imports': 'off',
// アルファベット順にソート
'import/order': ['error', {
alphabetize: {
order: 'asc',
caseInsensitive: true
}
}],
// 項目ごとに改行を強制
'import-newlines/enforce': ['error', {
items: 1,
semi: false
}]
}
module.exports = {
extends: [
'@eslint-recommended'
],
plugins: [
'import-newlines'
],
rules: {
...unicornRules,
...importRules
}
}
出典:https://github.com/munierujp/eslint-config/blob/0f91d7022ef481db7e0c615e5963b0c129bd8ad7/index.js
@eslint-recommended/eslint-config-typescript
@eslint-recommended/eslint-config-typescript
は、TypeScript用のESLint Shareable Configです。
内部的には以下のパッケージを使用しています。
- eslint-config-standard-with-typescript
- eslint-plugin-unicorn
- eslint-plugin-eslint-comments
- eslint-plugin-jsdoc
- eslint-plugin-tsdoc
このパッケージでは自分の好みはなるべく排除して、各パッケージの推奨設定をそのまま採用しています。
現在の設定:
module.exports = {
extends: [
'standard-with-typescript',
'plugin:unicorn/recommended',
'plugin:eslint-comments/recommended'
],
overrides: [
{
files: [
'*.js'
],
extends: [
'plugin:jsdoc/recommended'
]
},
{
files: [
'*.ts'
],
plugins: [
'tsdoc'
],
rules: {
'tsdoc/syntax': 'warn'
}
}
]
}
@eslint-recommended/eslint-config
との違いは、eslint-config-standard
のかわりにeslint-config-standard-with-typescript
を使っていることと、eslint-plugin-jsdoc
にくわえてeslint-plugin-tsdoc
も使っていることです。
いまのところ@munierujp/eslint-config-typescript
でしか使っていませんが、今後他のOrganization用のShareable Configをつくる際、こちらを共通の親として使うことを想定しています。
@munierujp/eslint-config-typescript
@munierujp/eslint-config-typescript
は、TypeScript用のESLint Shareable Configです。
内部的には以下のパッケージを使用しています。
@eslint-recommended/eslint-config-typescript
では自分の好みはなるべく排除していますが、こちらは自分の好みを反映した設定にしてあります。
現在の設定:
const unicornRules = {
// ファイル名のケースはものによって異なる(関数はローワーキャメルケース、クラスはアッパーキャメルケースなど)ので無効化
'unicorn/filename-case': 'off',
// Array.prototype.forEach() を使うのは理にかなっているので無効化
'unicorn/no-array-for-each': 'off',
// undefinedを明示的に書くのは理にかなっているので無効化
'unicorn/no-useless-undefined': 'off',
// 数値を 1_000 のように書くと読みやすいケースもあるもののそうではないケースもあるので無効化
'unicorn/numeric-separators-style': 'off',
// 完全にESMにはできないので無効化
'unicorn/prefer-module': 'off',
// セレクタによって要素の取得メソッドを使いわけるのは理にかなっているので無効化
'unicorn/prefer-query-selector': 'off',
// Array.from() を使うのは理にかなっているので無効化
'unicorn/prefer-spread': 'off',
// TODO [engine:node@>=18]: Node.js v18以上になったら有効化
'unicorn/prefer-top-level-await': 'off',
// 一般的に定着しているような略語を省略せずに書くのは冗長なので無効化
'unicorn/prevent-abbreviations': 'off',
// switch文のcase節を常にブロックにするのは冗長なので必要なときのみブロックにする
'unicorn/switch-case-braces': ['error', 'avoid']
}
const importRules = {
// 標準のソートを無効化
'sort-imports': 'off',
// アルファベット順にソート
'import/order': ['error', {
alphabetize: {
order: 'asc',
caseInsensitive: true
}
}],
// 項目ごとに改行を強制
'import-newlines/enforce': ['error', {
items: 1,
semi: false
}]
}
module.exports = {
extends: [
'@eslint-recommended/eslint-config-typescript'
],
plugins: [
'import-newlines'
],
rules: {
...unicornRules,
...importRules
}
}
@munierujp/eslint-config
との違いは、@eslint-recommended/eslint-config
のかわりに@eslint-recommended/eslint-config-typescript
を使っていることです。