the pluggable code transformer
Clone or download
coderaiser
Latest commit 4fc4267 Jan 21, 2019

README.md

Putout NPM version Dependency Status Build Status Coverage Status

Putout is a tool for identifying, reporting and fixing patterns found in JavaScript code. It can:

  • find and remove unused variables;
  • find and remove debugger statement;
  • find and replace test.only to test calls;
  • find and replace test.skip to test calls;
  • find and remove process.exit call;
  • find and split variable declarations;
  • find and remove console.log calls;
  • 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.

Package Version Dependencies
@putout/plugin-remove-unused-variables npm Dependency Status
@putout/plugin-remove-process-exit npm Dependency Status
@putout/plugin-remove-debugger npm Dependency Status
@putout/plugin-remove-only npm Dependency Status
@putout/plugin-remove-skip npm Dependency Status
@putout/plugin-split-variable-declarations npm Dependency Status
@putout/plugin-remove-console npm Dependency Status
@putout/plugin-remove-empty npm Dependency Status
@putout/plugin-remove-empty-pattern npm Dependency Status

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 to putout cli;
  • find(ast, context) - find errors using ast-traversing and return places array;
  • fix(path) - fixes paths using places array received using find function;

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 lib

Why?

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