{"id":13447610,"url":"https://github.com/coderaiser/putout","last_synced_at":"2026-03-10T01:14:02.443Z","repository":{"id":37396877,"uuid":"159849469","full_name":"coderaiser/putout","owner":"coderaiser","description":"🐊  Pluggable and configurable JavaScript Linter, code transformer and formatter with superpowers 💪: built-in support of js, jsx, ts, markdown, yaml, toml, json and ignore. Write declarative codemods in a simplest possible way 😏","archived":false,"fork":false,"pushed_at":"2026-03-06T17:51:20.000Z","size":23818,"stargazers_count":782,"open_issues_count":0,"forks_count":45,"subscribers_count":8,"default_branch":"master","last_synced_at":"2026-03-06T21:01:32.980Z","etag":null,"topics":["ast","babel","babel-plugin","codemod","codemods","codeshift","eslint","eslint-plugin","eslint-rules","hacktoberfest","javascript","linter","nodejs","parser","plugin","putout","putout-plugin","recast","static-code-analysis","transform"],"latest_commit_sha":null,"homepage":"https://putout.cloudcmd.io/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coderaiser.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"coderaiser","open_collective":"cloudcmd","ko_fi":"coderaiser"}},"created_at":"2018-11-30T16:24:14.000Z","updated_at":"2026-03-06T17:51:23.000Z","dependencies_parsed_at":"2026-02-04T20:06:14.436Z","dependency_job_id":null,"html_url":"https://github.com/coderaiser/putout","commit_stats":{"total_commits":14072,"total_committers":26,"mean_commits":541.2307692307693,"dds":0.08314383172256967,"last_synced_commit":"f79a0ccb180d0d2b12e7b31ebaf39cf14c213695"},"previous_names":[],"tags_count":1483,"template":false,"template_full_name":null,"purl":"pkg:github/coderaiser/putout","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderaiser%2Fputout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderaiser%2Fputout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderaiser%2Fputout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderaiser%2Fputout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coderaiser","download_url":"https://codeload.github.com/coderaiser/putout/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coderaiser%2Fputout/sbom","scorecard":{"id":297413,"data":{"date":"2025-08-11","repo":{"name":"github.com/coderaiser/putout","commit":"03e2e3d6219f2868e457e05416819a24555406b6"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.8,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/nodejs-pr.yml:1","Warn: no topLevel permission defined: .github/workflows/nodejs.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs-pr.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/coderaiser/putout/nodejs-pr.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/nodejs-pr.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/coderaiser/putout/nodejs-pr.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs-pr.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/coderaiser/putout/nodejs-pr.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs-pr.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/coderaiser/putout/nodejs-pr.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/coderaiser/putout/nodejs.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/nodejs.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/coderaiser/putout/nodejs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/coderaiser/putout/nodejs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/coderaiser/putout/nodejs.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/nodejs.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/coderaiser/putout/nodejs.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/nodejs.yml:57: update your workflow using https://app.stepsecurity.io/secureworkflow/coderaiser/putout/nodejs.yml/master?enable=pin","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}}]},"last_synced_at":"2025-08-17T19:53:36.979Z","repository_id":37396877,"created_at":"2025-08-17T19:53:36.979Z","updated_at":"2025-08-17T19:53:36.979Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30209910,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T05:23:27.321Z","status":"ssl_error","status_checked_at":"2026-03-07T05:00:17.256Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ast","babel","babel-plugin","codemod","codemods","codeshift","eslint","eslint-plugin","eslint-rules","hacktoberfest","javascript","linter","nodejs","parser","plugin","putout","putout-plugin","recast","static-code-analysis","transform"],"created_at":"2024-07-31T05:01:22.323Z","updated_at":"2026-03-10T01:14:02.425Z","avatar_url":"https://github.com/coderaiser.png","language":"JavaScript","readme":"# Putout [![NPM version][NPMIMGURL]][NPMURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Coverage Status][CoverageIMGURL]][CoverageURL] [![DeepScan][DeepScanIMGURL]][DeepScanURL]\n\n[NPMURL]: https://npmjs.org/package/putout \"npm\"\n[NPMIMGURL]: https://img.shields.io/npm/v/putout.svg?style=flat\u0026longCache=true\n[BuildStatusURL]: https://github.com/coderaiser/putout/actions?query=workflow%3A%22Node+CI%22 \"Build Status\"\n[BuildStatusIMGURL]: https://github.com/coderaiser/putout/workflows/Node%20CI/badge.svg\n[CoverageURL]: https://coveralls.io/github/coderaiser/putout?branch=master\n[CoverageIMGURL]: https://coveralls.io/repos/coderaiser/putout/badge.svg?branch=master\u0026service=github\n[DeepScanURL]: https://deepscan.io/dashboard#view=project\u0026tid=16903\u0026pid=20211\u0026bid=545558\n[DeepScanIMGURL]: https://deepscan.io/api/teams/16903/projects/20211/branches/545558/badge/grade.svg\n\n\u003e **Perfection is finally attained not when there is no longer anything to add,\n\u003e but when there is no longer anything to take away.**\n\u003e\n\u003e **(c) Antoine de Saint Exupéry**\n\n![putout](https://github.com/coderaiser/putout/blob/master/images/putout-logo.svg)\n\n🐊**Putout** is a JavaScript Linter, pluggable and configurable code transformer, drop-in **ESLint** replacement with built-in [code printer](https://github.com/putoutjs/printer#readme) and ability to [fix syntax errors](https://github.com/coderaiser/putout/blob/master/docs/syntax-errors.md#%EF%B8%8F-syntax-errors). It has [a lot of transformations](#-built-in-transformations) that keeps your codebase in a clean state, removing any code smell and making code readable according to best practices.\n\nThe main target is **JavaScript**, but:\n\n- ✅ JSX;\n- ✅ TypeScript;\n- ✅ Yaml;\n- ✅ Markdown;\n- ✅ JSON;\n- ✅ Ignore;\n\nare also supported. Here is how it looks like:\n\n[![putout](https://asciinema.org/a/0akg9gkJdbmbGl6BbpaycgKZm.svg)](https://asciinema.org/a/0akg9gkJdbmbGl6BbpaycgKZm)\n\n## Table of contents\n\n- [🤷‍♂️ In doubt about using 🐊Putout?](#%EF%B8%8F-in-doubt-about-using-putout)\n- [🙏 Whom should I thank for this project exist?](#-whom-should-i-thank-for-this-project-exist)\n- [🤷‍♂️ Why does this project exist?](#%EF%B8%8F-why-does-this-project-exist)\n- [🪬Core Concepts](https://github.com/coderaiser/putout/blob/master/docs/core-concepts.md#-core-concepts)\n- [🚚 Installation](#-installation)\n- [🎙 Usage](#-usage)\n- [🦕 Usage with Deno](#-usage-with-deno)\n- [📐 What is **Ruler**?](#-what-is-ruler)\n- [✂️ How **Ruler** can help me?](#%EF%B8%8F-how-ruler-can-help-me)\n- [🚁 Convert `CommonJS` to `ESM`](#-convert-commonjs-to-esm)\n- [🏛 Architecture](#-architecture)\n- [🌲 The Tree of Syntax](#-the-tree-of-syntax)\n- [🌴 Laws of the Jungle](#-laws-of-the-jungle)\n- [🏗 API](#-api)\n- [🏨 Built-in transformations](#-built-in-transformations)\n- [🛠️ Syntax errors](https://github.com/coderaiser/putout/blob/master/docs/syntax-errors.md#%EF%B8%8F-syntax-errors)\n- [🏟 Plugins](#-plugins)\n- [🦚 Formatters](#-formatters)\n- [🦉 Configuration](#-configuration)\n- [🧬 Plugins API](#-plugins-api)\n- [🛴 codemods](#-codemods)\n- [💾 rulesdir](#-rulesdir)\n- [⏣ Integration with ESLint](#-integration-with-eslint)\n- [☄️ Integration with Babel](#%EF%B8%8F-integration-with-babel)\n- [🐈 Integration with Yarn](#-integration-with-yarn)\n- [⛓ Using Putout as Loader](#-using-putout-as-loader)\n- [🚪 Exit Codes](#exit-codes)\n- [🦔 Real-world uses](#-real-world-uses)\n- [📻 Versioning policy](#-versioning-policy)\n- [🚀 I want contribute](#-i-want-contribute)\n- [🍄 License](#-license)\n\n## 🤷‍♂️ In doubt about using 🐊Putout?\n\nCheck out couple variants of plugins that does the same: [**linting debugger statement**](https://putout.cloudcmd.io/#/gist/f61ba31fe534868d49eba9b946f3ed4b/5ef6863d9cf4826666782ae0eea5cb5def266bbd):\n\n- ❌ SWCLint [no-debugger](https://github.com/swc-project/swc/blob/v1.2.138/crates/swc_ecma_lints/src/rules/no_debugger.rs): **49** lines;\n- ❌ RSLint [no-debugger](https://github.com/rslint/rslint/blob/v0.3.0/crates/rslint_core/src/groups/errors/no_debugger.rs): **48** lines;\n- ❌ ESLint [no-debugger](https://github.com/eslint/eslint/blob/2dc38aa653f1d5137a9abf82024c67a11620bb7c/lib/rules/no-debugger.js): **43** lines;\n- ❌ Rome [no-debugger](https://github.com/rome/tools/blob/4d5a99ce98e987cbd03f3ab6b38fa22d00bbfe27/packages/%40romejs/js-compiler/transforms/lint/noDebugger.ts): **28** lines;\n- 🐊 **Putout** [remove-debugger](https://github.com/coderaiser/putout/blob/v24.6.0/packages/plugin-remove-debugger/lib/remove-debugger.js): **7** lines:\n\n```js\n'use strict';\n\nmodule.exports.report = () =\u003e `Unexpected 'debugger' statement`;\n\nmodule.exports.replace = () =\u003e ({\n    debugger: '',\n});\n```\n\n*Choose wisely, competitors cannot even fix…* 🤫\n\n### Drop-in ESLint replacement\n\n🐊**Putout** in addition to own format [`.putout.json`](#-configuration) supports both `eslint.config.js` and `.eslintrc.json`, it has ability to autodect format you use.\nAlso it works good with monorepository, since it uses `eslint.config.js` that is closer to linting file, instead of `cwd` of ESLint run.\n\n## 🙏 Whom should I thank for this project exist?\n\n\u003e **If I have seen further, it is by standing upon the shoulders of giants.**\n\u003e\n\u003e **(c) Isaac Newton**\n\n- 💪[**ESLint**](https://eslint.org) for stable releases and future proof **API**.\n- 💪[**Babel**](https://babeljs.io) for amazing **API** documented in [**Handbook**](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#babel-plugin-handbook) and responsiveness of a team.\n- 💪[**Prettier**](https://github.com/prettier/prettier) for minimalistic options and uniform codestyle.\n- 💪[**JSCodeshift**](https://github.com/facebook/jscodeshift) for making codemods simple and popular.\n\n## 🤷‍♂️ Why does this project exist?\n\n- ❌[**ESLint**](https://eslint.org) avoids [fixes that could change the runtime behavior](https://eslint.org/docs/developer-guide/working-with-rules#applying-fixes).\n- ❌[**Babel**](https://babeljs.io) has no ability to report errors, it only runs transformations.\n- ❌[**Prettier**](https://github.com/prettier/prettier) is a formatter.\n- ❌[**JSCodeshift**](https://github.com/facebook/jscodeshift) has no **config** and **plugins** support.\n\n🐊**Putout** on the other hand can make more drastic code transformations that directly affects your codebase making it a better place to code 💻:\n\n- ✅ [fixes Reference Errors](https://github.com/coderaiser/putout/tree/master/packages/plugin-declare-before-reference#readme);\n- ✅ [declares variables](https://github.com/coderaiser/putout/tree/master/packages/plugin-declare#readme);\n- ✅ [convert CommonJS to ESM](https://github.com/coderaiser/putout/tree/master/packages/plugin-convert-commonjs-to-esm#readme);\n- ✅ [...and much more 😏!](#-built-in-transformations)\n\n## 🚚 Installation\n\nTo install 🐊**Putout** as a development dependency, run:\n\n```\nnpm i putout -D \n```\n\nMake sure that you are running a relatively recent (≥16) version of Node.\n\n## 🎙 Usage\n\n\u003e **Grown-ups never understand anything by themselves, and it is tiresome for children to be always and forever explaining things to them.**\n\u003e\n\u003e **(c) Antoine de Saint-Exupéry**\n\n🐊**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 :\n\n```\nUsage: putout [options] [path]\nOptions:\n   -h, --help                  display this help and exit\n   -v, --version               output version information and exit\n   -f, --format [formatter]    use a specific output format, the default is: 'progress-bar' locally and 'dump' on CI\n   -s, --staged                add staged files when in git repository\n   -i, --interactive           set lint options using interactive menu\n   --fix                       apply fixes of errors to code\n   --fix-count [count = 10]    count of fixes rounds\n   --rulesdir                  use additional rules from directory\n   --transform [replacer]      apply Replacer, for example 'var __a = __b -\u003e const __a = __b', read about Replacer https://git.io/JqcMn\n   --plugins [plugins]         a comma-separated list of plugins to use\n   --enable [rule]             enable the rule and save it to '.putout.json' walking up parent directories\n   --disable [rule]            disable the rule and save it to '.putout.json' walking up parent directories\n   --enable-all                enable all found rules and save them to '.putout.json' walking up parent directories\n   --disable-all               disable all found rules (set baseline) and save them to '.putout.json' walking up parent directories\n   --match [pattern]           read '.putout.json' and convert 'rules' to 'match' according to 'pattern'\n   --fresh                     generate a fresh cache\n   --no-config                 avoid reading '.putout.json'\n   --no-ci                     disable the CI detection\n   --no-cache                  disable the cache\n   --no-worker                 disable worker thread\n```\n\nTo skip prefix `node_modules/.bin/`, update your `$PATH` variable in with `.bashrc`:\n\n```sh\necho 'PATH=\"$PATH:node_modules/.bin\"' \u003e\u003e ~/.bashrc\nsource ~/.bashrc\n```\n\nTo find possible transform places in a folder named `lib`, run:\n\n```\nputout lib\n```\n\nTo find possible transform places in multiple folders, such as folders named `lib` and `test`, run:\n\n```\nputout lib test\n```\n\nTo apply the transforms, use `--fix`:\n\n```\nputout lib test --fix\n```\n\n### ☝️Commit your code before running 🐊Putout\n\nDevelopers, 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.\n\nA 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.\n\n### Environment variables\n\n🐊**Putout** supports the following environment variables:\n\n- `PUTOUT_CONFIG_FILE` - path to [configuration](#-configuration) file;\n- `PUTOUT_FILES` - files that should be processed split by comma (`,`);\n\nExample:\n\n```\nPUTOUT_FILES=lib,test putout --fix\n```\n\n## 🦕 Usage with **Deno**\n\nWhen you need to run 🐊**Putout** in [**Deno**](https://deno.land/), use [`@putout/bundle`](https://github.com/putoutjs/bundle):\n\n```js\nimport putout from 'https://esm.sh/@putout/bundle';\nimport removeDebugger from 'https://esm.sh/@putout/plugin-remove-debugger?alias=putout:@putout/bundle';\nimport declare from 'https://esm.sh/@putout/plugin-declare?alias=putout:@putout/bundle';\n\nputout('isFn(fn); debugger', {\n    plugins: [\n        ['remove-debugger', removeDebugger],\n        ['declare', declare],\n    ],\n});\n\n// returns\n({\n    code: `const isFn = a =\u003e typeof a === 'function';\\nisFn(fn);`,\n    places: [],\n});\n```\n\n## 📐 What is **Ruler**?\n\nWhen you need to change [configuration](#-configuration) file use **Ruler** instead of editing the file manually.\n\n**Ruler** can:\n\n- ✅ `putout --enable [rule]`;\n- ✅ `putout --disable [rule]`;\n- ✅ `putout --enable-all`;\n- ✅ `putout --disable-all`;\n\n*☝️Remember, **Ruler** should never be used with `--fix`, because unclear things makes 🐊 **Putout** angry and you can find him barking at you:*\n\n```\n🐊 '--fix' cannot be used with ruler toggler ('--enable', '--disable')\n```\n\n## ✂️ How **Ruler** can help me?\n\nYou may want to convert your [`CommonJS`](https://nodejs.org/api/modules.html) to [`ESM`](https://nodejs.org/api/esm.html) since [node v12 supports it without a flag](https://nodejs.org/en/blog/release/v12.17.0).\n\n### 🚁 Convert `CommonJS` to `ESM`\n\n#### ☝️ I have a `package.json`\n\nWell, if you have no `type` field or `type=commonjs` your package will be\nconverted to `CommonJS` automatically. To convert to `ESM` just set `type=module`.\n\n#### ☝️ I have `.cjs` or `.mjs` files\n\nThey will be converted automatically to `CommonJS` and `ESM` accordingly.\n\n#### ☝️ I want to run only one rule\n\nLet's suppose you have a file called `index.js`:\n\n```js\nconst unused = 5;\n\nmodule.exports = function() {\n    return promise();\n};\n\nasync function promise(a) {\n    return Promise.reject(Error('x'));\n}\n```\n\nYou call `putout --fix index.js` and see that file is changed:\n\n```js\n'use strict';\n\nmodule.exports = async function() {\n    return await promise();\n};\n\nasync function promise() {\n    throw Error('x');\n}\n```\n\nBut for some reason you don't want so many changes.\n\n☝️ *Remember, **safe** mode of **[eslint-plugin-putout](https://github.com/coderaiser/putout/tree/master/packages/eslint-plugin-putout#safe-mode)** has the most dangerous rules **disabled**, so it can be used as **auto fix** on each **save** in your **IDE***.\n\nSo, if you want to convert it to [`ESM`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) keeping everything else untouched  use **Ruler**: it can easily disable all rules 🐊**Putout** finds.\n\n`putout index.js --disable-all` will find next errors:\n\n```sh\n 1:4   error   'unused' is defined but never used                        remove-unused-variables\n 7:23  error   'a' is defined but never used                             remove-unused-variables\n 3:0   error   Use arrow function                                        convert-to-arrow-function\n 1:0   error   Add missing 'use strict' directive on top of CommonJS     nodejs/dd-missing-strict-cmode\n 8:4   error   Reject is useless in async functions, use throw instead   promises/convert-reject-to-throw\n 4:11  error   Async functions should be called using 'await'            promises/add-missing-await\n 7:0   error   Avoid useless async                                       promises/remove-useless-async\n```\n\nIt will create config file `.putout.json`:\n\n```json\n{\n    \"rules\": {\n        \"remove-unused-variables\": \"off\",\n        \"convert-to-arrow-function\": \"off\",\n        \"nodejs/add-missing-strict-mode\": \"off\",\n        \"promises/convert-reject-to-throw\": \"off\",\n        \"promises/add-missing-await\": \"off\",\n        \"promises/remove-useless-async\": \"off\"\n    }\n}\n```\n\nThen running `putout index.js --enable nodejs/convert-commonjs-to-esm` will update config with:\n\n```diff\n{\n    \"rules\": {\n        \"remove-unused-variables\": \"off\",\n        \"convert-to-arrow-function\": \"off\",\n        \"nodejs/add-missing-strict-mode\": \"off\",\n        \"promises/convert-reject-to-throw\": \"off\",\n        \"promises/add-missing-await\": \"off\",\n-       \"promises/remove-useless-async\": \"off\"\n+       \"promises/remove-useless-async\": \"off\",\n+       \"nodejs/convert-commonjs-to-esm\": \"on\"\n    }\n}\n```\n\nThen `putout --fix index.js` will do the thing and update `index.js` with:\n\n```js\nconst unused = 5;\n\nexport default function() {\n    return promise();\n}\n\nasync function promise(a) {\n    return Promise.reject(Error('x'));\n}\n```\n\nSo in case of `src` directory, it will look like:\n\n```sh\nputout src --disable-all \u0026\u0026 putout src --enable nodejs/convert-commonjs-to-esm \u0026\u0026 putout src --fix\n```\n\nThis 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.\n\n☝️*You can always disable what you don't need, so give it a try. You won't regret 🐊.*\n\nHappy coding 🎈!\n\n## 🏛 Architecture\n\n🐊**Putout** consists of a couple simple parts, here is a workflow representation:\n\n![putout](https://github.com/coderaiser/putout/blob/master/images/putout.png)\n\nAnd here is a CLI scheme:\n\n![putout](https://github.com/coderaiser/putout/blob/master/images/putout-cli.png)\n\n### 🌲 The Tree of Syntax\n\n\u003e **The wise speak of the perennial Ashvattha tree,\n\u003e which has roots above and branches below.\n\u003e The leaves protecting it are the Vedas.\n\u003e One who knows this, truly knows.**\n\u003e **The tender sprouts of this mighty tree\n\u003e are the senses nourished by the gunas.\n\u003e The branches extend both above and below.\n\u003e The secondary roots going downward represent actions\n\u003e that bind the individual soul to earthly existence.**\n\u003e\n\u003e **(c) “Bhagavatgita”, chapter 15**\n\n![Ashvattha](https://github.com/coderaiser/putout/blob/master/images/ashvattha.jpeg)\n\nOn 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](https://dev.to/viveknayyar/revealing-the-magic-of-ast-by-writing-babel-plugins-1h01). It is used mostly in compilers development.\n\nYou can read about it in [Babel Plugin Handbook](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md). To understand how things work from the inside take a look at [Super Tiny Compiler](https://github.com/jamiebuilds/the-super-tiny-compiler).\n\n\u003e **Preoccupied with a single leaf, you won't see the tree.\n\u003e Preoccupied with a single tree, you'll miss the entire forest.\n\u003e 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.**\n\u003e\n\u003e **(c) Takuan Soho, \"The Unfettered Mind: Writings of the Zen Master to the Sword Master\"**\n\nConsider next piece of code:\n\n```js\nhello = 'world';\n```\n\nIt looks this way in [**ESTree**](https://github.com/estree/estree) **JavaScript** syntax format:\n\n```json\n{\n    \"type\": \"AssignmentExpression\",\n    \"operator\": \"=\",\n    \"left\": {\n        \"type\": \"Identifier\",\n        \"name\": \"hello\"\n    },\n    \"right\": {\n        \"type\": \"StringLiteral\",\n        \"value\": \"world\"\n    }\n}\n```\n\n\u003e **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.**\n\u003e\n\u003e **(c) Yamamoto Tsunetomo \"Hagakure\"**\n\n🐊**Putout** based on [**Babel AST**](https://github.com/babel/babel/blob/main/packages/babel-parser/ast/spec.md#readme). It has a couple of differences from **ESTree** which are perfectly handled by [`estree-to-babel`](https://github.com/coderaiser/estree-to-babel).\n\n☝️ *You can get more information about **AST** in [The Book of AST](https://github.com/coderaiser/putout/blob/master/docs/the-book-of-ast.md#the-book-of-ast).*\n\n### 🌴 Laws of the Jungle\n\n- 🐅 `engines` chilling with `engines`, and chasing `plugins`, `processors`, `operators`;\n- 🦌 `plugins` chilling with `plugins` and `operators` via `require('putout').operator`;\n- 🦒 `processors` chilling with `processors`;\n- 🐃 `operators` chilling with `operators`;\n\n### 💚 Engines\n\n**Engines** is the heart of 🐊**Putout**: **Parser**, **Loader** and **Runner** are running for every processed file. **Processor** runs all the processors.\n\n| Package | Version |\n|--------|-------|\n| [`@putout/engine-parser`](/packages/engine-parser#readme) | [![npm](https://img.shields.io/npm/v/@putout/engine-parser.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/engine-parser) |\n| [`@putout/engine-loader`](/packages/engine-loader#readme) | [![npm](https://img.shields.io/npm/v/@putout/engine-loader.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/engine-loader) |\n| [`@putout/engine-runner`](/packages/engine-runner#readme) | [![npm](https://img.shields.io/npm/v/@putout/engine-runner.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/engine-runner) |\n| [`@putout/engine-processor`](/packages/engine-processor#readme) | [![npm](https://img.shields.io/npm/v/@putout/engine-processor.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/engine-processor) |\n| [`@putout/engine-reporter`](/packages/engine-reporter#readme) | [![npm](https://img.shields.io/npm/v/@putout/engine-reporter.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/engine-reporter) |\n\n### 🧪 Processors\n\nWith help of [processors](https://github.com/coderaiser/putout/blob/master/packages/engine-processor#readme) 🐊**Putout** can be extended to read any file format and parse **JavaScript** from there.\n\nHere is a list of built-in processors:\n\n| Package | Version |\n|--------|-------|\n| [`@putout/processor-javascript`](/packages/processor-javascript#readme) | [![npm](https://img.shields.io/npm/v/@putout/processor-javascript.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/processor-javascript) |\n| [`@putout/processor-json`](/packages/processor-json#readme) | [![npm](https://img.shields.io/npm/v/@putout/processor-json.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/processor-json) |\n| [`@putout/processor-markdown`](/packages/processor-markdown#readme) | [![npm](https://img.shields.io/npm/v/@putout/processor-markdown.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/processor-markdown) |\n| [`@putout/processor-ignore`](/packages/processor-ignore#readme) | [![npm](https://img.shields.io/npm/v/@putout/processor-ignore.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/processor-ignore) |\n| [`@putout/processor-yaml`](/packages/processor-yaml#readme) | [![npm](https://img.shields.io/npm/v/@putout/processor-yaml.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/processor-yaml) |\n| [`@putout/processor-css`](/packages/processor-css#readme) | [![npm](https://img.shields.io/npm/v/@putout/processor-css.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/processor-css) |\n| [`@putout/processor-filesystem`](/packages/processor-filesystem#readme) | [![npm](https://img.shields.io/npm/v/@putout/processor-filesystem.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/processor-filesystem) |\n\nYou can disable any of them with:\n\n```json\n{\n    \"processors\": [\n        [\"markdown\", \"off\"]\n    ]\n}\n```\n\nNot bundled processors:\n\n| Package | Version |\n|--------|-------|\n| [`@putout/processor-typescript`](/packages/processor-typescript#readme) | [![npm](https://img.shields.io/npm/v/@putout/processor-typescript.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/processor-typescript) |\n| [`@putout/processor-html`](/packages/processor-html#readme) | [![npm](https://img.shields.io/npm/v/@putout/processor-html.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/processor-html) |\n| [`@putout/processor-wasm`](/packages/processor-wasm#readme) | [![npm](https://img.shields.io/npm/v/@putout/processor-wasm.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/processor-wasm) |\n\nExternal processors:\n\n| Package | Version |\n|--------|-------|\n| [`putout-processor-typos`](https://github.com/putoutjs/putout-processor-typos) | [![npm](https://img.shields.io/npm/v/putout-processor-typos.svg?maxAge=86400)](https://www.npmjs.com/package/putout-processor-typos) |\n\nTo enable, install and use:\n\n```json\n{\n    \"processors\": [\n        [\"typescript\", \"on\"]\n    ]\n}\n```\n\nProcessors can be tested using [@putout/test/processors](https://github.com/coderaiser/putout/tree/master/packages/test#processors-api).\n\n## 🏗 API\n\n\u003e **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.**\n\u003e\n\u003e **(c) Yamamoto Tsunetomo \"Hagakure\"**\n\nIn the similar way works 🐊**Putout API**: it has no\nplugins defined, *tabula rasa*.\n\n### putout(source, options)\n\nFirst things first, `require` putout:\n\n```js\nconst putout = require('putout');\n```\n\nLet's consider the next `source` with two `VariableDeclarations` and one `CallExpression`:\n\n```js\nconst hello = 'world';\nconst hi = 'there';\n\nconsole.log(hello);\n```\n\nWe can declare it as `source`:\n\n```js\nconst source = `\n    const hello = 'world';\n    const hi = 'there';\n    \n    console.log(hello);\n`;\n```\n\n#### Plugins\n\n🐊**Putout** supports dynamic loading of plugins from `node_modules`. Let's consider example of using the [remove-unused-variables](https://github.com/coderaiser/putout/tree/master/packages/plugin-remove-unused-variables/README.md#readme) plugin:\n\n```js\nputout(source, {\n    plugins: [\n        'remove-unused-variables',\n    ],\n});\n\n// returns\n({\n    code: `\\n    const hello = 'world';\\n\\n    console.log(hello);\\n`,\n    places: [],\n});\n```\n\nAs you see, `places` is empty, but the code is changed: there is no `hi` variable.\n\n#### No fix\n\nFrom 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).\nIt is therefore easy to find sections that could be fixed.\nIn the following example redundant variables are found without making changes to the source file:\n\n```js\nputout(source, {\n    fix: false,\n    plugins: [\n        'remove-unused-variables',\n    ],\n});\n\n// returns\n({\n    code: '\\n' + `    const hello = 'world';\\n` + `    const hi = 'there';\\n` + '    \\n' + '    console.log(hello);\\n',\n    places: [{\n        rule: 'remove-unused-variables',\n        message: '\"hi\" is defined but never used',\n        position: {\n            line: 3,\n            column: 10,\n        },\n    }],\n});\n```\n\n#### 🗺 Source map\n\n\u003e *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.*\n\u003e\n\u003e (c) [Source maps in Node.js](https://nodejs.medium.com/source-maps-in-node-js-482872b56116)\n\nIn our case `Data URL` used. Here is an example of source map:\n\n```json\n{\n    \"version\": 3,\n    \"file\": \"out.js\",\n    \"sourceRoot\": \"\",\n    \"sources\": [\n        \"foo.js\",\n        \"bar.js\"\n    ],\n    \"names\": [\n        \"src\",\n        \"maps\",\n        \"are\",\n        \"fun\"\n    ],\n    \"mappings\": \"AAgBC,SAAQ,CAAEA\"\n}\n```\n\nTo generate **source map** you can use:\n\n```js\nconst {generate} = require('@putout/engine-parser');\nconst {parse} = require('@putout/engine-parser/babel');\n\nconst ast = parse(source, {\n    sourceFilename: 'hello.js',\n});\n\ngenerate(ast, {sourceMaps: true}, {\n    'hello.js': source,\n});\n\n// returns\n({\n    code,\n    map,\n});\n```\n\n## 🏨 Built-in transformations\n\n### JavaScript\n\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003eunused variables\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n  function show() {\n-     const message = 'hello';\n      console.log('hello world');\n  }\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove unused \u003ccode\u003efor...of variables\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-for (const {a, b} of c) {\n+for (const {a} of c) {\n    console.log(a);\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003eunreferenced variables\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-let a;\n- a = 1;\nlet b;\nb = 2;\nconsole.log(b);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove duplicate \u003ccode\u003ekeys\u003c/code\u003e\u003c/summary\u003e\n\n```diff\nconst a = {\n-   x: 'hello',\n-   ...y,\n    x: 'world',\n    ...y,\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove duplicate \u003ccode\u003ecase\u003c/code\u003e\u003c/summary\u003e\n\n```diff\nswitch (x) {\n    case 5:\n        console.log('hello');\n        break;\n-   case 5:\n-       console.log('zz');\n-       break;\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove unused \u003ccode\u003eprivate fields\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n  class Hello {\n    #a = 5;\n-   #b = 3;\n    get() {\n        return this.#a;\n    };\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove unused \u003ccode\u003eexpressions\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n  function show(error) {\n-     showError;\n  }\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003evariables\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-   function hi(a) {\n-       const b = a;\n    };\n+   function hi(b) {\n    };\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003epush\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n    function notUsed() {\n-       const paths = [];\n        for (const [key, name] of tuples) {\n-           paths.push([key, full]);\n        }\n    }\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003eObject.assign()\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const load = stub().rejects(assign(Error('LOAD USED')));\n+const load = stub().rejects(Error('LOAD USED'));\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003ereplace()\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const a = 'hello'.replace(world, world);\n+const a = 'hello';\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003enew\u003c/code\u003e(\u003ca href=https://262.ecma-international.org/12.0/#sec-error-constructor\u003ewhy\u003c/a\u003e)\u003c/summary\u003e\n\n```diff\n-new Error('something when wrong');\n+Error('something when wrong');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eadd missing \u003ccode\u003enew\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const map = Map();\n+const map = new Map();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003econstructor\u003c/code\u003e(\u003ca href=https://google.github.io/styleguide/tsguide.html#primitive-types-wrapper-classes\u003ewhy\u003c/a\u003e)\u003c/summary\u003e\n\n```diff\nclass A extends B() {\n-    constructor(...args) {\n-        super(...args);\n-    }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003emap\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const [str] = lines.map((line) =\u003e `hello ${line}`);\n+const [line] = lines;\n+const str = `hello ${line}`;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003econtinue\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-for (sign = decpt, i = 0; (sign /= 10) != 0; i++)\n-    continue;\n+for (sign = decpt, i = 0; (sign /= 10) != 0; i++);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003eoperand\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-a = a + b;\n+a += b;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003ereturn\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-module.exports.traverse = ({push}) =\u003e {\n-    return {\n-        ObjectExpression(path) {\n-        }\n-    }\n-};\n+module.exports.traverse = ({push}) =\u003e ({\n+    ObjectExpression(path) {\n+    }\n+});\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003earray\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-A[[B]];\n+A[B];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003earray constructor\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const a = Array(1, 2, 3);\n+const a = [1, 2, 3];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003econditions\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-if (zone?.tooltipCallback) {\n-    zone.tooltipCallback(e);\n-}\n+zone?.tooltipCallback(e);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003etype conversion\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const a = Boolean(b.includes(c));\n+const a = b.includes(c);\n\n--if (!!a)\n++if (a)\n    console.log('hi');\n\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003efunctions\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const f = (...a) =\u003e fn(...a);\n-array.filter((a) =\u003e a);\n\n+const f = fn;\n+array.filter(Boolean);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003etypeof\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n- typeof typeof 'hello';\n+ typeof 'hello';\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003edeclare before \u003ccode\u003ereference\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const {compare} = operator;\nimport {operator} from 'putout';\n+const {compare} = operator\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003edeclare \u003ccode\u003eimports\u003c/code\u003e first\u003c/summary\u003e\n\n```diff\n-const [arg] = process.argv;\nimport esbuild from 'esbuild';\n+const [arg] = process.argv;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003edeclare \u003ccode\u003evariables\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n+const fs = import 'fs/promises';\n+const {stub} = import 'supertape';\n+const {assign} = Object;\n\nconst readFile = stub();\nassign(fs, {\n    readFile,\n});\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003earguments\u003c/code\u003e\u003c/summary\u003e\n\n```diff\nonIfStatement({\n    push,\n-   generate,\n-   abc,\n})\n\nfunction onIfStatement({push}) {\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003etemplate expressions\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-let y = `${\"hello\"} + ${\"world\"}`;\n+let y = `hello + world`;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003efor...of\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-for (const a of ['hello']) {\n-    console.log(a);\n-}\n+console.log('hello');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003e\u003ca href=https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries\u003earray.entries()\u003c/a\u003e\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-for (const [, element] of array.entries()) {\n-}\n+for (const element of array) {\n+}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003ereuse duplicate init\u003c/summary\u003e\n\n```diff\nconst putout = require('putout');\n-const {operator} = require('putout');\n+const {operator} = putout;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003eassignment\u003c/code\u003e to \u003ccode\u003earrow function\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const createRegExp = (a) = RegExp(a, 'g');\n+const createRegExp = (a) =\u003e RegExp(a, 'g');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003eassignment\u003c/code\u003e to \u003ccode\u003ecomparison\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-if (a = 5) {\n+if (a === 5) {\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003earrow function\u003c/code\u003e to \u003ccode\u003econdition\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-if (a =\u003e b) {}\n+if (a \u003e= b) {}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003equotes\u003c/code\u003e to \u003ccode\u003ebackticks\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const a = 'hello \\'world\\'';\n+const a = `hello 'world'`;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003etypeof\u003c/code\u003e to \u003ccode\u003eis type\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n+const isFn = (a) =\u003e typeof a === 'function';\n+\n+if (isFn(fn))\n-if (typeof fn === 'function')\n    fn();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003ebitwise\u003c/code\u003e to \u003ccode\u003elogical\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-a | !b\n+a || !b\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003eequal\u003c/code\u003e to \u003ccode\u003estrict equal\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-if (a == b) {\n+if (a === b) {\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003eescape\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const t = 'hello \\\"world\\\"';\n-const s1 = `hello \\\"world\\\"`;\n-const s = `hello \\'world\\'`;\n+const t = 'hello \"world\"';\n+const s1 = `hello \"world\"`;\n+const s = `hello 'world'`;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003eArray.from()\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-for (const x of Array.from(y)) {}\n+for (const x of y) {}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003espread\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-for (const x of [...y]) {}\n+for (const x of y) {}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003edebugger\u003c/code\u003e statement\u003c/summary\u003e\n\n```diff\n- debugger;\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003eiife\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-(function() {\n-    console.log('hello world');\n-}());\n+console.log('hello world');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003eboolean\u003c/code\u003e from \u003ccode\u003eassertions\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-if (a === true)\n+if (a)\n    alert();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003eboolean\u003c/code\u003e from \u003ccode\u003elogical expressions\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const t = true \u0026\u0026 false;\n+const t = false;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove nested blocks\u003c/summary\u003e\n\n```diff\nfor (const x of Object.keys(a)) {\n-   {\n-       console.log(x);\n-   }\n+   console.log(x);\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove unreachable code\u003c/summary\u003e\n\n```diff\nfunction hi() {\n    return 5;\n-   console.log('hello');\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003esplit variable declarations\u003c/summary\u003e\n\n```diff\n-let a, b;\n+let a;\n+let b;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003esplit nested \u003ccode\u003edestructuring\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const {a: {b}} = c;\n+const {a} = c;\n+const {b} = a;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003esimplify \u003ccode\u003eassignment\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const {a} = {a: 5};\n-const [b] = [5];\n+const a = 5;\n+const b = 5;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003esimplify \u003ccode\u003eboolean return\u003c/code\u003e\u003c/summary\u003e\n\n```diff\nfunction isA(a, b) {\n-    if (a.length === b.length)\n-        return true;\n-\n-   return false;\n+   return a.length === b.length;\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003esimplify \u003ccode\u003elogical expressions\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-!(options \u0026\u0026 !options.bidirectional);\n+!options || options.bidirectional;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003esimplify \u003ccode\u003eternary\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-module.exports = fs.copyFileSync ? fs.copyFileSync : copyFileSync;\n+module.exports = fs.copyFileSync || copyFileSync;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003econsole.log\u003c/code\u003e calls\u003c/summary\u003e\n\n```diff\n-console.log('hello');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove empty block statements\u003c/summary\u003e\n\n```diff\n-if (x \u003e 0) {\n-}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove empty patterns\u003c/summary\u003e\n\n```diff\n-const {} = process;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003econstant conditions\u003c/code\u003e\u003c/summary\u003e\n\n```diff\nfunction hi(a) {\n-   if (2 \u003c 3) {\n-       console.log('hello');\n-       console.log('world');\n-   }\n+   console.log('hello');\n+   console.log('world');\n};\n\nfunction world(a) {\n-   if (false) {\n-       console.log('hello');\n-       console.log('world');\n-   }\n};\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003ereplace\u003c/code\u003e to \u003ccode\u003ereplaceAll\u003c/code\u003e (\u003ca href=https://github.com/tc39/proposal-string-replaceall\u003estage-4\u003c/a\u003e)\u003c/summary\u003e\n\n```diff\n-'hello'.replace(/hello/g, 'world');\n+'hello'.replaceAll('hello', 'world');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply consistent-blocks\u003c/summary\u003e\n\n```diff\n-if (a)\n+if (a) {\n    b();\n+} else {\n-else {\n    c();\n    d();\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply arrow\u003c/summary\u003e\n\n```diff\n-export function hello() {\n-    return 'world';\n-}\n+export const hello = () =\u003e 'world';\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply destructuring\u003c/summary\u003e\n\n```diff\n-const hello = world.hello;\n-const a = b[0];\n+const {hello} = world;\n+const [a] = b;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply dot notation\u003c/summary\u003e\n\n```diff\n-a['hello']['world'] = 5;\n+a.hello.world = 5;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply \u003ccode\u003e.startsWith()\u003c/code\u003e\u003c/summary\u003e\n\n```diff\nconst {a = ''} = b;\n-!a.indexOf('\u003e');\n+a.startsWith('\u003e');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply \u003ccode\u003eoverrides\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-export const readRules = (dirOpt, rulesDir, {cwd, readdirSync}) =\u003e {}\n+export const readRules = (dirOpt, rulesDir, overrides) =\u003e {\n    const {cwd, readdirSync} = overrides;\n+}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003esort imports by specifiers\u003c/summary\u003e\n\n```diff\n+import a1 from 'a1';\nimport {\n    a,\n    b,\n    c,\n    d,\n} from 'd';\n-import a1 from 'a1';\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply \u003ccode\u003etemplate literals\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const line = 'hello' + world;\n+const line = `hello${world}`\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply \u003ccode\u003eflatMap()\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-array.map(getId).flat();\n+array.flatMap(getId);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply \u003ccode\u003eif condition\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-if (2 \u003e 3);\n+if (2 \u003e 3)\n    alert();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply \u003ccode\u003e\u003ca href=https://web.mit.edu/jwalden/www/isArray.html\u003eisArray()\u003c/a\u003e\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-x instanceof Array;\n+Array.isArray(x);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply \u003ca href=https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V16.md#2021-07-29-version-1660-current-bethgriggs\u003e\u003ccode\u003eArray.at()\u003c/code\u003e\u003c/a\u003e\u003c/summary\u003e\n\n```diff\n-const latest = (a) =\u003e a[a.length - 1];\n+const latest = (a) =\u003e a.at(-1);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply optional chaining (\u003ca href=https://github.com/tc39/proposal-optional-chaining\u003eproposal-optional-chaining\u003c/a\u003e)\u003c/summary\u003e\n\n```diff\n-const result = hello \u0026\u0026 hello.world;\n+const result = hello?.world;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply nullish coalescing (\u003ca href=https://github.com/tc39/proposal-nullish-coalescing\u003eproposal-nullish-coalescing\u003c/a\u003e, not bundled)\u003c/summary\u003e\n\n```diff\n-result = typeof result  === 'undefined' ? 'hello': result;\nresult = result ?? 'hello';\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003ethrow\u003c/code\u003e statement into expression (\u003ca href=https://github.com/tc39/proposal-throw-expressions\u003eproposal-throw-expressions\u003c/a\u003e, not bundled)\u003c/summary\u003e\n\n```diff\n-const fn = (a) =\u003e {throw Error(a);}\n+const fn = (a) =\u003e throw Error(a);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003emerge destructuring properties\u003c/summary\u003e\n\n```diff\n-const {one} = require('numbers'):\n-const {two} = require('numbers');\n+ const {\n+   one,\n+   two\n+} = require('numbers');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003emerge \u003ccode\u003ereturn\u003c/code\u003e with next sibling\u003c/summary\u003e\n\n```diff\n-return\n-{\n-    a: 5\n-}\n+return {\n+   a: 5\n+};\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003emerge duplicate imports\u003c/summary\u003e\n\n```diff\n-import {m as b} from 'y';\n-import {z} from 'y';\n-import x from 'y';\n+import x, {m as b, z} from 'y';\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003emerge duplicate functions\u003c/summary\u003e\n\n```diff\nconst isFn = (a) =\u003e typeof a === 'function';\n-const isFn1 = (a) =\u003e typeof a === 'function';\n\nisFn(1);\n-isFn1(2);\n+isFn(2);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003emerge \u003ccode\u003eif\u003c/code\u003e statements\u003c/summary\u003e\n\n```diff\n-if (a \u003e b)\n-    if (b \u003c c)\n-        console.log('hi');\n+if (a \u003e b \u0026\u0026 b \u003c c)\n+    console.log('hi');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003emerge \u003ccode\u003eif\u003c/code\u003e with \u003ccode\u003eelse\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-if (!matchFn)\n+if (!matchFn || matchFn(options))\n    fix(from, to, path);\n-else if (matchFn(options))\n-   fix(from, to, path);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003eanonymous\u003c/code\u003e to \u003ccode\u003earrow function\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-module.exports = function(a, b) {\n+module.exports = (a, b) =\u003e {\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003efor\u003c/code\u003e to \u003ccode\u003efor...of\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-for (let i = 0; i \u003c items.length; i++) {\n+for (const item of items) {\n-   const item = items[i];\n    log(item);\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003eforEach\u003c/code\u003e to \u003ccode\u003efor...of\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-Object.keys(json).forEach((name) =\u003e {\n+for (const name of Object.keys(json)) {\n    manage(name, json[name]);\n-});\n+}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003efor...in\u003c/code\u003e to \u003ccode\u003efor...of\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-for (const name in object) {\n-   if (object.hasOwnProperty(name)) {\n+for (const name of Object.keys(object)) {\n    console.log(a);\n-   }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003emap\u003c/code\u003e to \u003ccode\u003efor...of\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-names.map((name) =\u003e {\n+for (const name of names) {\n    alert(`hello ${name}`);\n+}\n-});\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003ereduce\u003c/code\u003e to \u003ccode\u003efor...of\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const result = list.reduce((a, b) =\u003e a + b, 1);\n+let sum = 1;\n+for (const a of list) {\n+   sum += a;\n+}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003earray copy\u003c/code\u003e to \u003ccode\u003eslice\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const places = [\n-    ...items,\n-];\n+const places = items.slice();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eextract sequence expressions\u003c/summary\u003e\n\n```diff\n-module.exports.x = 1,\n-module.exports.y = 2;\n+module.exports.x = 1;\n+module.exports.y = 2;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eextract object properties into variable\u003c/summary\u003e\n\n```diff\n-const {replace} = putout.operator;\n-const {isIdentifier} = putout.types;\n+const {operator, types} = putout;\n+const {replace} = operator;\n+const {isIdentifier} = types;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003eapply\u003c/code\u003e to \u003ccode\u003espread\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-console.log.apply(console, arguments);\n+console.log(...arguments);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003econcat\u003c/code\u003e to \u003ccode\u003eflat\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-[].concat(...array);\n+array.flat();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003earguments\u003c/code\u003e to \u003ccode\u003erest\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-function hello() {\n-    console.log(arguments);\n+function hello(...args) {\n+    console.log(args);\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003eObject.assign()\u003c/code\u003e to \u003ccode\u003emerge spread\u003c/code\u003e\u003c/summary\u003e\n\n```diff\nfunction merge(a) {\n-   return Object.assign({}, a, {\n-       hello: 'world'\n-   });\n+   return {\n+       ...a,\n+       hello: 'world'\n+   };\n};\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003ecomparison\u003c/code\u003e to \u003ccode\u003eboolean\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-   const a = b === b;\n+   const a = true;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply comparison order\u003c/summary\u003e\n\n```diff\n-5 === a;\n+a === 5;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003econst\u003c/code\u003e to \u003ccode\u003elet\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-   const a = 5;\n+   let a = 5;\n    a = 3;\n```\n\n\u003c/details\u003e\n\n### Labels\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003elabel\u003c/code\u003e to \u003ccode\u003eobject\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const a = () =\u003e {\n-    hello: 'world'\n-}\n+const a = () =\u003e ({\n+    hello: 'world'\n+})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove unused \u003ccode\u003elabels\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-hello:\nwhile (true) {\n  break;\n}\n```\n\n\u003c/details\u003e\n\n### Promises\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003eawait\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-   await await Promise.resolve('hello');\n+   await Promise.resolve('hello');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003easync\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const show = async () =\u003e {\n+const show = () =\u003e {\n    console.log('hello');\n};\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eadd missing \u003ccode\u003eawait\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-runCli();\n+await runCli();\n\nasync function runCli() {\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eadd missing \u003ccode\u003easync\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-function hello() {\n+async function hello() {\n    await world();\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eadd \u003ccode\u003eawait\u003c/code\u003e to \u003ccode\u003ereturn promise()\u003c/code\u003e statements (\u003ca href=https://v8.dev/blog/fast-async\u003ebecause it's faster, produces call stack and more readable\u003c/a\u003e)\u003c/summary\u003e\n\n```diff\nasync run () {\n-   return promise();\n+   return await promise();\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply top-level-await (\u003ca href=https://github.com/tc39/proposal-top-level-await\u003eproposal-top-level-await\u003c/a\u003e, enabled for ESM)\u003c/summary\u003e\n\n```diff\nimport fs from 'fs';\n\n-(async () =\u003e {\n-    const data = await fs.promises.readFile('hello.txt');\n-})();\n+const data = await fs.promises.readFile('hello.txt');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003ePromise.resolve()\u003c/code\u003e\u003c/summary\u003e\n\n```diff\nasync () =\u003e {\n-    return Promise.resolve('x');\n+    return 'x';\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003ePromise.reject()\u003c/code\u003e to \u003ccode\u003ethrow\u003c/code\u003e\u003c/summary\u003e\n\n```diff\nasync () =\u003e {\n-    return Promise.reject('x');\n+    throw 'x';\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply \u003ccode\u003eawait import()\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const {readFile} = import('fs/promises');\n+const {readFile} = await import('fs/promises');\n```\n\n\u003c/details\u003e\n\n### Math\n\n\u003cdetails\u003e\u003csummary\u003eapply numeric separators(\u003ca href=https://github.com/tc39/proposal-numeric-separator\u003eproposal-numeric-separator\u003c/a\u003e)\u003c/summary\u003e\n\n```diff\n-const a = 100000000;\n+const a = 100_000_000;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003eMath.sqrt()\u003c/code\u003e to \u003ccode\u003eMath.hypot()\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const a = Math.sqrt(b ** 2 + c ** 2);\n+const a = Math.hypot(a, b);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003eMath.imul()\u003c/code\u003e to \u003ccode\u003emultiplication\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n- const a = Math.imul(b, c);\n+ const a = b * c;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003eMath.pow\u003c/code\u003e to \u003ccode\u003eexponentiation operator\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-Math.pow(2, 4);\n+2 ** 4;\n```\n\n\u003c/details\u003e\n\n### Node.js\n\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003estrict mode\u003c/code\u003e directive from esm\u003c/summary\u003e\n\n```diff\n-'use strict';\n-\nimport * from fs;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eAdd \u003ccode\u003estrict mode\u003c/code\u003e directive in \u003ccode\u003ecommonjs\u003c/code\u003e if absent\u003c/summary\u003e\n\n```diff\n+'use strict';\n+\nconst fs = require('fs');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eAdd \u003ccode\u003estrict mode\u003c/code\u003e directive in \u003ccode\u003ecommonjs\u003c/code\u003e if absent\u003c/summary\u003e\n\n```diff\n+'use strict';\n+\nconst fs = require('fs');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003estrict mode\u003c/code\u003e directive from esm\u003c/summary\u003e\n\n```diff\n-'use strict';\n-\nimport * from fs;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eAdd \u003ccode\u003estrict mode\u003c/code\u003e directive in \u003ccode\u003ecommonjs\u003c/code\u003e if absent\u003c/summary\u003e\n\n```diff\n+'use strict';\n+\nconst fs = require('fs');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003estrict mode\u003c/code\u003e directive from esm\u003c/summary\u003e\n\n```diff\n-'use strict';\n-\nimport * from fs;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eAdd \u003ccode\u003estrict mode\u003c/code\u003e directive in \u003ccode\u003ecommonjs\u003c/code\u003e if absent\u003c/summary\u003e\n\n```diff\n+'use strict';\n+\nconst fs = require('fs');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003estrict mode\u003c/code\u003e directive from esm\u003c/summary\u003e\n\n```diff\n-'use strict';\n-\nimport * from fs;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eAdd \u003ccode\u003estrict mode\u003c/code\u003e directive in \u003ccode\u003ecommonjs\u003c/code\u003e if absent\u003c/summary\u003e\n\n```diff\n+'use strict';\n+\nconst fs = require('fs');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003eesm\u003c/code\u003e to \u003ccode\u003ecommonjs\u003c/code\u003e (disabled)\u003c/summary\u003e\n\n```diff\n-import hello from 'world';\n+const hello = require('world');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003ecommonjs\u003c/code\u003e to \u003ccode\u003eesm\u003c/code\u003e (disabled)\u003c/summary\u003e\n\n```diff\n-const hello = require('world');\n+import hello from 'world';\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003efs.promises\u003c/code\u003e to \u003ccode\u003efs/promises\u003c/code\u003e for \u003ca href=https://nodejs.org/dist/latest-v15.x/docs/api/fs.html#fs_fs_promises_api\u003enode.js\u003c/a\u003e\u003c/summary\u003e\n\n```diff\n-const {readFile} = require('fs').promises;\n+const {readFile} = require('fs/promises');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003etop-level return\u003c/code\u003e into \u003ccode\u003eprocess.exit()\u003c/code\u003e(because EcmaScript Modules doesn't support top level return)\u003c/summary\u003e\n\n```diff\n-   return;\n+   process.exit();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove \u003ccode\u003eprocess.exit\u003c/code\u003e call\u003c/summary\u003e\n\n```diff\n-process.exit();\n```\n\n\u003c/details\u003e\n\n### Tape\n\n\u003cdetails\u003e\u003csummary\u003ereplace \u003ccode\u003etest.only\u003c/code\u003e with \u003ccode\u003etest\u003c/code\u003e calls\u003c/summary\u003e\n\n```diff\n-test.only('some test here', (t) =\u003e {\n+test('some test here', (t) =\u003e {\n    t.end();\n});\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003ereplace \u003ccode\u003etest.skip\u003c/code\u003e with \u003ccode\u003etest\u003c/code\u003e calls\u003c/summary\u003e\n\n```diff\n-test.skip('some test here', (t) =\u003e {\n+test('some test here', (t) =\u003e {\n    t.end();\n});\n```\n\n\u003c/details\u003e\n\n### TypeScript\n\n\u003cdetails\u003e\u003csummary\u003eremove duplicates from \u003ccode\u003eunion\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-type x = boolean[] | A | string | A | string[] | boolean[];\n+type x = boolean[] | A | string | string[];\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003econvert \u003ccode\u003egeneric\u003c/code\u003e to \u003ccode\u003eshorthand\u003c/code\u003e(\u003ca href=https://stackoverflow.com/a/36843084/4536327\u003ewhy\u003c/a\u003e)\u003c/summary\u003e\n\n```diff\ninterface A {\n-    x: Array\u003cX\u003e;\n+    x: X[];\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003etypes\u003c/code\u003e from \u003ccode\u003econstants\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-const x: any = 5;\n+const x = 5;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003e\u003ca href=https://www.typescriptlang.org/docs/handbook/2/mapped-types.html\u003emapped types\u003c/a\u003e\u003c/code\u003e\u003c/summary\u003e\n\n```diff\n-type SuperType = {\n-   [Key in keyof Type]: Type[Key]\n-}\n+type SuperType = Type;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003e\u003ca href=https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#mapping-modifiers\u003emapping modifiers\u003c/a\u003e\u003c/code\u003e\u003c/summary\u003e\n\n```diff\ntype SuperType = {\n-   +readonly[Key in keyof Type]+?: Type[Key];\n+   readonly[Key in keyof Type]?: Type[Key];\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove useless \u003ccode\u003etypes\u003c/code\u003e\u003c/summary\u003e\n\n```diff\ntype oldType = number;\n-type newType = oldType;\n-const x: newType = 5;\n+const x: oldType = 5;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove duplicate \u003ccode\u003einterface\u003c/code\u003e keys\u003c/summary\u003e\n\n```diff\ninterface Hello {\n-   'hello': any;\n    'hello': string;\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eremove unused \u003ccode\u003etypes\u003c/code\u003e\u003c/summary\u003e\n\n```diff\ntype n = number;\n-type s = string;\nconst x: n = 5;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply \u003ccode\u003eas\u003c/code\u003e type assertion (according to \u003ca href=https://basarat.gitbook.io/typescript/type-system/type-assertion#as-foo-vs.-less-than-foo-greater-than\u003ebest practices\u003c/a\u003e)\u003c/summary\u003e\n\n```diff\n-const boundaryElement = \u003cHTMLElement\u003ee.target;\n+const boundaryElement1 = e.target as HTMLElement;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eapply \u003ca href=https://www.typescriptlang.org/docs/handbook/utility-types.html\u003eutility types\u003c/a\u003e\u003c/summary\u003e\n\n```diff\n-type SuperType = {\n-    [Key in keyof Type]?: Type[Key];\n-}\n+type SuperType = Partial\u003cType\u003e;\n```\n\n\u003c/details\u003e\n\n## 🏟 Plugins\n\nThe 🐊**Putout** repo is comprised of many npm packages. It is a [Lerna](https://github.com/lerna/lerna) monorepo similar to [Babel](https://github.com/babel/babel).\nIt has a lot of plugins divided by groups:\n\n### Appliers\n\n| Package | Version |\n|--------|-------|\n| [`@putout/plugin-apply-arrow`](/packages/plugin-apply-arrow#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-apply-arrow.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-apply-arrow) |\n| [`@putout/plugin-apply-consistent-blocks`](/packages/plugin-apply-consistent-blocks#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-apply-consistent-blocks.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-apply-consistent-blocks) |\n| [`@putout/plugin-apply-at`](/packages/plugin-apply-at#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-apply-at.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-apply-at) |\n| [`@putout/plugin-apply-dot-notation`](/packages/plugin-apply-dot-notation#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-apply-dot-notation.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-apply-dot-notation) |\n| [`@putout/plugin-apply-starts-with`](/packages/plugin-apply-starts-with#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-apply-starts-with.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-apply-starts-with) |\n| [`@putout/plugin-apply-flat-map`](/packages/plugin-apply-flat-map#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-apply-flat-map.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-apply-flat-map) |\n| [`@putout/plugin-apply-destructuring`](/packages/plugin-apply-destructuring#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-apply-destructuring.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-apply-destructuring) |\n| [`@putout/plugin-apply-template-literals`](/packages/plugin-apply-template-literals#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-apply-template-literals.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-apply-template-literals) |\n| [`@putout/plugin-apply-overrides`](/packages/plugin-apply-overrides#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-apply-overrides.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-apply-overrides) |\n| [`@putout/plugin-apply-shorthand-properties`](/packages/plugin-apply-shorthand-properties#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-apply-shorthand-properties.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-apply-shorthand-properties) |\n\n### Splitters\n\n| Package | Version |\n|--------|-------|\n| [`@putout/plugin-split-call-with-destructuring`](/packages/plugin-split-call-with-destructuring#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-split-call-with-destructuring.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-split-call-with-destructuring) |\n| [`@putout/plugin-split-variable-declarations`](/packages/plugin-split-variable-declarations#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-split-variable-declarations.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-split-variable-declarations) |\n| [`@putout/plugin-split-nested-destructuring`](/packages/plugin-split-nested-destructuring#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-split-nested-destructuring.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-split-nested-destructuring) |\n\n### Mergers\n\n| Package | Version |\n|--------|-------|\n| [`@putout/plugin-merge-destructuring-properties`](/packages/plugin-merge-destructuring-properties#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-merge-destructuring-properties.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-merge-destructuring-properties) |\n| [`@putout/plugin-merge-duplicate-functions`](/packages/plugin-merge-duplicate-functions#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-merge-duplicate-functions.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-merge-duplicate-functions) |\n\n### Converters\n\n| Package | Version |\n|--------|-------|\n| [`@putout/plugin-convert-arguments-to-rest`](/packages/plugin-convert-arguments-to-rest#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-arguments-to-rest.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-arguments-to-rest) |\n| [`@putout/plugin-convert-apply-to-spread`](/packages/plugin-convert-apply-to-spread#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-apply-to-spread.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-apply-to-spread) |\n| [`@putout/plugin-convert-expression-to-params`](/packages/plugin-convert-expression-to-params#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-expression-to-params.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-expression-to-params) |\n| [`@putout/plugin-convert-quotes-to-backticks`](/packages/plugin-convert-quotes-to-backticks#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-quotes-to-backticks.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-quotes-to-backticks) |\n| [`@putout/plugin-convert-concat-to-flat`](/packages/plugin-convert-concat-to-flat#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-concat-to-flat.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-concat-to-flat) |\n| [`@putout/plugin-convert-array-copy-to-slice`](/packages/plugin-convert-array-copy-to-slice#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-array-copy-to-slice.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-array-copy-to-slice) |\n| [`@putout/plugin-convert-template-to-string`](/packages/plugin-convert-template-to-string#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-template-to-string.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-template-to-string) |\n| [`@putout/plugin-convert-index-of-to-includes`](/packages/plugin-convert-index-of-to-includes#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-index-of-to-includes.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-index-of-to-includes) |\n| [`@putout/plugin-convert-object-assign-to-merge-spread`](/packages/plugin-convert-object-assign-to-merge-spread#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-object-assign-to-merge-spread.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-object-assign-to-merge-spread) |\n| [`@putout/plugin-convert-assignment-to-arrow-function`](/packages/plugin-convert-assignment-to-arrow-function#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-assignment-to-arrow-function.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-assignment-to-arrow-function) |\n| [`@putout/plugin-convert-const-to-let`](/packages/plugin-convert-const-to-let#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-const-to-let.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-const-to-let) |\n| [`@putout/plugin-convert-object-entries-to-array-entries`](/packages/plugin-convert-object-entries-to-array-entries#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-object-entries-to-array-entries.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-object-entries-to-array-entries) |\n\n### Removers\n\n| Package | Version |\n|--------|-------|\n| [`@putout/plugin-remove-unused-variables`](/packages/plugin-remove-unused-variables#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-unused-variables.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-unused-variables) |\n| [`@putout/plugin-remove-unreferenced-variables`](/packages/plugin-remove-unreferenced-variables#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-unreferenced-variables.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-unreferenced-variables) |\n| [`@putout/plugin-remove-duplicate-keys`](/packages/plugin-remove-duplicate-keys#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-duplicate-keys.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-duplicate-keys) |\n| [`@putout/plugin-remove-duplicate-case`](/packages/plugin-remove-duplicate-case#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-duplicate-case.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-duplicate-case) |\n| [`@putout/plugin-remove-unused-expressions`](/packages/plugin-remove-unused-expressions#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-unused-expressions.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-unused-expressions) |\n| [`@putout/plugin-remove-unused-private-fields`](/packages/plugin-remove-unused-private-fields#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-unused-private-fields.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-unused-private-fields) |\n| [`@putout/plugin-remove-useless-variables`](/packages/plugin-remove-useless-variables#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-variables.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-variables) |\n| [`@putout/plugin-remove-useless-assign`](/packages/plugin-remove-useless-assign#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-assign.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-assign) |\n| [`@putout/plugin-remove-useless-replace`](/packages/plugin-remove-useless-replace#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-replace.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-replace) |\n| [`@putout/plugin-remove-useless-map`](/packages/plugin-remove-useless-map#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-map.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-map) |\n| [`@putout/plugin-remove-useless-constructor`](/packages/plugin-remove-useless-constructor#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-constructor.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-constructor) |\n| [`@putout/plugin-remove-useless-continue`](/packages/plugin-remove-useless-continue#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-continue.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-continue) |\n| [`@putout/plugin-remove-useless-operand`](/packages/plugin-remove-useless-operand#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-operand.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-operand) |\n| [`@putout/plugin-remove-useless-arguments`](/packages/plugin-remove-useless-arguments#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-arguments.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-arguments) |\n| [`@putout/plugin-remove-useless-array`](/packages/plugin-remove-useless-array#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-array.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-array) |\n| [`@putout/plugin-remove-useless-array-constructor`](/packages/plugin-remove-useless-array-constructor#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-array-constructor.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-array-constructor) |\n| [`@putout/plugin-remove-useless-array-entries`](/packages/plugin-remove-useless-array-entries#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-array-entries.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-array-entries) |\n| [`@putout/plugin-remove-useless-escape`](/packages/plugin-remove-useless-escape#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-escape.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-escape) |\n| [`@putout/plugin-remove-useless-functions`](/packages/plugin-remove-useless-functions#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-functions.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-functions) |\n| [`@putout/plugin-remove-useless-spread`](/packages/plugin-remove-useless-spread#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-spread.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-spread) |\n| [`@putout/plugin-remove-useless-push`](/packages/plugin-remove-useless-push#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-push.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-push) |\n| [`@putout/plugin-remove-useless-template-expressions`](/packages/plugin-remove-useless-template-expressions#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-template-expressions.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-template-expressions) |\n| [`@putout/plugin-remove-useless-delete`](/packages/plugin-remove-useless-delete#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-useless-delete.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-useless-delete) |\n| [`@putout/plugin-remove-debugger`](/packages/plugin-remove-debugger#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-debugger.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-debugger) |\n| [`@putout/plugin-remove-iife`](/packages/plugin-remove-iife#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-iife.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-iife) |\n| [`@putout/plugin-remove-unreachable-code`](/packages/plugin-remove-unreachable-code#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-unreachable-code.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-unreachable-code) |\n| [`@putout/plugin-remove-console`](/packages/plugin-remove-console#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-console.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-console) |\n| [`@putout/plugin-remove-empty`](/packages/plugin-remove-empty#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-empty.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-empty) |\n| [`@putout/plugin-remove-nested-blocks`](/packages/plugin-remove-nested-blocks#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-remove-nested-blocks.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-remove-nested-blocks) |\n\n### Simplifiers\n\n| Package | Version |\n|--------|-------|\n| [`@putout/plugin-simplify-ternary`](/packages/plugin-simplify-ternary#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-simplify-ternary.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-simplify-ternary) |\n\n### Declarators\n\n| Package | Version |\n|--------|-------|\n| [`@putout/plugin-declare`](/packages/plugin-declare#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-declare.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-declare) |\n| [`@putout/plugin-declare-before-reference`](/packages/plugin-declare-before-reference#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-declare-before-reference.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-declare-before-reference) |\n\n### Groups\n\n| Package | Version |\n|--------|-------|\n| [`@putout/plugin-assignment`](/packages/plugin-assignment#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-assignment.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-assignment) |\n| [`@putout/plugin-conditions`](/packages/plugin-conditions#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-conditions.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-conditions) |\n| [`@putout/plugin-esm`](/packages/plugin-esm#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-esm.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-esm) |\n| [`@putout/plugin-filesystem`](/packages/plugin-filesystem#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-filesystem.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-filesystem) |\n| [`@putout/plugin-for-of`](/packages/plugin-for-of#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-for-of.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-for-of) |\n| [`@putout/plugin-types`](/packages/plugin-types#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-types.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-types) |\n| [`@putout/plugin-labels`](/packages/plugin-labels#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-labels.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-labels) |\n| [`@putout/plugin-math`](/packages/plugin-math#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-math.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-math) |\n| [`@putout/plugin-madrun`](/packages/plugin-madrun#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-madrun.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-madrun) |\n| [`@putout/plugin-optional-chaining`](/packages/plugin-putout#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-optional-chaining.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-optional-chaining) |\n| [`@putout/plugin-parens`](/packages/plugin-parens#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-parens.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-parens) |\n| [`@putout/plugin-putout`](/packages/plugin-putout#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-putout.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-putout) |\n| [`@putout/plugin-return`](/packages/plugin-return#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-return.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-return) |\n| [`@putout/plugin-putout-config`](/packages/plugin-putout-config#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-putout-config.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-putout-config) |\n| [`@putout/plugin-tape`](/packages/plugin-tape#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-tape.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-tape) |\n| [`@putout/plugin-webpack`](/packages/plugin-webpack#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-webpack.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-webpack) |\n| [`@putout/plugin-eslint`](/packages/plugin-eslint#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-eslint.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-eslint) |\n| [`@putout/plugin-package-json`](/packages/plugin-package-json#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-package-json.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-package-json) |\n| [`@putout/plugin-promises`](/packages/plugin-promises#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-promises.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-promises) |\n| [`@putout/plugin-generators`](/packages/plugin-generators#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-generators.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-generators) |\n| [`@putout/plugin-gitignore`](/packages/plugin-gitignore#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-gitignore.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-gitignore) |\n| [`@putout/plugin-npmignore`](/packages/plugin-npmignore#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-npmignore.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-npmignore) |\n| [`@putout/plugin-coverage`](/packages/plugin-coverage#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-coverage.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-coverage) |\n| [`@putout/plugin-browserlist`](/packages/plugin-browserlist#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-browserlist.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-browserlist) |\n| [`@putout/plugin-github`](/packages/plugin-github#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-github.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-github) |\n| [`@putout/plugin-regexp`](/packages/plugin-regexp#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-regexp.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-regexp) |\n| [`@putout/plugin-nodejs`](/packages/plugin-nodejs#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-nodejs.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-nodejs) |\n| [`@putout/plugin-typescript`](/packages/plugin-typescript#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-typescript.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-typescript) |\n| [`@putout/plugin-try-catch`](/packages/plugin-try-catch#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-try-catch.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-try-catch) |\n| [`@putout/plugin-montag`](/packages/plugin-montag#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-montag.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-montag) |\n| [`@putout/plugin-maybe`](/packages/plugin-maybe#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-maybe.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-maybe) |\n| [`@putout/plugin-new`](/packages/plugin-new#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-new.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-new) |\n| [`@putout/plugin-logical-expressions`](/packages/plugin-logical-expressions#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-logical-expressions.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-logical-expressions) |\n\n### Extractors\n\n| Package | Version |\n|--------|-------|\n| [`@putout/plugin-extract-sequence-expressions`](/packages/plugin-extract-sequence-expressions#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-extract-sequence-expressions.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-extract-sequence-expressions) |\n| [`@putout/plugin-extract-object-properties`](/packages/plugin-extract-object-properties#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-extract-object-properties.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-extract-object-properties) |\n| [`@putout/plugin-extract-keywords-from-variables`](/packages/plugin-extract-keywords-from-variables#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-extract-keywords-from-variables.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-extract-keywords-from-variables) |\n\n### Reusers\n\n| Package | Version |\n|--------|-------|\n| [`@putout/plugin-reuse-duplicate-init`](/packages/plugin-reuse-duplicate-init#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-reuse-duplicate-init.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-reuse-duplicate-init) |\n\n### Not bundled\n\nNext packages not bundled with 🐊**Putout** but can be installed separately.\n\n| Package | Version |\n|--------|-------|\n| [`@putout/plugin-apply-entries`](/packages/plugin-apply-entries#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-apply-entries.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-apply-entries) |\n| [`@putout/plugin-eslint-plugin`](/packages/plugin-eslint-plugin#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-eslint-plugin.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-eslint-plugin) |\n| [`@putout/plugin-react`](/packages/plugin-react#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-react.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-react) |\n| [`@putout/plugin-react-hook-form`](/packages/plugin-react-hook-form#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-react-hook-form.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-react-hook-form) |\n| [`@putout/plugin-nextjs`](/packages/plugin-nextjs#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-nextjs.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-nextjs) |\n| [`@putout/plugin-react-router`](/packages/plugin-react-router#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-react-router.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-react-router) |\n| [`@putout/plugin-convert-is-nan-to-number-is-nan`](/packages/plugin-convert-is-nan-to-number-is-nan#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-is-nan-to-number-is-nan.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-is-nan-to-number-is-nan) |\n| [`@putout/plugin-convert-spread-to-array-from`](/packages/plugin-convert-spread-to-array-from#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-spread-to-array-from.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-spread-to-array-from) |\n| [`@putout/plugin-convert-assert-to-with`](/packages/plugin-convert-assert-to-with#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-assert-to-with.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-assert-to-with) |\n| [`@putout/plugin-apply-nullish-coalescing`](/packages/plugin-apply-nullish-coalescing#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-apply-nullish-coalescing.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-apply-nullish-coalescing) |\n| [`@putout/plugin-cloudcmd`](/packages/plugin-cloudcmd#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-cloudcmd.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-cloudcmd) |\n| [`@putout/plugin-postcss`](/packages/plugin-postcss#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-postcss.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-postcss) |\n| [`@putout/plugin-jest`](/packages/plugin-jest#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-jest.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-jest) |\n| [`@putout/plugin-vitest`](/packages/plugin-vitest#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-vitest.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-vitest) |\n| [`@putout/plugin-travis`](/packages/plugin-travis#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-travis.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-travis) |\n| [`@putout/plugin-convert-throw`](/packages/plugin-convert-throw#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-convert-throw.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-convert-throw) |\n| [`@putout/plugin-printer`](/packages/plugin-printer#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-printer.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-printer) |\n| [`@putout/plugin-minify`](/packages/plugin-minify#readme) | [![npm](https://img.shields.io/npm/v/@putout/plugin-minify.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/plugin-minify) |\n\n## 🦚 Formatters\n\n🐊**Putout** uses formatters similar to [**ESLint's** formatters](https://eslint.org/docs/user-guide/formatters/).\nYou can specify a formatter using the `--format` or `-f` flag on the command line. For example, `--format codeframe` uses the `codeframe` formatter.\n\nThe built-in formatter options are:\n\n- `dump`\n- `stream`\n- `json`\n- `json-lines`\n- `codeframe`\n- `progress`\n- `progress-bar`\n- `frame` (`codeframe` + `progress`)\n- `memory`\n- `time`\n\n| Package | Version |\n|---------|---------|\n| [`@putout/formatter-dump`](/packages/formatter-dump#readme) | [![npm](https://img.shields.io/npm/v/@putout/formatter-dump.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/formatter-dump#readme) |\n| [`@putout/formatter-stream`](/packages/formatter-stream#readme) | [![npm](https://img.shields.io/npm/v/@putout/formatter-stream.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/formatter-stream#readme) |\n| [`@putout/formatter-progress`](/packages/formatter-progress#readme) | [![npm](https://img.shields.io/npm/v/@putout/formatter-progress.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/formatter-progress#readme) |\n| [`@putout/formatter-progress-bar`](/packages/formatter-progress-bar#readme) | [![npm](https://img.shields.io/npm/v/@putout/formatter-progress-bar.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/formatter-progress-bar#readme) |\n| [`@putout/formatter-json`](/packages/formatter-json#readme) | [![npm](https://img.shields.io/npm/v/@putout/formatter-json.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/formatter-json) |\n| [`@putout/formatter-json-lines`](/packages/formatter-json-lines#readme) | [![npm](https://img.shields.io/npm/v/@putout/formatter-json-lines.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/formatter-json-lines) |\n| [`@putout/formatter-codeframe`](/packages/formatter-codeframe#readme) | [![npm](https://img.shields.io/npm/v/@putout/formatter-codeframe.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/formatter-codeframe) |\n| [`@putout/formatter-frame`](/packages/formatter-frame#readme) | [![npm](https://img.shields.io/npm/v/@putout/formatter-frame.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/formatter-frame) |\n| [`@putout/formatter-eslint`](/packages/formatter-eslint#readme) | [![npm](https://img.shields.io/npm/v/@putout/formatter-eslint.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/formatter-eslint) |\n| [`@putout/formatter-memory`](/packages/formatter-memory#readme) | [![npm](https://img.shields.io/npm/v/@putout/formatter-memory.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/formatter-memory) |\n| [`@putout/formatter-time`](/packages/formatter-time#readme) | [![npm](https://img.shields.io/npm/v/@putout/formatter-time.svg?maxAge=86400)](https://www.npmjs.com/package/@putout/formatter-time) |\n\n### Custom Formatter\n\nA formatter function executes on every processed file, it should return an `output string`.\n\n```js\nexport default function formatter({name, source, places, index, count, filesCount, errorsCount}) {\n    return '';\n}\n```\n\nHere is list of options:\n\n- `name` - name of processed file\n- `source` - source code of processed file\n- `index` - current index\n- `count` - processing files count\n- `filesCount` - count of files with errors\n- `errorsCount` count of errors\n\nYou can avoid any of this and use only what you need. To make your formatter usable with `putout`, add the prefix `putout-formatter-` to your `npm` package,\nand add the tags `putout`, `formatter`, `putout-formatter`.\n\n### ESLint Formatters\n\n**ESLint** formatters can be used as well with help of `@putout/formatter-eslint` this way:\n\nInstall:\n\n```\nnpm i putout @putout/formatter-eslint eslint-formatter-pretty -D\n```\n\nRun:\n\n```sh\nESLINT_FORMATTER=pretty putout -f eslint lib\n```\n\n## 🦉 Configuration\n\nTo configure 🐊**Putout** add a section named `putout` to your `package.json` file or create `.putout.json` file and override any of [default options](/packages/putout/putout.json).\n\n### Rules\n\nAll rules located in `plugins` section and built-in rules are enabled by default.\nYou can disable rules using `\"off\"`, or enable them (in `match` section) using `\"on\"`.\n\n```json\n{\n    \"rules\": {\n        \"remove-unused-variables\": \"off\"\n    }\n}\n```\n\nOr pass options using `rules` section:\n\n```json\n{\n    \"rules\": {\n        \"remove-unused-variables\": [\"on\", {\n            \"exclude\": \"const global = __\"\n        }]\n    }\n}\n```\n\n#### Exclude\n\nWith help of `exclude` you can set `type` or `code pattern` to exclude for current rule.\nPass an array when you have a couple templates to exclude:\n\n```json\n{\n    \"rules\": {\n        \"remove-unused-variables\": [\"on\", {\n            \"exclude\": [\n                \"VariableDeclaration\"\n            ]\n        }]\n    }\n}\n```\n\n`exclude` is cross-plugin function supported by core, when develop your plugin, please use other name\nto keep users ability to customize all plugins in a way they need to.\n\n### Match\n\nWhen you need to match paths to rules you can use `match` section for this purpose in `.putout.json`:\n\n```json\n{\n    \"match\": {\n        \"server\": {\n            \"nodejs/remove-process-exit\": \"on\"\n        }\n    }\n}\n```\n\n### Ignore\n\nWhen you need to ignore some routes no matter what, you can use `ignore` section in `.putout.json`:\n\n```json\n{\n    \"ignore\": [\n        \"test/fixture\"\n    ]\n}\n```\n\n### Printer\n\n\u003e **In the eyes of mercy, no one should have hateful thoughts. Feel pity for the man who is even more at fault. The area and size of mercy is limitless.**\n\u003e\n\u003e **(c) Yamamoto Tsunetomo \"Hagakure\"**\n\nYou have also ability to define `printer` of your choose, it can be:\n\n- ✅[`putout`](https://github.com/putoutjs/printer) (*default*)\n- ✅[`babel`](https://babeljs.io/docs/babel-generator)\n\n`@putout/printer` used by default, if you want to set any other update `.putout.json` with:\n\n```json\n{\n    \"printer\": \"babel\"\n}\n```\n\n`@putout/printer`:\n\n- ✅ much simpler in support then `recast`;\n- ✅ opinionated and has good defaults;\n- ✅ produces code like it was processed by **ESLint**;\n\n`babel`:\n\n- ✅ supports source maps then `recast`;\n- ❌ [produces throw away code](https://github.com/babel/babel/issues/5139);\n\nYou can choose any of them, but preferred is *[default printer](https://github.com/putoutjs/printer)*.\n\n### Plugins\n\nThere are two types of plugin names supported by 🐊**Putout**, their names in npm start with a prefix:\n\n- `@putout/plugin-` for official plugins\n- `putout-plugin-` for user plugins\n\n*Example*\nIf you need to `remove-something` create `putout` plugin with a name `putout-plugin-remove-something` and add it to `.putout.json`:\n\n```json\n{\n    \"plugins\": [\n        \"remove-something\"\n    ]\n}\n```\n\nAdd `putout` as a `peerDependency` to your `packages.json` (\u003e= of version you developing for).\n\n☝️ *Always add keywords `putout`, `putout-plugin` when publish putout plugin to `npm` so others can easily find it.*\n\n## 🧬 Plugins API\n\n\u003e **Throughout your life advance daily, becoming more skillful than yesterday more skillful than today. This is never-ending**\n\u003e\n\u003e **(c) Yamamoto Tsunetomo \"Hagakure\"**\n\n🐊**Putout** plugins are the simplest possible way to transform `AST` and this is for a reason.\n\nAnd the reason is **JavaScript**-compatible language 🦎[**PutoutScript**](https://github.com/coderaiser/putout/blob/master/docs/putout-script.md#-putoutscript) which adds additional meaning to identifiers used in `AST`-template.\n\nLet's dive into plugin types that you can use for you next code transformation.\n\n### Replacer\n\nThe simplest 🐊**Putout** plugin type consists of 2 functions:\n\n- `report` - report error message to `putout` cli;\n- `replace` - replace `key` template into `value` template;\n\n```js\nmodule.exports.report = () =\u003e 'use optional chaining';\nmodule.exports.replace = () =\u003e ({\n    '__a \u0026\u0026 __a.__b': '__a?.__b',\n});\n```\n\nThis plugin will find and suggest to replace all occurrences of code: `object \u0026\u0026 object.property` into `object?.property`.\n\n### Includer\n\nMore powerful plugin type, when you need more control over traversing.\nIt should contain next 2 functions:\n\n- `report` - report error message to `putout` cli;\n- `fix` - fixes paths using `places` array received using `find` function;\n\nand one or more of this:\n\n- `filter` - filter path, should return `true`, or `false` (don't use with `traverse`);\n- `include` - returns array of templates, or node names to include;\n- `exclude` - returns array of templates, or node names to exclude;\n\n```js\nmodule.exports.report = () =\u003e 'use optional chaining';\nmodule.exports.include = () =\u003e ['debugger'];\n\nmodule.exports.fix = (path) =\u003e {\n    path.remove(path);\n};\n```\n\n☝️ *Use [yeoman generator](https://yeoman.io/) [`yo putout`](https://github.com/putoutjs/generator-putout), it will generate most of the plugin for you.*\n\n☝️ *More information about supported plugin types you can find in [@putout/engine-runner](https://github.com/coderaiser/putout/tree/master/packages/engine-runner#readme).*\n\n☝️ *Find out about the way plugins load in [@putout/engine-loader](https://github.com/coderaiser/putout/tree/master/packages/engine-loader#readme).*\n\n☝️ *When you need, you can use [@babel/types](https://babeljs.io/docs/en/next/babel-types.html), [template](https://babeljs.io/docs/en/next/babel-template.html) and [generate](https://babeljs.io/docs/en/babel-generator). All of this can be gotten from **🐊Putout**:*\n\n```js\nconst {\n    types,\n    template,\n    generate,\n} = require('putout');\n```\n\n### Operator\n\nWhen you need to use `replaceWith`, `replaceWithMultiple`, or `insertAfter`, please use [`operator`](https://github.com/coderaiser/putout/tree/master/packages/operate#readme) instead of `path`-methods.\n\n```js\nconst {template, operator} = require('putout');\nconst {replaceWith} = operator;\n\nconst ast = template.ast(`\n  const str = 'hello';\n`);\n\nmodule.exports.fix = (path) =\u003e {\n    // wrong\n    path.replaceWith(ast);\n    // correct\n    replaceWith(path, ast);\n};\n```\n\nThis should be done to preserve `loc` and `comments` information, which is different in **Babel** and **[Recast](https://github.com/putoutjs/recast)**. 🐊**Putout** will handle this case for you :),\njust use the methods of `operator`.\n\n### 🐊 Putout Plugin\n\nWhen you work on a `plugin` or `codemod` please add rule `putout` into `.putout.json`:\n\n```json\n{\n    \"rules\": {\n        \"putout\": \"on\"\n    }\n}\n```\n\n[@putout/plugin-putout](https://github.com/coderaiser/putout/tree/master/packages/plugin-putout#readme) will handle plugin-specific cases for you :).\n\n### Example\n\nLet's consider simplest possible plugin for removing `debugger statements` [@putout/plugin-remove-debugger](https://github.com/coderaiser/putout/tree/master/packages/plugin-remove-debugger#readme):\n\n```js\n// this is a message to show in putout cli\nmodule.exports.report = () =\u003e 'Unexpected \"debugger\" statement';\n// let's find all \"debugger\" statements and replace them with \"\"\nmodule.exports.replace = () =\u003e ({\n    debugger: '',\n});\n```\n\n`Visitor` used in `traverse function` can be code template as well. So when you need to find `module.exports = \u003csomething\u003e`, you\ncan use:\n\n```js\nmodule.exports.traverse = ({push}) =\u003e ({\n    'module.exports = __'(path) {\n        push(path);\n    },\n});\n```\n\nWhere `__` is a placeholder for anything.\n\n*☝️Remember: template key should be valid **JavaScript**, or **Node Type**, like in previous example.*\n\nYou can also use `include` and/or `exclude` instead of `traverse` and `filter` ([more sophisticated example](https://github.com/coderaiser/putout/blob/v25.4.1/packages/plugin-add-return-await/lib/add-return-await.js)):\n\n```js\n// should be always used include/or exclude, when traverse not used\nmodule.exports.include = () =\u003e ['debugger'];\n// optional\nmodule.exports.exclude = () =\u003e [\n    'console.log',\n];\n\n// optional\nmodule.exports.filter = (path) =\u003e {\n    // do some checks\n    return true;\n};\n```\n\n### Template\n\nThere is predefined placeholders:\n\n- `__` - any code;\n- `\"__\"` - any string literal;\n- `__` - any template string literal;\n\n### 📼 Testing\n\nThat was the simplest module to remove `debugger` statements in your code. Let's look how to test it using [@putout/test](https://github.com/coderaiser/putout/tree/master/packages/test#readme):\n\n```js\nconst removeDebugger = require('..');\n\nconst test = require('@putout/test')(__dirname, {\n    'remove-debugger': removeDebugger,\n});\n\n// this is how we test that messages is correct\ntest('remove debugger: report', (t) =\u003e {\n    t.reportCode('debugger', 'Unexpected \"debugger\" statement');\n    t.end();\n});\n\n// statement should be removed so result is empty\ntest('remove debugger: transformCode', (t) =\u003e {\n    t.transformCode('debugger', '');\n    t.end();\n});\n```\n\nAs you see test runner it is little bit extended 📼[**Supertape**](https://github.com/coderaiser/supertape#readme).\nTo see a more sophisticated example look at [@putout/plugin-remove-console](https://github.com/coderaiser/putout/tree/master/packages/plugin-remove-console#readme).\n\n### 🤷‍♂️ What if I don't want to publish a plugin?\n\nIf you don't want to publish a **plugin** you developed, you can pass it to 🐊**Putout** as an `object` described earlier. Here is [how it can look like](https://github.com/coderaiser/mock-import/blob/v1.0.8/lib/convert-imports/index.js#L19-L33):\n\n```js\nputout('const a = 5', {\n    plugins: [\n        ['remove-unused-variables', require('@putout/plugin-remove-unused-variables')],\n    ],\n});\n```\n\nWhere `plugins` is an `array` that contains `[name, implementation]` `tuples`.\n\n## 🛴 Codemods\n\n🐊**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](https://github.com/coderaiser/putout/tree/v12.0.0/codemods/convert-tape-to-supertape#install) and [this is example of work](https://github.com/coderaiser/putout/commit/ad02cebc344ce73cdee668cffc5078bf08830d52).\n\n## 💾 Rulesdir\n\nWhen you have plugins related to your project and you don't want to publish them (because it cannot be reused right now). Use [`rulesdir`](https://github.com/coderaiser/putout/tree/master/rules):\n\n```sh\nputout --rulesdir ./rules\n```\n\nThis way you can keep rules specific for your project and run them on each lint.\n\n☝️ *Remember: if you want to exclude file from loading, add prefix `not-rule-` and 🐊**Putout** will ignore it (in the same way as he does for `node_modules`).*\n\n## ⏣ Integration with ESLint\n\n\u003e Find and fix problems in your **JavaScript** code\n\u003e\n\u003e (c) [eslint.org](https://eslint.org/)\n\nIf you see that 🐊**Putout** breaks formatting of your code, use **ESLint** plugin [eslint-plugin-putout](https://github.com/coderaiser/putout/tree/master/packages/eslint-plugin-putout#eslint-plugin-putout--).\n\nInstall `eslint-plugin-putout` with:\n\n```\nnpm i eslint eslint-plugin-putout -D\n```\n\nThen create `.eslintrc.json`:\n\n```json\n{\n    \"extends\": [\n        \"plugin:putout/recommended\"\n    ],\n    \"plugins\": [\"putout\"]\n}\n```\n\nAnd use with 🐊**Putout** this way:\n\n```sh\nputout --fix lib\n```\n\nTo set custom config file for **ESLint** use `ESLINT_CONFIG_FILE` env variable:\n\n```sh\nESLINT_CONFIG_FILE=test.eslintrc.json putout --fix lib\n```\n\nTo disable **ESLint** support use `NO_ESLINT` env variable:\n\n```sh\nNO_ESLINT=1 putout --fix lib\n```\n\nIf you want to ignore **ESLint** warnings (if you for some reason have annoying unfixable errors 🤷) use `NO_ESLINT_WARNINGS=1`:\n\n```sh\nNO_ESLINT_WARNINGS=1 putout --fix lib\n```\n\nYou can even lint without **CLI** using **ESlint** only, since 🐊**Putout** is bundled to `eslint-plugin-putout`:\n\n```\neslint --fix lib\n```\n\nApplies 🐊**Putout** transformations for you :).\n\n### ESLint API\n\n**ESLint** begins his work as a formatter when 🐊**Putout** done his transformations. That's why it is used a lot in different parts of application, for testing purpose and using **API** in a simplest possible way. You can access it using [`@putout/eslint`](https://github.com/coderaiser/putout/tree/master/packages/eslint#readme):\n\n```js\nimport eslint from '@putout/eslint';\n```\n\nTo use it simply write:\n\n```js\nconst [source, places] = await eslint({\n    name: 'hello.js',\n    code: `const t = 'hi'\\n`,\n    fix: false,\n});\n```\n\nDoesn't it look similar to 🐊**Putout** way? It definitely is! But... It has a couple of differences you should remember:\n\n- ☝️ *[🐊**Putout** returns object with `code` and `places` properties](https://github.com/coderaiser/putout#plugins).*\n- ☝️ ***ESLint** has a `name` property that is used to calculate configuration file.*\n\nAnd you can even override any of **ESLint** ⚙️ options with help of `config` property:\n\n```js\nconst [source, places] = await eslint({\n    name: 'hello.js',\n    code: `const t = 'hi'\\n`,\n    fix: false,\n    config: {\n        extends: [\n            'plugin:putout/recommended',\n        ],\n    },\n});\n```\n\nIf you want to apply 🐊**Putout** transformations using [`putout/putout`](https://github.com/coderaiser/putout/tree/master/packages/eslint-plugin-putout#readme) **ESLint** rule, enable 🐊**Putout** with the same called flag lowercased:\n\n```js\nconst [source, places] = await eslint({\n    name: 'hello.js',\n    code: `const t = 'hi'\\n`,\n    fix: true,\n    putout: true,\n    config: {\n        extends: [\n            'plugin:putout/recommended',\n        ],\n    },\n});\n```\n\nIt is disabled by default, because **ESLint** always runs after 🐊**Putout** transformations, so there is no need to traverse tree again.\n\n## ☄️ Integration with Babel\n\n🐊 **Putout** can be used as [babel plugin](/packages/babel-plugin-putout).\nJust create `.babelrc.json` file with configuration you need.\n\n```json\n{\n    \"plugins\": [\n        [\"putout\", {\n            \"rules\": {\n                \"remove-unused-variables\": \"off\"\n            }\n        }]\n    ]\n}\n```\n\n## 🐈 Integration with Yarn\n\nSince 🐊**Putout** has dynamic nature of loading:\n\n- `plugins`;\n- `processors`;\n- `formatters`;\n\nIt was a nice adventure to add support of such a wonderful feature of `Yarn` as [`Plug'n'Play`](https://yarnpkg.com/features/pnp).\nFor this purpose new `env variable` was added to help to [load external extensions](https://yarnpkg.com/advanced/rulebook/#modules-shouldnt-hardcode-node_modules-paths-to-access-other-modules): `PUTOUT_YARN_PNP`.\n\nSo if you use package **eslint-config-hardcore** you should run **ESLint** this way:\n\n```sh\nPUTOUT_YARN_PNP=eslint-config-hardcore eslint .\n```\n\n## ⛓ Using Putout as Loader\n\n🐊**Putout** can be used as [loader](https://nodejs.org/dist/latest-v17.x/docs/api/esm.html#loaders) this way:\n\n```sh\nnode --import putout/register your-file.js\n```\n\nYou can also transform input files using `Babel`. For example if you need to transform `jsx` with `@babel/plugin-transform-react-jsx` you can use `.putout.json`:\n\n```json\n{\n    \"plugins\": [\n        \"babel/transform-react-jsx\"\n    ]\n}\n```\n\n## 🚪Exit Codes\n\n🐊**Putout** can have one of next [exit codes](https://github.com/coderaiser/putout/blob/master/packages/putout/lib/cli/exit-codes.mjs):\n\n| Code | Name                    | Description                   | Output Example                                                                    |\n|------|-------------------------|-------------------------------|----------------------------------------------------------------------------|\n| 0    | `OK`                    | no errors found               | `\u003cempty\u003e`                                                                  |\n| 1    | `PLACE`                 | found places with errors      | `\u003cviolations of rules\u003e`                                                    |\n| 2    | `STAGE`                 | nothing in stage              | `\u003cempty\u003e`                                                                  |\n| 3    | `NO_FILES`              | no files found                | `🐊 No files matching the pattern \"hello\" were found`                      |\n| 4    | `NO_PROCESSORS`         | no processor found            | `🐊 No processors found for hello.abc`                                     |\n| 5    | `NO_FORMATTER`          | no formatter found            | `🐊 Cannot find module 'putout-formatter-hello'`                           |\n| 6    | `WAS_STOP`              | was stop                      | `\u003cempty or violations of rules\u003e`                                           |\n| 7    | `INVALID_OPTION`        | invalid option                | `🐊 Invalid option '--hello'. Perhaps you meant '--help'`                  |\n| 8    | `CANNOT_LOAD_PROCESSOR` | processor has errors          | `\u003cunhandled exception\u003e`                                                    |\n| 9    | `CANNOT_LOAD_FORMATTER` | formatter has errors          | `🐊 @putout/formatter-dump: Syntax error`                                  |\n| 10   | `RULER_WITH_FIX`        | ruler used with `--fix`      | `🐊 '--fix' cannot be used with ruler toggler ('--enable', '--disable')`   |\n| 11   | `RULER_NO_FILES`        | ruler used without files     | `🐊 'path' is missing for ruler toggler ('--enable-all', '--disable-all')` |\n| 12   | `INVALID_CONFIG`        | config has invalid properties | `🐊 .putout.json: exclude: must NOT have additional properties`            |\n| 13   | `UNHANDLED`             | unhandled exception           | `\u003cunhandled exception\u003e`                                                    |\n| 14   | `CANNOT_LINT_STAGED`    | cannot lint staged            | `🐊 --staged: not git repository`                                          |\n| 15   |`INTERACTIVE_CANCELED`   | interactive canceled          | `\u003cempty\u003e`                                                                  |\n\nExample of providing invalid option:\n\n```sh\ncoderaiser@localcmd:~/putout$ putout --hello\n🐊 Invalid option `--hello`. Perhaps you meant `--help`\ncoderaiser@localcmd:~/putout$ echo $?\n7\n```\n\n### API\n\nExit codes `enum` can be imported as:\n\n```js\nimport {OK} from 'putout/exit-codes';\n```\n\n## 🦔 Real-world uses\n\n- [**Cloud Commander**](https://cloudcmd.io): orthodox file manager for the web.\n- [**Eslint Config Hardcore**](https://github.com/EvgenyOrekhov/eslint-config-hardcore): The most strict (but practical) ESLint config out there.\n- [**Mock Import**](https://github.com/coderaiser/mock-import): Mocking of Node.js EcmaScript Modules.\n- [🏎 **Madrun**](https://github.com/coderaiser/madrun): CLI tool to run multiple npm-scripts in a madly comfortable way.\n- [**Xterm.js**](https://github.com/xtermjs/xterm.js/pull/4118): A terminal for the web.\n- [**Stylelint**](https://github.com/stylelint/stylelint/issues/5291#issuecomment-920778090): A mighty, modern linter that helps you avoid errors and enforce conventions in your styles.\n- [**ESTrace**](https://github.com/coderaiser/estrace): Trace functions in EcmaScript Modules.\n- 🎩[**ESCover**](https://github.com/coderaiser/escover): Coverage for EcmaScript Modules.\n- ♨️ [**Speca**](https://github.com/coderaiser/speca): Write [tape](https://github.com/coderaiser/supertape) tests for you.\n- 🤫[**Goldstein**](https://github.com/coderaiser/goldstein): JavaScript with no limits.\n- 🎬[**MadCut**](https://github.com/coderaiser/goldstein): CLI tool to cut markdown into pieces.\n- [**Minify**](https://github.com/coderaiser/minify): a minifier of js, css, html and img files.\n- [**RedPut**](https://github.com/putoutjs/redput) - CLI tool to download source of a rule and fixtures from 🐊**Putout Editor** and generate tests from it.\n- [**RedLint**](https://github.com/putoutjs/redlint) - Linter for your Filesystem 😏💾.\n- [**Bundler**](https://github.com/putoutjs/bundler#) - Simplest possible bundler.\n- [**OpenRewrite**](https://docs.openrewrite.org/) - an open-source automated refactoring ecosystem for source code, enabling developers to effectively eliminate technical debt within their repositories.\n\nAre you also use 🐊**Putout** in your application? Please open a Pull Request to include it here. We would love to have it in our list.\n\n## 📻 Versioning Policy\n\n**Putout** follows semantic versioning ([semver](https://semver.org)) principles, with version numbers being on the format **major**.**minor**.**patch**:\n\n- **patch**: `bug fix`, `dependency update` (`17.0.0 -\u003e 17.0.1`).\n- **minor**: `new features`, `new plugins` or `fixes` (`17.0.0 -\u003e 17.1.0`).\n- **major** `breaking changes`, `plugins remove` (`17.0.0 -\u003e 18.0.0`).\n\n## 🚀 I want contribute\n\nYou can contribute by proposing a feature, fixing a bug or a typo in the documentation.\nIf you wish to play with code 🔥, [you can](https://github.com/coderaiser/putout/blob/master/CONTRIBUTING.md) 💪!\n🐊 **Putout** rejoice and wag its tail when see new contributions 👾.\n\n## 🍄 License\n\nMIT\n","funding_links":["https://github.com/sponsors/coderaiser","https://opencollective.com/cloudcmd","https://ko-fi.com/coderaiser"],"categories":["JavaScript","Linters","Libraries/Tools for refactoring","babel","Multiple languages","Analysis platforms"],"sub_categories":["JavaScript","Debian"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoderaiser%2Fputout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoderaiser%2Fputout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoderaiser%2Fputout/lists"}