2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

JavaScriptAdvent Calendar 2022

Day 25

JavaScriptをeslintrc使用せずESLintしてみた話

Last updated at Posted at 2022-12-24

まず結論です。
上から順番に、
Lint確認のみ
Lint確認のみ(browserかnodeで使用)
Lint確認と優しめのFormat確認
Lint確認と厳しめのFormat確認

npx eslint --no-eslintrc --parser-options=ecmaVersion:latest sample.js
npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env browser,node sample.js
npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env es6,browser,node -c node_modules\eslint\conf\eslint-recommended.js sample.js
npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --env browser -c node_modules\eslint-config-airbnb-base\index.js sample.js

ちなみに、
ファイル名ではなく、
ディレクトリ名を指定すると、
ディレクトリ内の全てのJavaScriptファイルをLint確認出来ます。
カレントディレクトリを指定するのであれば.
例:npx eslint --no-eslintrc --parser-options=ecmaVersion:latest .

sample.js

以下機能等を含んだ、
以下コードで検証しています。

:notebook_with_decorative_cover: 機能等
:notebook_with_decorative_cover: コード
sample.js
function func2015(n = 0, ...rest) {
  console.log({}.toString.call(''));
  console.log({}.toString.call([]));
  console.log({}.toString.call({}));
  console.log({}.toString.call(() => {}));
  console.log(n);
  console.log(n.toString().concat('', ...rest) * 1);
  console.log(Array(5));
  console.log(Array(5).fill());
  console.log(Array(5).fill(0));
  console.log([...Array(5).keys()]);
  [...Array(5).keys()].forEach((i) => console.log(i));
  const range1 = (start, stop, step = 1) => Array.from({ length: (stop - start) / step + 1 }, (_, i) => start + i * step);
  const range2 = (start, stop, step = 1) => Array(Math.trunc((stop - start) / step + 1)).fill().map((_, i) => start + i * step);
  const range3 = (start, stop, step = 1) => [...Array(Math.trunc((stop - start) / step + 1)).keys()].map((i) => start + i * step);
  console.log(range1(1, 10));
  console.log(range2(1, 10));
  console.log(range3(1, 10));
  console.log(range1(1, 10, 2));
  console.log(range2(1, 10, 2));
  console.log(range3(1, 10, 2));
  console.log([1, 4, 9].map((x) => x * 2));
  console.log([12, 5, 8, 130, 44].filter((x) => x >= 10));
  console.log([1, 2, 3, null, 5, undefined, false, 7].filter((x) => x));
  console.log([0, 1, 2, 3].reduce((p, c) => p + c));
  console.log([0, 1, 2, 3].reduce((p, c) => p + c, 0));
  console.log([0, 1, 2, 3].reduce((p, c) => p + c, 10));
  console.log([12, 54, 18, 130, 44].every((x) => x >= 20));
  console.log([12, 54, 18, 130, 44].every((x) => x >= 10));
  console.log([12, 5, 8, 1, 4].some((x) => x >= 20));
  console.log([12, 5, 8, 1, 4].some((x) => x >= 10));
  const [cat, dog] = ['neko', 'inu'];
  console.log(`${cat}, ${dog}`);
  console.log({ [cat]: 'nico' }.neko);
  console.log(new Map([['cat', 'neko']]));
  console.log(new Set(['cat', 'neko']));
  console.log(new WeakMap());
  console.log(new WeakSet());
  console.log(new Promise(() => {}));
  const res = new Promise((resolve) => {
    resolve();
  });
  const rej = new Promise((resolve, reject) => {
    reject();
  });
  res.then(() => {});
  rej.then(() => {}).catch(() => {});
  console.log(res);
  console.log(rej);
  console.log(Symbol('cat').toString());
  console.log();
}

const func2016 = () => {
  console.log(2 ** 4);
  console.log([1, 2, 3].includes(3));
  console.log();
};

const func2017 = async (...rest) => {
  await new Promise((resolve) => {
    setTimeout(resolve, 1000);
  });
  console.log('func2017.01---------------------------');
  console.log(''.concat('', ...rest));
  console.log((2017).toString().padStart(8, 0));
  console.log((2017).toString().padEnd(8, '_'));
  console.log('func2017.02---------------------------');
};

const func2018 = () => {
  console.log('123456'.match(/123(?=456)/));
  console.log('123456'.match(/123(?!456)/));
  console.log('123456'.match(/(?<=123)456/));
  console.log('123456'.match(/(?<!123)456/));
  const s = 'I am a cat. Name is undefined.';
  const r = s.match(/(?<c>cat).*(?<n>undef)/);
  console.log(r);
  console.log(r.groups.c);
  console.log(r.groups.n);
  console.log();
};

const func2019 = () => {
  try {
    console.log('try');
  } catch {
    console.log('catch');
  }
  console.log('     hello     '.trimStart());
  console.log('     world     '.trimEnd());
  console.log();
};

const func2020 = async () => {
  await new Promise((resolve) => {
    window.addEventListener('DOMContentLoaded', resolve);
  });
  console.log('func2020.01---------------------------');
  console.log(document?.head);
  console.log(document?.body);
  console.log(document?.foot);
  console.log(document?.foot?.heel);
  console.log(document?.head && 'find head');
  console.log(document?.body && 'find body');
  console.log(document?.foot && 'find foot');
  console.log(document?.foot?.heel && 'find heel');
  console.log(document?.head || 'not found head');
  console.log(document?.body || 'not found body');
  console.log(document?.foot || 'not found foot');
  console.log(document?.foot?.heel || 'not found heel');
  console.log(document?.head ?? 'not found head');
  console.log(document?.body ?? 'not found body');
  console.log(document?.foot ?? 'not found foot');
  console.log(document?.foot?.heel ?? 'not found heel');
  console.log('func2020.02---------------------------');
};

const func2021 = () => {
  let x = 0;
  let y = 1;
  let z;
  console.log((x ||= 'Logical OR assignment'));
  console.log((y &&= 'Logical AND assignment'));
  console.log((z ??= 'Logical nullish assignment'));
  console.log();
};

const func2022 = () => {
  const s = 'I am a cat. Name is undefined.';
  const r = s.match(/(?<c>cat).*(?<n>undef)/d);
  console.log(r);
  console.log(r[0]);
  console.log(r[1]);
  console.log(r[2]);
  console.log(r.indices[0]);
  console.log(r.indices[1]);
  console.log(r.indices[2]);
  console.log(r.groups.c);
  console.log(r.groups.n);
  console.log(r.indices.groups.c);
  console.log(r.indices.groups.n);
  console.log();
};

// main
func2015(2, 0, 1, 5);
func2016();
func2017(
  'T',
  'r',
  'a',
  'i',
  'l',
  'i',
  'n',
  'g',
  ' ',
  'c',
  'o',
  'm',
  'm',
  'a',
  's',
  ' ',
  'i',
  'n',
  ' ',
  'f',
  'u',
  'n',
  'c',
  't',
  'i',
  'o',
  'n',
  's',
);
func2018();
func2019();
func2020();
func2021();
func2022();
sample.html
<!doctype html>
<html>
<head>
<script src="sample.js"></script>
</head>
<body>
</body>
</html>

install

まずは、
npm i -D eslint
npm i -D eslint-config-airbnb-base
します。

iはinstallのエイリアスで、
-Dは--save-devのエイリアスなので、
npm install --save-dev eslint
npm install --save-dev eslint-config-airbnb-base
と同じです。

※Node.js(およびnpm)はインストールされているものとします。

https://www.npmjs.com/package/eslint
https://www.npmjs.com/package/eslint-config-airbnb-base
https://docs.npmjs.com/cli/commands/npm-install

npx eslint sample.js

npx eslint sample.js

上記を実行します。しかし、
設定ファイルが見つからんよ、
と言われます。
ということで、

npx eslint --no-eslintrc sample.js

npx eslint --no-eslintrc sample.js

上記を実行します。しかし、
デフォルト引数の部分でerrorになってしまいます。
ESLintの標準はES5相当のようなのです。
ということで、

ECMAScript

npx eslint --no-eslintrc --env es6 sample.js

上記を実行します。しかし、
べき乗演算子(**)
などを解析出来ないようです。
ということで、

npx eslint --no-eslintrc --env es2016 sample.js

上記を実行します。しかし、
async function
などを解析出来ないようです。
ということで、

npx eslint --no-eslintrc --env es2017 sample.js
npx eslint --no-eslintrc --env es2018 sample.js
npx eslint --no-eslintrc --env es2019 sample.js
npx eslint --no-eslintrc --env es2020 sample.js
npx eslint --no-eslintrc --env es2021 sample.js

上記を実行します。しかし、
なんだかんだ解析出来ないところがあり、
errorになってしまいます。
ということで、

