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;
- β Yaml;
- β Markdown;
- β JSON;
- β Ignore;
are also supported. Here is how it looks like:
Check out couple variants of plugins that does the same: linting debugger statement:
- β SWCLint no-debugger: 49 lines;
- β RSLint no-debugger: 48 lines;
- β ESLint no-debugger: 43 lines;
- β Rome no-debugger: 28 lines;
- β πPutout remove-debugger: 7 lines:
'use strict';
module.exports.report = () => 'Unexpected "debugger" statement';
module.exports.replace = () => ({
debugger: '',
});
Choose wisely, competitors cannot even fixβ¦ π€«
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 inHandbook
and responsiveness of a team. - πͺ Prettier for minimalistic options and uniform codestyle.
- πͺ jscodeshift for making codemods simple and popular.
- β ESLint avoids fixes that could change the runtime behavior.
- β Babel produces throw-away code.
- β Prettier is a formatter.
- β jscodeshift has no
config
andplugins
support.
βοΈ πPutout on the other hand can make more drastic code transformations that directly affects your codebase making it a better place to code π».
- β
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 fromesm
; - β
remove
constant conditions
; - β
remove
boolean
fromassertion
; - β
remove
boolean
fromlogical expressions
; - β
remove
duplicates
from TypeScriptUnion
; - β
remove
unreachable code
; - β
remove
duplicate keys
; - β
remove useless
typescripts
types; - β
remove duplicate
typescripts
interface keys; - β
replace
test.only
totest
calls; - β
replace
test.skip
totest
calls; - β
reuse duplicate
init
; - β
split
variable declarations
; - β
split
nested destructuring
; - β
simplify
assignment
; - β
simplify
ternary
; - β
simplify
logical expressions
; - β
if absent
strict mode
directive incommonjs
add it; - β
convert
const
tolet
(when needed to avoidTypeError
); - β
convert
apply
tospread
; - β
convert
bitwise
tological
operator; - β
convert
concat
toflat
; - β
convert
esm
tocommonjs
(enabled for*.cjs
); - β
convert
commonjs
toesm
(enabled for*.mjs
); - β
convert
template
with oneexpression
tostring
; - β
convert
equal
tostrict equal
; - β
convert
indexOf
toincludes
; - β
convert
replace
toreplaceAll
; - β
convert
assignment
toarrow function
; - β
convert
forEach
tofor...of
; - β
convert
map
tofor...of
; - β
convert
reduce
tofor...of
; - β
convert
Math.sqrt()
toMath.hypot()
; - β extract sequence expressions;
- β extract object properties;
- β
add
return await
; - β
remove useless
Promise.resolve
; - β
convert
Promise.reject
tothrow
; - β
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
;
npm i putout -D
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'
--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
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
π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
To configure create .putout.json
file and override any of default options.
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
}
}
}
When you need to ignore some routes no metter what, you can use ignore
section in .putout.json
:
{
"ignore": ["test/fixture"]
}
π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"]
}
π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.
All examples works both in ESM and CommonJS.
CommonJS:
const putout = require('putout');
ESM:
import {putout} from 'putout';
import {putout} from 'putout';
const source = `
const t = 'hello';
const m = t + '!';
console.log(t);
`;
putout(source, {
plugins: ['remove-unused-variables'],
});
// returns
`
const t = 'hello';
console.log(t);
`;
import {putoutAsync} from 'putout';
const source = `
const t = 'hello';
const m = t + '!';
console.log(t);
`;
await putoutAsync(source, {
plugins: ['remove-unused-variables'],
});
// returns
`
const t = 'hello';
console.log(t);
`;
MIT