- EsLint
- Prettier
- EsLint & Prettier Integration
Eslint checks syntax, finds problems and enforces code style in JavaScript files.
- eslint is a NPM module
sudo npm install -D eslint
- sudo is only needed while installing globally
- install packages as locally (instead of globally) is a better option to make sure your npm settings (package.json) is a sharable configuration and when initiated (
npm init
) it'll download are the necessary packages
"extends": "eslint:recommended"
= default when you choose to 'Answer questions about your style'- You can view (part of it, I don't know the rest; doesn't contain 'no-console' rule, for example) here
eslint --init
= creates '.eslintrc.js' with the configeslint path
= to check js files in the path directory and in its subdirectorieseslint --fix path
= check and fix some of the warnings and errors; e.g. indentation, quotes and semicolon
- ESLint will automatically look for config files ('.eslintrc') in the directory of the file to be linted,
- and in successive parent directories all the way up to the root directory of the filesystem
- this behavior is useful when you want different configurations for different parts of a project or when you want others to be able to use ESLint directly without needing to remember to pass in the configuration file
- add
"root": true
to the '.eslintrc' file to disable this behavior
elsint --print-config script.js
- output all of the rules that will be used for a given file
- no linting is performed and only config-related options are valid.
- at '.eslintrc.js', edit the 'rules' object
"no-console": [ "warn" }
= simple rule example- "rule-name": [ "off, 0 | warn, 1 | error, 2" ] = basic format
- off or 0 = turn the rule off
- warn or 1 = turn the rule on as a warning, exit code will still be success
- error or 2 = turn the rule on as an error, exit code will be 1 (error)
"quotes": ["error", "double"]
,"no-console": { "allow": ["warn", "error"] }
= rules with extra options
- ignore one line:
console.log("!!!"); // eslint-disable-line
- ignore multiple lines:
/* eslint-disable */
console.log("!!!");
/* eslint-enable */
- ignore file/directory:
"ignorePatterns": [ ".eslintrc.js", "vendor/*" ],
= add to '.eslintrc.js'- or create a file '.eslintignore' and add paths to ignore
.eslintrc.js
vendor/*
npm install -D eslint-watch
npx esw -w path
npm install -D pre-commit
- NOTE: you must've already
git init
, otherwise this install won't find the '.git' directory to add the hook
- NOTE: you must've already
- will try to run your npm test command in the root of the git repository by default unless it's the default value that is set by 'package.json'
"precommit": ["foo", "bar", "test"],
= run multiple scripts (npm run foo
, ...)
- to be able to read the code, eslint parse it using espree/acorn which creates an abstract syntax tree (ast)
- https://astexplorer.net/ to view what your code's ast looks like
- when creating a custom rule, you must know what type of structure the rule must apply (VariableDeclarator, FunctionDeclaration, CallExpression...) and how to filter it by one of its properties
// error if a 'x' variable is declared
return {
VariableDeclarator: function (node) {
if (node.id.name === "x") {
context.report(node, "Not allowed!");
}
},
};
// error if a call to the 'test' function is made
return {
CallExpression: function (node) {
if (node.callee.name === "test") {
context.report(node, "Not allowed!");
}
},
};
// error if a 'test' function is declared
return {
FunctionDeclaration: function (node) {
if (node.id.name === "test") {
context.report(node, "Not allowed!");
}
},
};
- plugin: = it's good for reusability
- cli option = you must include the 'rulesdir' option everytime you call eslint
- in the root of the main project, create the plugin directory, e.g. 'custom-rules'
- in this directory, create 'index.js' and add rules like this:
module.exports.rules = {
"var-length": (context) => ({
VariableDeclarator: (node) => {
if (node.id.name.length < 2) {
context.report(
node,
"Variable names should be longer than 1 character"
);
}
},
}),
"no-test-function": (context) => ({
FunctionDeclaration: function (node) {
if (node.id.name === "test") {
context.report(node, "Not allowed!");
}
},
}),
};
npm init
, NOTE: the name of this package must start with 'eslint-plugin', e.g. 'eslint-plugin-custom-rules'sudo npm link
- back in the root,
npm link eslint-plugin-custom-rules
- in the 'eslintrc.js', add the new plugin
"plugins": [ "custom-rules" ],
; NOTE: the leading 'eslint-plugin-' isn't required and can be omitted - also, add to the rules array
"my-rules/var-length": [ "error" ], "my-rules/no-test": [ "error" ],
- instead of add the custom rules to the rules array one by one
- in the plugin's index export:
module.exports.configs = {
recommended: {
rules: {
"my-rules/var-length": "error",
"my-rules/no-test-function": "error",
},
},
};
- in '.eslintrcjs', add
"extends": ["plugin:my-rules/recommended"],
- create a directory (with any name) to contain your custom rules, e.g 'eslint-custom-rules'
- the code below (saved at 'eslint-custom-rules/no-test-function.js') creates a rule that will throw error if the function 'test' is called
module.exports = {
create: function (context) {
return {
CallExpression: function (node) {
if (node.callee.name === "test") {
context.report(node, "Call 'test' function is not allowed!");
}
},
};
},
};
- add it to '.eslintrc.js' in the rules array
"no-test-function": [ "error" ]
eslint --rulesdir eslint-custom-rules/ .
"custom-rule": ["error", "opt1", "opt2"],
, at '.eslintrc.js' = any other parameter passed to the rule besides the first one, will be considered a option- you can access they in the 'context.options' in your custom rule file
- will rename any variable named "colour" to "color"
module.exports = {
create: function (context) {
return {
VariableDeclarator: function (node) {
if (node.id.name === "colour") {
context.report({
node: node,
message: "Use american english spelling!",
fix: function (fixer) {
return fixer.replaceText(node.id, "color");
},
});
}
},
};
},
};
- you can choose to use a popular config during the init
- or, after init, do
npx install-peerdeps --dev eslint-config-airbnb
= install airbnb config and all of its peer dependencies"extends": "airbnb"
= in '.eslintrc.js'
Opinionated (few defaults can be changed) code formatter with support for JS, JSX, TypeScript, JSON, CSS, SCSS, HTML, Markdown...
- Linters have two categories of rules:
- formatting rules = e.g. max-len, tabs-or-spaces, comma-style...
- code-quality rules = e.g. no-unused-vars, no-implicity-globals...
- Prettier will take care of formatting rules - the first category, but not the second
- and will format code much better than a linter
npm i prettier --save-dev --save-exact
ornpm i -DE prettier
- NOTE: "We recommend pinning an exact version of prettier in your package.json as we introduce stylistic changes in patch releases".
npx prettier --write <filename...>
- install the package onchange
npm i onchange --save-dev
and - execute it:
npx onchange <file path> -- npx prettier --write {{changed}}
- run once:
prettier --write "."
- watch:
onchange "." -- prettier --write {{changed}}
- view all options
- options can be configured in the
- cli = e.g.
npx prettier --single-quote --write "."
- file = '.prettierrc.json' file (other options here)
- cli = e.g.
// basic JSON '.prettierrc.json' file
{
"singleQuote": true
}
- ignore files
- add them in the '.prettierignore' file
- cli
--ignore-path
option
- to ignore blocks of code:
// TOPIC: next line will exclude the next node in the abstract syntax tree from formatting
// prettier-ignore
let z = {
a : 1,
bbbb: 2,
cc : 3,
};
<div>
{/* prettier-ignore */}
<span ugly format='' />
</div>
/* prettier-ignore */
h1 { color: red; }
- integrate a liting tool to prettier is done in two steps
- disable any existing formatiing rule in you linter that may coflict with Prettier
- add an extension to your linting tool to format your file with Prettier - so that you only need a single command for format a file, or run your linter then Prettier as separate steps
npm i -DE prettier
npm i -D eslint
npx eslint --init
, choose the 'airbnb' style guidenpm i -D eslint-config-prettier eslint-plugin-prettier
- first is a config that disables rules that conflict with prettier
- second runs prettier as an eslint rule
"extends": ["airbnb", "plugin:prettier/recommended"]
in '.eslintrc.js'- NOTE: make sure to put 'prettier' last in the extends array, so it gets the chance to override other configs
- done! now run with:
npx eslint "."
= view errors that doesn't pass either eslint or prettier rules--fix
option = fix all (fixable) of them
- this is necessary, because the 'eslint-config-prettier' will disable any airbnb rules (or any other ruleset being applied in eslint) that conflict with prettier
- to make prettier use single-quotes (just like airbnb), add
"singleQuote": true
to '.prettierrc.json'- NOTE:
"singleQuote": true
this isn't a hard rule in prettier, prettier will use the type of quotes which requires less escapes and, with that option set to true, will prefer single-quotes in case of a tie.
- NOTE: