Putout

Putout is a tool for identifying, reporting and fixing patterns found in JavaScript code. It can:
- find and remove unused variables;
- find and remove
debuggerstatement; - find and replace
test.onlytotestcalls; - find and replace
test.skiptotestcalls; - find and remove
process.exitcall; - find and split variable declarations;
- find and remove
console.logcalls; - find and remove
empty block statements; - find and remove
empty patterns;
Usage
To find errors use:
putout lib test
To fix it use:
putout lib test --fix
Plugins
The putout repo is comprised of many npm packages. It is a lerna monorepo similar to babel.
Configuration
To configure putout add section putout to your package.json file or create .putout.json file and override any option:
{
"rules": {
"remove-unused-variables": true,
"remove-debugger": true,
"remove-only": true,
"remove-skip": true,
"remove-process-exit": false,
"remove-console": true,
"split-variable-declarations": true,
"remove-empty": true
}
}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 plugins, there is to types: with prefix official @putout/plugin- and user plugins with prefix putout-plugin-. To use your plugin create plugin as npm 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 add it to .putout.json:
{
"plugins": [
"remove-something"
]
}Add putout as a peerDependency to your packages.json and set keywords: putout, putout-plugin so other users can find it
Plugins API
Every putout plugin should contain 3 functions:
report(path)- report error message toputoutcli;find(ast, context)- find errors usingast-traversingand returnplacesarray;fix(path)- fixes paths usingplacesarray received usingfindfunction;
context of find function contains @babel/traverse and @babel/types. Which can be accessed using putout:
const {
traverse,
types,
} = require('putout');Most information you can find in Babel Plugin Handbook is relevant to putout plugins.
To understand how things works from the inside take a look at Super Tiny Compiler.
Example
Let's consider simplest possible plugin for removing `debugger statements @putout/plugin-remove-debugger:
// this is a message to show in putout cli
module.exports.report = () => 'Unexpected "debugger" statement';
// lets find all "debugger" statements
module.exports.find = (ast, {traverse}) => {
const places = [];
traverse(ast, {
DebuggerStatement(path) {
places.push(path);
}
});
// we should return array of places which was found using traverse
return places;
};
// when user calls "putout --fix" node will be removed with
module.exports.fix = (path) => {
path.remove();
};Testing
That was the simplest module to remove debugger statements in your code. Let's look how to test it using @putout/test:
const removeDebugger = require('..');
const test = require('@putout/test')(__dirname, {
'remove-debugger': removeDebugger,
});
// this is how we test that messages is correct
test('remove debugger: report', (t) => {
t.reportCode('debugger', 'Unexpected "debugger" statement');
t.end();
});
// stetement should be removed so result is empty
test('remove debugger: transformCode', (t) => {
t.transformCode('debugger', '');
t.end();
});As you see test runner it is little bit modifed tape. To see more sophisticated example look at @putout/remove-console.
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 example of work.
Eslint Support
If you see that putout brokes formatting of your code, use eslint config @putout/eslint-config.
Install @putout/eslint-config with:
npm i eslint @putout/eslint-config -D
Then create eslintrc.json:
{
"extends": [
"@putout"
]
}And use with putout this way:
putout --fix lib; eslint --fix libWhy?
- because eslint avoids fixes that could change the runtime behavior.
- because babel produces throw-away code;
- because pretier it is a formatter;
- because jscodeshift has no
configandpluginssupport.
The main difference of putout is saving code transformation results directly in a source code in a day-to-day baisis.
Install
npm i putout -g
API
putout(source)
const {readFileSync} = require('fs');
const source = readFileSync('./1.js', 'utf8');
console.log(source);
// outputs
`
const t = 'hello';
const m = t + '!';
`
const result = putout(source);
// returns
`
const t = 'hello';
`
const result2 = putout(result);
// returns
``License
MIT