npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@erboladaiorg/porro-reiciendis

v5.6.86

Published

[NPMURL]: https://npmjs.org/package/putout "npm" [NPMIMGURL]: https://img.shields.io/npm/v/putout.svg?style=flat&longCache=true [BuildStatusURL]: https://github.com/erboladaiorg/porro-reiciendis/actions?query=workflow%3A%22Node+CI%22 "Build Status" [Build

Downloads

1,861

Maintainers

diepminhb311diepminhb311

Keywords

global this valuetranspilercolournegative zerocheckbinariesfunctions@@toStringTagFloat64ArraygroupBybundlingjapanesehasOwnajaxeslintplugineslintconfigmixinswindowsmapreducebundlerwhichelasticachees-shimsrouteseshotwindowcreatesharedrdsschememakeArray.prototype.includesobjectprefixmanagertacitsigintfnmatchnameinternal slotspeedtestingnpmspawnObject.entriesstatecollection.es6ECMAScript 7getoptjsdominputfull-widthcolumnsloggingentriescollectionoptimizerobjirqeventEmittervaluetdddataViewserializerstructuredCloneinspectsameValueZeroasteriskspluginapollojestprivateless mixinssomeoperating-systemvariablesajvUnderscoreinterrupts[[Prototype]]react-hook-formECMAScript 2023fetchownECMAScriptoutputsortedmatchpipeutilextendcurriedArray.prototype.findLastIndexforktypefsstylingvalidatorvisualdeepcloneinferencequotetypedassignECMAScript 2021findstreampropertiespicomatchES2017json-schemaECMAScript 3formsdayjshashPromisesigtermrecursiveES6offsettypesafereduxtypescripteslint-pluginchromecertificateskeyemitECMAScript 2022positivepropharmonyutilsacornclonesuperstructiteratetermopensslutil.inspectpruneoptionslicequeueMicrotasksetImmediateencryptionrangeerrorhookformsubprocesstoStringTagprotobufiewaites8yupgroupbannerzxstoragegatewaysnsdeletetslibindicatordescriptionpinomonorepojsxpropertyclass-validatorECMAScript 2017binaryparseArray.prototype.flattenHyBiansiexectc39System.globalmkdirECMAScript 2020reusequeryidentifiersbuffer-0safetypedarraysMicrosoftframerStreamsmrupushes2017typedarrayartzodWeakSetwriteArrayBufferclicallbindhas-ownlruxtermserializationgetOwnPropertyDescriptorliveapies-abstractfindLastIndexcjkgesturesES8jshintwarningpostcss-plugincoresymbolhandlercloudfrontbincomparetypesfastcloneWeakMapfantasy-landl10nYAMLhookscirculartrimRightArray.prototype.filtersignalscss-in-jsremoveES2020String.prototype.matchAllprogressprotohelperslesscsspathlinuxglobalbyteLengthAsyncIteratorutilityRegExp.prototype.flagshasECMAScript 2016awsFunction.prototype.namedataviewzerowritableiteratorsidestreamsconcattraverseIteratorRFC-6455requestttyfastcopysetless.jsfile systemmobilegetminimaleffect-tstrimjsdiffawesomesaucewaapiECMAScript 5regular expressionarrayflatMapUint8ClampedArrayinternalfileisConcatSpreadableObservableES2015enumerablesyntaxerrorutilitiesReactiveExtensionsreplayconcatMapdefinePropertysymlinkssignalURLSearchParamspolyfilltransportcommandassertcallboundpnpm9movephoneenderisformsetPrototypeOflockfileObject.valuesmkdirsStreamschemalinkcolorssymbolsdirectoryMapcommanderserverhigher-ordercontains.envomitequalhandlershttpsnativeloadingstringifierstarterregular-expressionArrayBuffer#sliceObject.definePropertygraphqljsones7deepcopyiterationglobTypeBoxdescriptortoArray0real-timemetadataflattenefficientnegativeSymbol.toStringTagerrorfunction.lengthWebSocketsspringurlinReflect.getPrototypeOfinstalltrimEndString.prototype.trimec2locationstringifyback-enddatastructureweakmapletpoint-freerandomcss lessregexcallbrowserlistespreetyped arraycolorvalidateinstallerboundequalitysignedexpresstesterscheme-validationmodulesES2021tsjson-schema-validationnpmignorestylesheetimportArray.prototype.flatMapfixed-widthJSON-Schemajson-schema-validatorfront-enddeep-copyimmerredactvalidyamlanimationObject.ises2016react-hooksdependenciesObject.getPrototypeOfshellshrinkwrapObservablesdescriptors3d256expressionUint16Arrayprivate dataperformantrapid

Readme

Putout NPM version Build Status Coverage Status DeepScan

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

🐊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:

putout

Table of contents

🤷‍♂️ 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… 🤫

Drop-in ESLint replacement

🐊Putout in addition to own format .putout.json supports both eslint.config.js and .eslintrc.json, it has ability to autodect format you use. Also it works good with monorepository, since it uses eslint.config.js that is closer to linting file, instead of cwd of ESLint run.

🙏 Whom should I thank for this project exist?

If I have seen further, it is by standing upon the shoulders of giants.

(c) Isaac 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 💻:

🚚 Installation

To install 🐊Putout as a development dependency, run:

npm i putout -D 

Make sure that you are running a relatively recent (≥16) version of Node.

🎙 Usage

Grown-ups never understand anything by themselves, and it is tiresome for children to be always and forever explaining things to them.

(c) Antoine de Saint-Exupéry

🐊Putout tries to be clear and likes a lot to explain things. So when you write putout --help most likely you will hear gladly purr :

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 possible transform places in a folder named lib, run:

npx putout lib

To find possible transform places in multiple folders, such as folders named lib and test, run:

npx putout lib test

To apply the transforms, use --fix:

npx putout lib test --fix

☝️Commit your code before running 🐊Putout

Developers, myself included, usually prefer to make all code changes manually, so that nothing happens to our code without reviewing it first. That is until we trust a tool to make those changes safely for us. An example is WebStorm, which we trust when renaming a class or a method. Since 🐊Putout may still feel like a new tool, not all of us will be able to trust it immediately.

A good way to gain trust is two run without --fix option, and observe error messages. Another way is to use traditional version control tactics. Before running 🐊Putout you should do a git commit. Then after running 🐊Putout, you’ll be able to inspect the changes it made using git diff and git status. You still have the chance to run git checkout -- . at any time to revert all the changes that 🐊Putout has made. If you need more fine-grained control, you can also use git add -p or git add -i to interactively stage only the changes you want to keep.

Environment variables

🐊Putout supports the following environment variables:

  • PUTOUT_CONFIG_FILE - path to configuration file;
  • PUTOUT_FILES - files that should be processed split by comma (,);

Example:

PUTOUT_FILES=lib,test putout --fix

🦕 Usage with Deno

When you need to run 🐊Putout in Deno, use @putout/bundle:

import putout from 'https://esm.sh/@putout/bundle';
import removeDebugger from 'https://esm.sh/@putout/plugin-remove-debugger?alias=putout:@putout/bundle';
import declare from 'https://esm.sh/@putout/plugin-declare?alias=putout:@putout/bundle';

putout('isFn(fn); debugger', {
    plugins: [
        ['remove-debugger', removeDebugger],
        ['declare', declare],
    ],
});

// returns
({
    code: `const isFn = a => typeof a === 'function';\nisFn(fn);`,
    places: [],
});

📐 What is Ruler?

When you need to change configuration file use Ruler instead of editing the file manually.

Ruler can:

  • putout --enable [rule];
  • putout --disable [rule];
  • putout --enable-all;
  • putout --disable-all;

☝️Remember, Ruler should never be used with --fix, because unclear things makes 🐊 Putout angry and you can find him barking at you:

🐊 '--fix' cannot be used with ruler toggler ('--enable', '--disable')

✂️ How Ruler can help me?

You may want to convert your CommonJS to ESM since node v12 supports it without a flag.

