Putout
Perfection is finally attained not when there is no longer anything to add,
but when there is no longer anything to take away.
(c) Antoine de Saint ExupΓ©ry
πPutout is a JavaScript Linter, pluggable and configurable code transformer, drop-in ESLint replacement with built-in code printer and ability to fix syntax errors. It has a lot of transformations that keeps your codebase in a clean state, removing any code smell and making code readable according to best practices.
The main target is JavaScript, but:
- β
JSX;
- β
TypeScript;
- β
Flow;
- β
Yaml;
- β
Markdown;
- β
JSON;
- β
Ignore;
are also supported. Here is how it looks like:
π€·βοΈ In doubt about using πPutout?
Check out couple variants of plugins that does the same: linting debugger statement:
'use strict';
module.exports.report = () => 'Unexpected "debugger" statement';
module.exports.replace = () => ({
debugger: '',
});
Choose wisely, competitors cannot even fixβ¦ π€«
π Whom should I thank for this project exist?
If I have seen further, it is by standing upon the shoulders of giants.
(c) Isaak Newton
- πͺ ESLint for stable releases and future proof
API
. - πͺ Babel for amazing
API
documented in Handbook
and responsiveness of a team. - πͺ Prettier for minimalistic options and uniform codestyle.
- πͺ jscodeshift for making codemods simple and popular.
π€· Why does this project exist?
βοΈ πPutout on the other hand can make more drastic code transformations that directly affects your codebase making it a better place to code π».
It can:
- β
remove unused
variables
; - β
remove unused
for-of variables
; - β
remove unused
typescripts
types; - β
remove unreferenced
variables
; - β
remove unused
private fields
; - β
remove unused
expressions
; - β
remove useless
variables
; - β
remove useless
Object.assign()
; - β
remove useless
replace()
; - β
remove useless
map
; - β
remove useless
mapped types
; - β
remove useless
mapping modifiers
; - β
remove useless
continue
; - β
remove useless
operand
; - β
remove useless
array constructor
; - β
remove useless
conditions
; - β
remove useless
type conversion
; - β
remove useless
functions
; - β
remove useless
Array.from
; - β
remove useless
spread
; - β
remove useless
arguments
; - β
remove useless
escape
; - β
remove useless
async
; - β
remove useless
await
; - β
remove useless
typeof
; - β
remove useless
template expressions
; - β
remove useless
for-of
; - β
remove useless
array.entries()
; - β
remove
debugger
statement; - β
remove
iife
; - β
remove nested blocks;
- β
remove
process.exit
call; - β
remove
console.log
calls; - β
remove
empty block statements
; - β
remove
empty patterns
; - β
remove
strict mode
directive from esm
; - β
remove
constant conditions
; - β
remove
boolean
from assertion
; - β
remove
boolean
from logical expressions
; - β
remove
duplicates
from TypeScript Union
; - β
remove
unreachable code
; - β
remove
duplicate keys
; - β
remove useless
typescripts
types; - β
remove duplicate
typescripts
interface keys; - β
replace
test.only
to test
calls; - β
replace
test.skip
to test
calls; - β
reuse duplicate
init
; - β
split
variable declarations
; - β
split
nested destructuring
; - β
simplify
assignment
; - β
simplify
ternary
; - β
simplify
logical expressions
; - β
if absent
strict mode
directive in commonjs
add it; - β
convert
const
to let
(when needed to avoid TypeError
); - β
convert
apply
to spread
; - β
convert
bitwise
to logical
operator; - β
convert
concat
to flat
; - β
convert
esm
to commonjs
(enabled for *.cjs
); - β
convert
commonjs
to esm
(enabled for *.mjs
); - β
convert
template
with one expression
to string
; - β
convert
equal
to strict equal
; - β
convert
indexOf
to includes
; - β
convert
replace
to replaceAll
; - β
convert
assignment
to arrow function
; - β
convert
forEach
to for...of
; - β
convert
map
to for...of
; - β
convert
reduce
to for...of
; - β
convert
Math.sqrt()
to Math.hypot()
; - β
extract sequence expressions;
- β
extract object properties;
- β
add
return await
; - β
remove useless
Promise.resolve
; - β
convert
Promise.reject
to throw
; - β
declare before
reference
; - β
declare
undefined variables
; - β
declare
imports
first; - β
apply
as
type assertions; - β
apply
utility types
; - β
apply
array.at
; - β
apply
filter(Boolean)
; - β
apply isArray;
- β
apply
if condition
; - β
apply
await import
; - β
apply comparison order;
- β
apply
flatMap()
; - β
apply
template literals
; - β
merge duplicate
imports
; - β
merge duplicate
functions
;
Install
npm i putout -D
Usage
Usage: putout [options] [path]
Options:
-h, --help display this help and exit
-v, --version output version information and exit
-f, --format [formatter] use a specific output format, the default is: 'progress-bar' locally and 'dump' on CI
-s, --staged add staged files when in git repository
-i, --interactive set lint options using interactive menu
--fix apply fixes of errors to code
--fix-count [count = 10] count of fixes rounds
--rulesdir use additional rules from directory
--transform [replacer] apply Replacer, for example 'var __a = __b -> const __a = __b', read about Replacer https://git.io/JqcMn
--plugins [plugins] a comma-separated list of plugins to use
--enable [rule] enable the rule and save it to '.putout.json' walking up parent directories
--disable [rule] disable the rule and save it to '.putout.json' walking up parent directories
--enable-all enable all found rules and save them to '.putout.json' walking up parent directories
--disable-all disable all found rules (set baseline) and save them to '.putout.json' walking up parent directories
--match [pattern] read '.putout.json' and convert 'rules' to 'match' according to 'pattern'
--flow enable flow
--fresh generate a fresh cache
--no-config avoid reading '.putout.json'
--no-ci disable the CI detection
--no-cache disable the cache
--no-worker disable worker thread
To find errors:
putout lib test
To fix errors:
putout lib test --fix
Plugins
By default πPutout uses all enabled by default plugins, anyways it can be run with a couple mentioned plugins (split with ","):
putout lib --plugins remove-debugger,remove-unused-variables
Environment variables
πPutout supports next environment variables
:
PUTOUT_FILES
- files that should be processed by putout, divided by ",";PUTOUT_CONFIG_FILE
- path to πPutout config file;ESLINT_CONFIG_FILE
- path to ESLint config file;NO_ESLINT
- do not run ESLint after πPutout;NO_ESLINT_WARNINGS
- do not show ESLint warnings;
PUTOUT_FILES=lib,test putout --fix
Configuration
To configure create .putout.json
file and override any of default options.
Match
When you need to match paths to rules you can use match
section for this purpose in .putout.json
:
{
"match": {
"server": {
"remove-process-exit": true
}
}
}
Ignore
When you need to ignore some routes no metter what, you can use ignore
section in .putout.json
:
{
"ignore": ["test/fixture"]
}
Plugins
πPutout supports two types of plugins
, prefix with:
- β
@putout/plugin-
; - β
putout-plugin-
;
To use your plugin createnpm
package with keywords putout
, putout-plugin
and add it to .putout.json
.
For example if you need to remove-something
create πPutout plugin with name putout-plugin-remove-something
and it to package.json
:
{
"plugins": ["remove-something"]
}
Codemods
πPutout supports codemodes
in the similar to plugins way, just create a directory ~/.putout
and put your plugins there. Here is example: convert-tape-to-supertape and this is examples of work.
API
All examples works both in ESM and CommonJS.
CommonJS:
const putout = require('putout');
ESM:
import {putout} from 'putout';
putout(source, options)
import {putout} from 'putout';
const source = `
const t = 'hello';
const m = t + '!';
console.log(t);
`;
putout(source, {
plugins: ['remove-unused-variables'],
});
`
const t = 'hello';
console.log(t);
`;
putoutAsync(source, options)
import {putoutAsync} from 'putout';
const source = `
const t = 'hello';
const m = t + '!';
console.log(t);
`;
await putoutAsync(source, {
plugins: ['remove-unused-variables'],
});
`
const t = 'hello';
console.log(t);
`;
License
MIT