ESLint's flat config and Emacs
Latest update:
I expected to use this "new" eslint as follows:
- have a user-wide eslint installation with a personal default
configuration;
- given #1, to be able to run eslint in any project (mine or not)
to check it against my personal rules;
- if a project has
node_modules/.bin/eslint
script (implying there
is a config file in the project's root directory), running
node_modules/.bin/eslint
should ignore the global config and use
the local one;
- Flycheck in Emacs should automatically execute either
node_modules/.bin/eslint
(if it exists) or the global version
otherwise.
Naïvely installing eslint via 'npm i -g' won't do much good since any
plugins must still be installed locally.
Hence, I created a directory ~/lib/dotfiles/eslint
solely for a
"global", user-wide installation & configuration:
|-- eslint*
|-- eslint.config.mjs
|-- node_modules/
| |-- .bin/
| | `-- eslint -> ../eslint/bin/eslint.js*
| `-- eslint/
`-- package.json
where eslint is a shell script, symlinked from a directory in PATH:
$ stat -c%N `which eslint`
'/home/alex/bin/eslint' -> '/home/alex/lib/dotfiles/eslint/eslint'
$ cat eslint
#!/bin/sh
__dir__=$(dirname "$(readlink -f "$0")")
"$__dir__"/node_modules/.bin/eslint -c "$__dir__"/eslint.config.mjs "$@"
and eslint.config.mjs
has common rules for .js files and files
without extensions:
import globals from 'globals'
import js from '@eslint/js'
import react from 'eslint-plugin-react'
export default [
js.configs.recommended,
{
rules: {
"no-unused-vars": [ "warn", { "argsIgnorePattern": "^_" } ],
…
},
languageOptions: {
globals: {
...globals.browser,
...globals.node,
…
}
}
},
{
files: ["**/!(*.*)"],
ignores: ["**/{Makefile,Rakefile,Gemfile,LICENSE,README}"],
},
…
]
If you don't care about any custom configurations that arrive with
almost any JS project, you may stop here. Otherwise, we need to
instruct Emacs where to search for eslint executable.
(defun my--npm-exec-path()
(let ((npm-root (string-trim
(shell-command-to-string "npm root 2>/dev/null"))))
(when (not (string= "" npm-root))
(make-local-variable 'exec-path)
(add-to-list 'exec-path (file-name-concat npm-root ".bin"))
)))
(add-hook 'js-mode-hook 'my--npm-exec-path)
(add-hook 'js-mode-hook 'flycheck-mode)
This tells the editor to invoke my--npm-exec-path
function every
time Emacs opens a .js file. The function runs npm root
to guess the
proper path for node_modules
directory and prepends Emacs'
internal exec-path
list with the path where the eslint script
might be installed. Iff such a script is found by Flycheck, our global
~/lib/dotfiles/eslint/eslint.config.mjs
is ignored.
Tags: ойті
Authors: ag