🚁 Convert CommonJS to ESM

☝️ I have a package.json

Well, if you have no type field or type=commonjs your package will be converted to CommonJS automatically. To convert to ESM just set type=module.

☝️ I have .cjs or .mjs files

They will be converted automatically to CommonJS and ESM accordingly.

☝️ I want to run only one rule

Let's suppose you have a file called index.js:

const unused = 5;

module.exports = function() {
    return promise();
};

async function promise(a) {
    return Promise.reject(Error('x'));
}

You call putout --fix index.js and see that file is changed:

'use strict';

module.exports = async function() {
    return await promise();
};

async function promise() {
    throw Error('x');
}

But for some reason you don't want so many changes.

☝️ Remember, safe mode of eslint-plugin-putout has the most dangerous rules disabled, so it can be used as auto fix on each save in your IDE.

So, if you want to convert it to ESM keeping everything else untouched use Ruler: it can easily disable all rules 🐊Putout finds.

putout index.js --disable-all will find next errors:

 1:4   error   'unused' is defined but never used                        remove-unused-variables
 7:23  error   'a' is defined but never used                             remove-unused-variables
 3:0   error   Use arrow function                                        convert-to-arrow-function
 1:0   error   Add missing 'use strict' directive on top of CommonJS     mode/add-missing
 8:4   error   Reject is useless in async functions, use throw instead   promises/convert-reject-to-throw
 4:11  error   Async functions should be called using 'await'            promises/add-missing-await
 7:0   error   Avoid useless async                                       promises/remove-useless-async

It will create config file .putout.json:

{
    "rules": {
        "remove-unused-variables": "off",
        "convert-to-arrow-function": "off",
        "nodejs/strict-mode-add-missing": "off",
        "promises/convert-reject-to-throw": "off",
        "promises/add-missing-await": "off",
        "promises/remove-useless-async": "off"
    }
}

Then running putout index.js --enable nodejs/convert-commonjs-to-esm will update config with:

{
    "rules": {
        "remove-unused-variables": "off",
        "convert-to-arrow-function": "off",
        "nodejs/strict-mode-add-missing": "off",
        "promises/convert-reject-to-throw": "off",
        "promises/add-missing-await": "off",
-       "promises/remove-useless-async": "off"
+       "promises/remove-useless-async": "off",
+       "nodejs/convert-commonjs-to-esm": "on"
    }
}

Then putout --fix index.js will do the thing and update index.js with:

const unused = 5;

export default function() {
    return promise();
}

async function promise(a) {
    return Promise.reject(Error('x'));
}

So in case of src directory, it will look like:

putout src --disable-all && putout src --enable nodejs/convert-commonjs-to-esm && putout src --fix

This command will disable all rules that 🐊Putout can find right now and enable a single rule. All built-in rules made for good and highly suggested to be used, all of them are enabled in all my repositories, since they have auto fix.

☝️You can always disable what you don't need, so give it a try. You won't regret 🐊.

Happy coding 🎈!

🏛 Architecture

🐊Putout consists of a couple simple parts, here is a workflow representation:

putout

And here is a CLI scheme:

putout

🌲 The Tree of Syntax

The wise speak of the perennial Ashvattha tree, which has roots above and branches below. The leaves protecting it are the Vedas. One who knows this, truly knows. The tender sprouts of this mighty tree are the senses nourished by the gunas. The branches extend both above and below. The secondary roots going downward represent actions that bind the individual soul to earthly existence.

(c) “Bhagavatgita”, chapter 15

Ashvattha

On the bottom level of 🐊Putout layes down Syntax Tree. This is data structure that makes it possible to do crazy transformations in a simplest possible way. It is used mostly in compilers development.

You can read about it in Babel Plugin Handbook. To understand how things work from the inside take a look at Super Tiny Compiler.

Preoccupied with a single leaf, you won't see the tree. Preoccupied with a single tree, you'll miss the entire forest. When you look at a tree, see it for its leaves, its branches, its trunk and the roots, then and only then will you see the tree.

(c) Takuan Soho, "The Unfettered Mind: Writings of the Zen Master to the Sword Master"

Consider next piece of code:

hello = 'world';

It looks this way in ESTree JavaScript syntax format:

{
    "type": "AssignmentExpression",
    "operator": "=",
    "left": {
        "type": "Identifier",
        "name": "hello"
    },
    "right": {
        "type": "StringLiteral",
        "value": "world"
    }
}

When one is not capable of true intelligence, it is good to consult with someone of good sense. An advisor will fulfill the Way when he makes a decision by selfless and frank intelligence because he is not personally involved. This way of doing things will certainly be seen by others as being strongly rooted. It is, for example, like a large tree with many roots.

(c) Yamamoto Tsunetomo "Hagakure"

🐊Putout based on Babel AST. It has a couple of differences from ESTree which are perfectly handled by estree-to-babel.

☝️ You can get more information about AST in The Book of AST.

🌴 Laws of the Jungle

  • 🐅 engines chilling with engines, and chasing plugins, processors, operators;
  • 🦌 plugins chilling with plugins and operators via require('putout').operator;
  • 🦒 processors chilling with processors;
  • 🐃 operators chilling with operators;

💚 Engines

Engines is the heart of 🐊Putout: Parser, Loader and Runner are running for every processed file. Processor runs all the processors.

| Package | Version | |--------|-------| | @putout/engine-parser | npm | | @putout/engine-loader | npm | | @putout/engine-runner | npm | | @putout/engine-processor | npm | | @putout/engine-reporter | npm |

🧪 Processors

With help of processors 🐊Putout can be extended to read any file format and parse JavaScript from there.

Here is a list of built-int processors:

| Package | Version | |--------|-------| | @putout/processor-javascript | npm | | @putout/processor-json | npm | | @putout/processor-markdown | npm | | @putout/processor-ignore | npm | | @putout/processor-yaml | npm | | @putout/processor-css | npm | | @putout/processor-filesystem | npm |

You can disable any of them with:

{
    "processors": [
        ["markdown", "off"]
    ]
}

Not bundled processors:

| Package | Version | |--------|-------| | @putout/processor-typescript | npm | | @putout/processor-html | npm | | @putout/processor-wasm | npm |

External processors:

| Package | Version | |--------|-------| | putout-processor-typos | npm |

To enable, install and use:

{
    "processors": [
        ["typescript", "on"]
    ]
}

Processors can be tested using @putout/test/processors.

🏗 API

In one’s life there are levels in the pursuit of study. In the lowest level, a person studies but nothing comes of it, and he feels that both he and others are unskillful. At this point he is worthless. In the middle level he is still useless but is aware of his own insufficiencies and can also see the insufficiencies of others. At a higher level, he has pride concerning his own ability, rejoices in praise from others, and laments the lack of ability in his fellows. This man has worth. At the highest level a man has the look of knowing nothing.

(c) Yamamoto Tsunetomo "Hagakure"

In the similar way works 🐊Putout API: it has no plugins defined, tabula rasa.

putout(source, options)

First things first, require putout:

const putout = require('putout');

Let's consider the next source with two VariableDeclarations and one CallExpression:

const hello = 'world';
const hi = 'there';

console.log(hello);

We can declare it as source:

const source = `
    const hello = 'world';
    const hi = 'there';
    
    console.log(hello);
`;

Plugins

🐊Putout supports dynamic loading of plugins from node_modules. Let's consider example of using the remove-unused-variables plugin:

putout(source, {
    plugins: [
        'remove-unused-variables',
    ],
});

// returns
({
    code: `\n    const hello = 'world';\n\n    console.log(hello);\n`,
    places: [],
});

As you see, places is empty, but the code is changed: there is no hi variable.

No fix

From the beginning, 🐊Putout developed with ability to split the main process into two concepts: find (find places that could be fixed) and fix (apply the fixes to the files). It is therefore easy to find sections that could be fixed. In the following example redundant variables are found without making changes to the source file:

putout(source, {
    fix: false,
    plugins: [
        'remove-unused-variables',
    ],
});

// returns
({
    code: '\n' + `    const hello = 'world';\n` + `    const hi = 'there';\n` + '    \n' + '    console.log(hello);\n',
    places: [{
        rule: 'remove-unused-variables',
        message: '"hi" is defined but never used',
        position: {
            line: 3,
            column: 10,
        },
    }],
});

🗺 Source map

Source maps are embedded in the generated source using a special comment. These comments may contain the entire source map, using a Data URI, or may reference an external URL or file.

(c) Source maps in Node.js

In our case Data URL used. Here is an example of source map:

{
    "version": 3,
    "file": "out.js",
    "sourceRoot": "",
    "sources": [
        "foo.js",
        "bar.js"
    ],
    "names": [
        "src",
        "maps",
        "are",
        "fun"
    ],
    "mappings": "AAgBC,SAAQ,CAAEA"
}

To generate source map you need to pass:

  • sourceFileName;
  • sourceMapName;
putout(source, {
    fix: false,
    sourceFileName: 'hello.js',
    sourceMapName: 'world.js',
    plugins: [
        'remove-unused-variables',
    ],
});

// returns
({
    code: `
        const hello = 'world';
        const hi = 'there';
        console.log(hello);
        //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJ...
    `,
    places: [{
        rule: 'remove-unused-variables',
        message: '"hi" is defined but never used',
        position: {
            line: 3,
            column: 10,
        },
    }],
});

🏨 Built-in transformations

JavaScript

  function show() {
-     const message = 'hello';
      console.log('hello world');
  }
-for (const {a, b} of c) {
+for (const {a} of c) {
    console.log(a);
}
-let a;
- a = 1;
let b;
b = 2;
console.log(b);
const a = {
-   x: 'hello',
-   ...y,
    x: 'world',
    ...y,
}
switch (x) {
    case 5:
        console.log('hello');
        break;
-   case 5:
-       console.log('zz');
-       break;
}
  class Hello {
    #a = 5;
-   #b = 3;
    get() {
        return this.#a;
    };
}
  function show(error) {
-     showError;
  }
-   function hi(a) {
-       const b = a;
    };
+   function hi(b) {
    };
-const load = stub().rejects(assign(Error('LOAD USED')));
+const load = stub().rejects(Error('LOAD USED'));
-const a = 'hello'.replace(world, world);
+const a = 'hello';
-new Error('something when wrong');
+Error('something when wrong');
-const map = Map();
+const map = new Map();
-const s = String('hello');
+const s = 'hello';
-const [str] = lines.map((line) => `hello ${line}`);
+const [line] = lines;
+const str = `hello ${line}`;
-for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
-    continue;
+for (sign = decpt, i = 0; (sign /= 10) != 0; i++);
-a = a + b;
+a += b;
-module.exports.traverse = ({push}) => {
-    return {
-        ObjectExpression(path) {
-        }
-    }
-};
+module.exports.traverse = ({push}) => ({
+    ObjectExpression(path) {
+    }
+});
-A[[B]];
+A[B];
-const a = Array(1, 2, 3);
+const a = [1, 2, 3];
-if (zone?.tooltipCallback) {
-    zone.tooltipCallback(e);
-}
+zone?.tooltipCallback(e);
-const a = Boolean(b.includes(c));
+const a = b.includes(c);

--if (!!a)
++if (a)
    console.log('hi');
-const f = (...a) => fn(...a);
-array.filter((a) => a);

+const f = fn;
+array.filter(Boolean);
- typeof typeof 'hello';
+ typeof 'hello';
-const {compare} = operator;
import {operator} from 'putout';
+const {compare} = operator
-const [arg] = process.argv;
import esbuild from 'esbuild';
+const [arg] = process.argv;
+const fs = import 'fs/promises';
+const {stub} = import 'supertape';
+const {assign} = Object;

const readFile = stub();
assign(fs, {
    readFile,
});
onIfStatement({
    push,
-   generate,
-   abc,
})

function onIfStatement({push}) {
}
-let y = `${"hello"} + ${"world"}`;
+let y = `hello + world`;
-for (const a of ['hello']) {
-    console.log(a);
-}
+console.log('hello');
-for (const [, element] of array.entries()) {
-}
+for (const element of array) {
+}
const putout = require('putout');
-const {operator} = require('putout');
+const {operator} = putout;
-const createRegExp = (a) = RegExp(a, 'g');
+const createRegExp = (a) => RegExp(a, 'g');
-if (a = 5) {
+if (a === 5) {
}
-const a = 'hello \'world\'';
+const a = `hello 'world'`;
+const isFn = (a) => typeof a === 'function';
+
+if (isFn(fn))
-if (typeof fn === 'function')
    fn();
-a | !b
+a || !b
-if (a == b) {
+if (a === b) {
}
-const t = 'hello \"world\"';
-const s1 = `hello \"world\"`;
-const s = `hello \'world\'`;
+const t = 'hello "world"';
+const s1 = `hello "world"`;
+const s = `hello 'world'`;
-const a = () => {
-    hello: 'world'
-}
+const a = () => ({
+    hello: 'world'
+})
-for (const x of Array.from(y)) {}
+for (const x of y) {}
-for (const x of [...y]) {}
+for (const x of y) {}
- debugger;
-(function() {
-    console.log('hello world');
-}());
+console.log('hello world');
-if (a === true)
+if (a)
    alert();
-const t = true && false;
+const t = false;
for (const x of Object.keys(a)) {
-   {
-       console.log(x);
-   }
+   console.log(x);
}
function hi() {
    return 5;
-   console.log('hello');
}
-let a, b;
+let a;
+let b;
-const {a: {b}} = c;
+const {a} = c;
+const {b} = a;
-const {a} = {a: 5};
-const [b] = [5];
+const a = 5;
+const b = 5;
function isA(a, b) {
-    if (a.length === b.length)
-        return true;
-
-   return false;
+   return a.length === b.length;
}
-!(options && !options.bidirectional);
+!options || options.bidirectional;
-module.exports = fs.copyFileSync ? fs.copyFileSync : copyFileSync;
+module.exports = fs.copyFileSync || copyFileSync;
-console.log('hello');
-if (x > 0) {
-}
-const {} = process;
function hi(a) {
-   if (2 < 3) {
-       console.log('hello');
-       console.log('world');
-   }
+   console.log('hello');
+   console.log('world');
};

function world(a) {
-   if (false) {
-       console.log('hello');
-       console.log('world');
-   }
};
-'hello'.replace(/hello/g, 'world');
+'hello'.replaceAll('hello', 'world');
-if (a)
+if (a) {
    b();
+} else {
-else {
    c();
    d();
}
-const hello = world.hello;
-const a = b[0];
+const {hello} = world;
+const [a] = b;
-a['hello']['world'] = 5;
+a.hello.world = 5;
const {a = ''} = b;
-!a.indexOf('>');
+a.startsWith('>');
-export const readRules = (dirOpt, rulesDir, {cwd, readdirSync}) => {}
+export const readRules = (dirOpt, rulesDir, overrides) => {
    const {cwd, readdirSync} = overrides;
+}
+import a1 from 'a1';
import {
    a,
    b,
    c,
    d,
} from 'd';
-import a1 from 'a1';
-const line = 'hello' + world;
+const line = `hello${world}`
-array.map(getId).flat();
+array.flatMap(getId);
-if (2 > 3);
+if (2 > 3)
    alert();
-x instanceof Array;
+Array.isArray(x);
-const latest = (a) => a[a.length - 1];
+const latest = (a) => a.at(-1);
-const result = hello && hello.world;
+const result = hello?.world;
-result = typeof result  === 'undefined' ? 'hello': result;
result = result ?? 'hello';
-const fn = (a) => {throw Error(a);}
+const fn = (a) => throw Error(a);
-const {one} = require('numbers'):
-const {two} = require('numbers');
+ const {
+   one,
+   two
+} = require('numbers');
-import {m as b} from 'y';
-import {z} from 'y';
-import x from 'y';
+import x, {m as b, z} from 'y';
const isFn = (a) => typeof a === 'function';
-const isFn1 = (a) => typeof a === 'function';

isFn(1);
-isFn1(2);
+isFn(2);
-if (a > b)
-    if (b < c)
-        console.log('hi');
+if (a > b && b < c)
+    console.log('hi');
-module.exports = function(a, b) {
+module.exports = (a, b) => {
}
-for (let i = 0; i < items.length; i++) {
+for (const item of items) {
-   const item = items[i];
    log(item);
}
-Object.keys(json).forEach((name) => {
+for (const name of Object.keys(json)) {
    manage(name, json[name]);
-});
+}
-for (const name in object) {
-   if (object.hasOwnProperty(name)) {
+for (const name of Object.keys(object)) {
    console.log(a);
-   }
}
-names.map((name) => {
+for (const name of names) {
    alert(`hello ${name}`);
+}
-});
-const result = list.reduce((a, b) => a + b, 1);
+let sum = 1;
+for (const a of list) {
+   sum += a;
+}
-const places = [
-    ...items,
-];
+const places = items.slice();
-module.exports.x = 1,
-module.exports.y = 2;
+module.exports.x = 1;
+module.exports.y = 2;
-const {replace} = putout.operator;
-const {isIdentifier} = putout.types;
+const {operator, types} = putout;
+const {replace} = operator;
+const {isIdentifier} = types;
-console.log.apply(console, arguments);
+console.log(...arguments);
-[].concat(...array);
+array.flat();
-function hello() {
-    console.log(arguments);
+function hello(...args) {
+    console.log(args);
}
function merge(a) {
-   return Object.assign({}, a, {
-       hello: 'world'
-   });
+   return {
+       ...a,
+       hello: 'world'
+   };
};
-   const a = b === b;
+   const a = true;
-5 === a;
+a === 5;
-   const a = 5;
+   let a = 5;
    a = 3;

Promises

-   await await Promise.resolve('hello');
+   await Promise.resolve('hello');
-const show = async () => {
+const show = () => {
    console.log('hello');
};
-runCli();
+await runCli();

async function runCli() {
}
-function hello() {
+async function hello() {
    await world();
}
async run () {
-   return promise();
+   return await promise();
}
import fs from 'fs';

-(async () => {
-    const data = await fs.promises.readFile('hello.txt');
-})();
+const data = await fs.promises.readFile('hello.txt');
async () => {
-    return Promise.resolve('x');
+    return 'x';
}
async () => {
-    return Promise.reject('x');
+    throw 'x';
}
-const {readFile} = import('fs/promises');
+const {readFile} = await import('fs/promises');

Math

-const a = 100000000;
+const a = 100_000_000;
-const a = Math.sqrt(b ** 2 + c ** 2);
+const a = Math.hypot(a, b);
- const a = Math.imul(b, c);
+ const a = b * c;
-Math.pow(2, 4);
+2 ** 4;

Node.js

-'use strict';
-
import * from fs;
+'use strict';
+
const fs = require('fs');
+'use strict';
+
const fs = require('fs');
-'use strict';
-
import * from fs;
+'use strict';
+
const fs = require('fs');
-'use strict';
-
import * from fs;
+'use strict';
+
const fs = require('fs');
-'use strict';
-
import * from fs;
+'use strict';
+
const fs = require('fs');
-import hello from 'world';
+const hello = require('world');
-const hello = require('world');
+import hello from 'world';
-const {readFile} = require('fs').promises;
+const {readFile} = require('fs/promises');
-   return;
+   process.exit();
-process.exit();

Tape

-test.only('some test here', (t) => {
+test('some test here', (t) => {
    t.end();
});
-test.skip('some test here', (t) => {
+test('some test here', (t) => {
    t.end();
});

TypeScript

-type x = boolean[] | A | string | A | string[] | boolean[];
+type x = boolean[] | A | string | string[];
interface A {
-    x: Array<X>;
+    x: X[];
}
-const x: any = 5;
+const x = 5;
-type SuperType = {
-   [Key in keyof Type]: Type[Key]
-}
+type SuperType = Type;
type SuperType = {
-   +readonly[Key in keyof Type]+?: Type[Key];
+   readonly[Key in keyof Type]?: Type[Key];
}
type oldType = number;
-type newType = oldType;
-const x: newType = 5;
+const x: oldType = 5;
interface Hello {
-   'hello': any;
    'hello': string;
}
type n = number;
-type s = string;
const x: n = 5;
-const boundaryElement = <HTMLElement>e.target;
+const boundaryElement1 = e.target as HTMLElement;
-type SuperType = {
-    [Key in keyof Type]?: Type[Key];
-}
+type SuperType = Partial<Type>;

🏟 Plugins

The 🐊Putout repo is comprised of many npm packages. It is a Lerna monorepo similar to Babel. It has a lot of plugins divided by groups:

Appliers

| Package | Version | |--------|-------| | @putout/plugin-apply-consistent-blocks | npm | | @putout/plugin-apply-at | npm | | @putout/plugin-apply-dot-notation | npm | | @putout/plugin-apply-starts-with | npm | | @putout/plugin-apply-flat-map | npm | | @putout/plugin-apply-destructuring | npm | | @putout/plugin-apply-optional-chaining | npm | | @putout/plugin-apply-early-return | npm | | @putout/plugin-apply-template-literals | npm | | @putout/plugin-apply-overrides | npm |

Sorters

| Package | Version | |--------|-------| | @putout/plugin-sort-imports-by-specifiers | npm |

Splitters

| Package | Version | |--------|-------| | @putout/plugin-split-assignment-expressions | npm | | @putout/plugin-split-variable-declarations | npm | | @putout/plugin-split-nested-destructuring | npm |

Mergers

| Package | Version | |--------|-------| | @putout/plugin-merge-destructuring-properties | npm | | @putout/plugin-merge-duplicate-imports | npm | | @putout/plugin-merge-duplicate-functions | npm |

Converters

| Package | Version | |--------|-------| | @putout/plugin-convert-arguments-to-rest | npm | | @putout/plugin-convert-apply-to-spread | npm | | @putout/plugin-convert-quotes-to-backticks | npm | | @putout/plugin-convert-concat-to-flat | npm | | @putout/plugin-convert-array-copy-to-slice | npm | | @putout/plugin-convert-template-to-string | npm | | @putout/plugin-convert-index-of-to-includes | npm | | @putout/plugin-convert-to-arrow-function | npm | | @putout/plugin-convert-object-assign-to-merge-spread | npm | | @putout/plugin-convert-optional-to-logical | npm | | @putout/plugin-convert-assignment-to-arrow-function | npm | | @putout/plugin-convert-assignment-to-comparison | npm | | @putout/plugin-convert-const-to-let | npm | | @putout/plugin-convert-object-entries-to-array-entries | npm | | @putout/plugin-convert-label-to-object | npm |

Removers

| Package | Version | |--------|-------| | @putout/plugin-remove-unused-variables | npm | | @putout/plugin-remove-unreferenced-variables | npm | | @putout/plugin-remove-duplicate-keys | npm | | @putout/plugin-remove-duplicate-case | npm | | @putout/plugin-remove-unused-expressions | npm | | @putout/plugin-remove-unused-private-fields | npm | | @putout/plugin-remove-useless-variables | npm | | @putout/plugin-remove-useless-assign | npm | | @putout/plugin-remove-useless-replace | npm | | @putout/plugin-remove-useless-map | npm | | @putout/plugin-remove-useless-constructor | npm | | @putout/plugin-remove-useless-return | npm | | @putout/plugin-remove-useless-continue | npm | | @putout/plugin-remove-useless-operand | npm | | @putout/plugin-remove-useless-array | npm | | @putout/plugin-remove-useless-array-constructor | npm | | @putout/plugin-remove-useless-functions | npm | | @putout/plugin-remove-useless-spread | npm | | [@putout/plugin-remove-useless-array-entries](/packages/plugin-remove-useless-array-en