npx eslint --no-eslintrc --env es2022 sample.js

上記を実行して、
ようやくerrorなく解析完了出来ます。

しかし、
ECMAScriptのバージョンが上がるごとに、
コマンドの引数を変更しなければならないのは面倒です。
ということで、

ecmaVersion:latest

npx eslint --no-eslintrc --parser-options=ecmaVersion:latest sample.js

とします。
これで最新のECMAScriptで解析してくれます。

ところで、
--env--parser-options=ecmaVersionの違いは何でしょうか?

ESLint Language Options # Specifying Parser Options
上記に記載があり、
--env es6はES6のグローバル変数を有効にする、
--parser-options=ecmaVersion:6はES6のグローバル変数を有効にしない、
とのことです。

しかし、この段階では謎です。何故なら、

npx eslint --no-eslintrc --parser-options=ecmaVersion:latest sample.js

何もerrorが出ないのです...

--env未指定なのに、
ES2015(ES6)で追加されたMap,Set,WeakMap,WeakSet,Promise,Symbolが、
問題なく解析出来ています。

ともかく進めます。

npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module sample.js
npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env browser,node sample.js

--parser-options=sourceType:module
一応上記オプションを追加しておきます。

--env browser,node
一応上記オプションも追加しておきます。
ブラウザとNodeのグローバルオブジェクトが認識出来るようになります。

ここまでで基本的な構文解析が可能です。

ESLintの推奨設定

node_modules\eslint\conf\eslint-recommended.js
ESLintの推奨設定があるようなので利用してみます。

npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env browser,node -c node_modules\eslint\conf\eslint-recommended.js sample.js

上記を実行します。しかし、
ES2015(ES6)で追加されたMap,Set,WeakMap,WeakSet,Promise,Symbolで、
何それおいしいの?と言われます。

どうも設定ファイルを読み込むとESlintの初期設定も無設定にされてしまうようです。
--env es6を追加します。
ということで、

npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env es6,browser,node -c node_modules\eslint\conf\eslint-recommended.js sample.js

上記を実行します。
問題なく解析出来ました。

ESLintの全部設定

node_modules\eslint\conf\eslint-all.js
ESLintの全部設定があるようなので利用してみます。

npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env es6,browser,node -c node_modules\eslint\conf\eslint-all.js sample.js

滅茶苦茶errorが出ます。
なかには、
Comments should not begin with a lowercase character
コメントは小文字で始めるべきではありません。
いや、こまか!!

ということで、

eslint-config-airbnb-base

airbnbです。

ESLintは設定が多岐に渡るので丁度良い設定を誰か作ってくれい、
ということで、
eslint-config-airbnb-base
eslint-config-airbnb
eslint-config-google
eslint-config-standard
です。
eslint-config-airbnb-baseと
eslint-config-airbnbの違いはreactなどの有無とのことです。

airbnbとgoogleとstandardの三種類が有名なようですが、
https://npmtrends.com/eslint-config-airbnb-vs-eslint-config-airbnb-base-vs-eslint-config-google-vs-eslint-config-standard
上記を見ると2022年12月現在、
eslint-config-airbnb-base
が一番使用されているようなので、
冒頭でインストールしています。

ということで、

npx eslint --no-eslintrc -c node_modules\eslint-config-airbnb-base\index.js sample.js

上記を実行します。
optional catch bindingでerrorが出ます...

eslint-config-airbnb-baseの設定を見ると、
ecmaVersion:2018となっています...

ecmaVersion:latestにします。あと
--env browserを追加しておきます。

ということで、

npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --env browser -c node_modules\eslint-config-airbnb-base\index.js sample.js

です。

これでeslintrcを使用せず、
JavaScriptをairbnbのconfigでESLint出来ました。

おまけ

https://www.npmjs.com/package/prettier
PrettierはJavascriptなどのFormatterです。

https://npmtrends.com/eslint-config-airbnb-vs-eslint-config-airbnb-base-vs-eslint-config-google-vs-eslint-config-standard-vs-prettier
PrettierはJavascript以外のFormatterでもあるので、
単純比較では比較出来ないかもしれませんが、
上記を見るととても使われているようです。

なので、
npm i -D prettier
します。

npx prettier --print-width 100 --single-quote --trailing-comma all -c sample.js

とすると、
airbnbと構文解釈が、
大凡一緒になりますが、
全く一緒ではないので、
うまいこと書く必要がありますね...

WindowsのCLIのテスト用バッチファイル

sample.bat
@pause
echo npx eslint sample.js
call npx eslint sample.js
echo npx eslint --no-eslintrc sample.js
call npx eslint --no-eslintrc sample.js
echo npx eslint --no-eslintrc --env es6 sample.js
call npx eslint --no-eslintrc --env es6 sample.js
echo npx eslint --no-eslintrc --env es2016 sample.js
call npx eslint --no-eslintrc --env es2016 sample.js
echo npx eslint --no-eslintrc --env es2017 sample.js
call npx eslint --no-eslintrc --env es2017 sample.js
echo npx eslint --no-eslintrc --env es2018 sample.js
call npx eslint --no-eslintrc --env es2018 sample.js
echo npx eslint --no-eslintrc --env es2019 sample.js
call npx eslint --no-eslintrc --env es2019 sample.js
echo npx eslint --no-eslintrc --env es2020 sample.js
call npx eslint --no-eslintrc --env es2020 sample.js
echo npx eslint --no-eslintrc --env es2021 sample.js
call npx eslint --no-eslintrc --env es2021 sample.js
echo npx eslint --no-eslintrc --env es2022 sample.js
call npx eslint --no-eslintrc --env es2022 sample.js
echo npx eslint --no-eslintrc --parser-options=ecmaVersion:latest sample.js
call npx eslint --no-eslintrc --parser-options=ecmaVersion:latest sample.js
echo npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module sample.js
call npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module sample.js
echo npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env browser,node,webextensions sample.js
call npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env browser,node,webextensions sample.js
@pause
echo npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env browser,node,webextensions -c node_modules\eslint\conf\eslint-recommended.js sample.js
call npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env browser,node,webextensions -c node_modules\eslint\conf\eslint-recommended.js sample.js
echo npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env es6,browser,node,webextensions -c node_modules\eslint\conf\eslint-recommended.js sample.js
call npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env es6,browser,node,webextensions -c node_modules\eslint\conf\eslint-recommended.js sample.js
echo npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env es6,browser,node,webextensions -c node_modules\eslint\conf\eslint-all.js sample.js
call npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --parser-options=sourceType:module --env es6,browser,node,webextensions -c node_modules\eslint\conf\eslint-all.js sample.js
@pause
@rem after install eslint-config-airbnb-base
echo npx eslint --no-eslintrc -c node_modules\eslint-config-airbnb-base\index.js sample.js
call npx eslint --no-eslintrc -c node_modules\eslint-config-airbnb-base\index.js sample.js
echo npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --env browser,webextensions -c node_modules\eslint-config-airbnb-base\index.js sample.js
call npx eslint --no-eslintrc --parser-options=ecmaVersion:latest --env browser,webextensions -c node_modules\eslint-config-airbnb-base\index.js sample.js
@pause
@rem after install prettier
echo npx prettier --print-width 100 --single-quote --trailing-comma all -c sample.js
call npx prettier --print-width 100 --single-quote --trailing-comma all -c sample.js
@pause

あとがき

ノンプログラマーの素人が記述をしたコードです。
狭い利用範囲と少ない利用頻度での確認ですので、
記載内容に間違いや勘違いがあるかもしれません。
上記内容を参照の際は自己責任でお願い致します。

参考

ESLint Documentation
https://eslint.org/docs/latest/
https://eslint.org/docs/latest/user-guide/
https://eslint.org/docs/latest/user-guide/configuring/configuration-files
https://eslint.org/docs/latest/user-guide/configuring/configuration-files#using-eslintrecommended
https://eslint.org/docs/latest/user-guide/configuring/configuration-files#using-eslintall
https://eslint.org/docs/latest/user-guide/configuring/language-options
https://eslint.org/docs/latest/user-guide/configuring/language-options#specifying-parser-options
https://eslint.org/docs/latest/user-guide/command-line-interface

みどりのさるのエンジニア ESLintをちゃんと理解する
https://t-yng.jp/post/understand-eslint

とほほのJavaScript
https://www.tohoho-web.com/js/
https://www.tohoho-web.com/js/what.htm
caniuse ECMAScript
https://caniuse.com/?search=ECMAScript
https://caniuse.com/?search=ECMAScript-20
ECMAScript compatibility table
https://kangax.github.io/compat-table/es6/
https://kangax.github.io/compat-table/es2016plus/

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?