123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <title>JSDoc: Home</title>
- <script src="scripts/prettify/prettify.js"> </script>
- <script src="scripts/prettify/lang-css.js"> </script>
- <!--[if lt IE 9]>
- <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
- <![endif]-->
- <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
- <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
- </head>
- <body>
- <div id="main">
- <h1 class="page-title">Home</h1>
-
-
- <h3> </h3>
-
- <section>
- <article><h1>jscodeshift <a href="https://travis-ci.org/facebook/jscodeshift"><img src="https://travis-ci.org/facebook/jscodeshift.svg?branch=master" alt="Build Status"></a></h1><p>jscodeshift is a toolkit for running codemods over multiple JS files.
- It provides:</p>
- <ul>
- <li>A runner, which executes the provided transform for each file passed to it.
- It also outputs a summary of how many files have (not) been transformed.</li>
- <li>A wrapper around <a href="https://github.com/benjamn/recast">recast</a>, providing a different API. Recast is an
- AST-to-AST transform tool and also tries to preserve the style of original code
- as much as possible.</li>
- </ul>
- <h2>Install</h2><p>Get jscodeshift from <a href="https://www.npmjs.com/">npm</a>:</p>
- <pre class="prettyprint source"><code>$ npm install -g jscodeshift</code></pre><p>This will install the runner as <code>jscodeshift</code>.</p>
- <h2>Usage (CLI)</h2><p>The CLI provides the following options:</p>
- <pre class="prettyprint source lang-text"><code>$ jscodeshift --help
- Usage: jscodeshift <path>... [options]
- path Files or directory to transform
- Options:
- -t FILE, --transform FILE Path to the transform file. Can be either a local path or url [./transform.js]
- -c, --cpus (all by default) Determines the number of processes started.
- -v, --verbose Show more information about the transform process [0]
- -d, --dry Dry run (no changes are made to files)
- -p, --print Print output, useful for development
- --babel Apply Babel to transform files [true]
- --extensions File extensions the transform file should be applied to [js]
- --ignore-pattern Ignore files that match a provided glob expression
- --ignore-config FILE Ignore files if they match patterns sourced from a configuration file (e.g., a .gitignore)
- --run-in-band Run serially in the current process [false]
- -s, --silent No output [false]
- --parser The parser to use for parsing your source files (babel | babylon | flow) [babel]
- --version print version and exit</code></pre><p>This passes the source of all passed through the transform module specified
- with <code>-t</code> or <code>--transform</code> (defaults to <code>transform.js</code> in the current
- directory). The next section explains the structure of the transform module.</p>
- <h2>Transform module</h2><p>The transform is simply a module that exports a function of the form:</p>
- <pre class="prettyprint source lang-js"><code>module.exports = function(fileInfo, api, options) {
- // transform `fileInfo.source` here
- // ...
- // return changed source
- return source;
- };</code></pre><h3>Arguments</h3><h4><code>fileInfo</code></h4><p>Holds information about the currently processed file.</p>
- <table>
- <thead>
- <tr>
- <th>Property</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>path</td>
- <td>File path</td>
- </tr>
- <tr>
- <td>source</td>
- <td>File content</td>
- </tr>
- </tbody>
- </table>
- <h4><code>api</code></h4><p>This object exposes the <code>jscodeshift</code> library and helper functions from the
- runner.</p>
- <table>
- <thead>
- <tr>
- <th>Property</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>jscodeshift</td>
- <td>A reference to the jscodeshift library</td>
- </tr>
- <tr>
- <td>stats</td>
- <td>A function to collect statistics during <code>--dry</code> runs</td>
- </tr>
- </tbody>
- </table>
- <p><code>jscodeshift</code> is a reference to the wrapper around recast and provides a
- jQuery-like API to navigate and transform the AST. Here is a quick example,
- a more detailed description can be found below.</p>
- <pre class="prettyprint source lang-js"><code>/**
- * This replaces every occurence of variable "foo".
- */
- module.exports = function(fileInfo, api) {
- return api.jscodeshift(fileInfo.source)
- .findVariableDeclarators('foo')
- .renameTo('bar')
- .toSource();
- }</code></pre><p><strong>Note:</strong> This api is exposed for convenience, but you don't have to use it.
- You can use any tool to modify the source.</p>
- <p><code>stats</code> is a function that only works when the <code>--dry</code> options is set. It accepts
- a string, and will simply count how often it was called with that value.</p>
- <p>At the end, the CLI will report those values. This can be useful while
- developing the transform, e.g. to find out how often a certain construct
- appears in the source(s).</p>
- <h4><code>options</code></h4><p>Contains all options that have been passed to runner. This allows you to pass
- additional options to the transform. For example, if the CLI is called with</p>
- <pre class="prettyprint source"><code>$ jscodeshift -t myTransforms fileA fileB --foo=bar</code></pre><p><code>options</code> would contain <code>{foo: 'bar'}</code>. jscodeshift uses <a href="https://www.npmjs.com/package/nomnom">nomnom</a> to parse
- command line options.</p>
- <h3>Return value</h3><p>The return value of the function determines the status of the transformation:</p>
- <ul>
- <li>If a string is returned and it is different from passed source, the
- transform is considered to be successful.</li>
- <li>If a string is returned but it's the same as the source, the transform
- is considered to be unsuccessful.</li>
- <li>If nothing is returned, the file is not supposed to be transformed (which is
- ok).</li>
- </ul>
- <p>The CLI provides a summary of the transformation at the end. You can get more
- detailed information by setting the <code>-v</code> option to <code>1</code> or <code>2</code>.</p>
- <p>You can collect even more stats via the <code>stats</code> function as explained above.</p>
- <h3>Parser</h3><p>The transform can let jscodeshift know with which parser to parse the source
- files (and features like templates).</p>
- <p>To do that, the transform module can export <code>parser</code>, which can either be one
- of the strings <code>"babel"</code>, <code>"babylon"</code>, or <code>"flow"</code>, or it can be a parser
- object that is compatible with with recast.</p>
- <p>For example:</p>
- <pre class="prettyprint source lang-js"><code>module.exports.parser = 'flow'; // use the flow parser
- // or
- module.exports.parser = {
- parse: function(source) {
- // return estree compatible AST
- },
- };</code></pre><h3>Example output</h3><pre class="prettyprint source lang-text"><code>$ jscodeshift -t myTransform.js src
- Processing 10 files...
- Spawning 2 workers with 5 files each...
- All workers done.
- Results: 0 errors 2 unmodified 3 skipped 5 ok</code></pre><h2>The jscodeshift API</h2><p>As already mentioned, jscodeshift also provides a wrapper around <a href="https://github.com/benjamn/recast">recast</a>.
- In order to properly use the jscodeshift API, one has to understand the basic
- building blocks of recast (and ASTs) as well.</p>
- <h3>Core Concepts</h3><h4>AST nodes</h4><p>An AST node is a plain JavaScript object with a specific set of fields, in
- accordance with the <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API">Mozilla Parser API</a>. The primary way to identify nodes
- is via their <code>type</code>.</p>
- <p>For example, string literals are represented via <code>Literal</code> nodes, which
- have the structure</p>
- <pre class="prettyprint source lang-js"><code>// "foo"
- {
- type: 'Literal',
- value: 'foo',
- raw: '"foo"'
- }</code></pre><p>It's OK to not know the structure of every AST node type.
- The <a href="http://astexplorer.net/">(esprima) AST explorer</a> is an online tool to inspect the AST
- for a given piece of JS code.</p>
- <h4>Path objects</h4><p>Recast itself relies heavily on <a href="https://github.com/benjamn/ast-types">ast-types</a> which defines methods to traverse
- the AST, access node fields and build new nodes. ast-types wraps every AST node
- into a <em>path object</em>. Paths contain meta-information and helper methods to
- process AST nodes.</p>
- <p>For example, the child-parent relationship between two nodes is not explicitly
- defined. Given a plain AST node, it is not possible to traverse the tree <em>up</em>.
- Given a path object however, the parent can be traversed to via <code>path.parent</code>.</p>
- <p>For more information about the path object API, please have a look at
- <a href="https://github.com/benjamn/ast-types">ast-types</a>.</p>
- <h4>Builders</h4><p>To make creating AST nodes a bit simpler and "safer", ast-types defines a couple
- of <em>builder methods</em>, which are also exposed on <code>jscodeshift</code>.</p>
- <p>For example, the following creates an AST equivalent to <code>foo(bar)</code>:</p>
- <pre class="prettyprint source lang-js"><code>// inside a module transform
- var j = jscodeshift;
- // foo(bar);
- var ast = j.callExpression(
- j.identifier('foo'),
- [j.identifier('bar')]
- );</code></pre><p>The signature of each builder function is best learned by having a look at the
- <a href="https://github.com/benjamn/ast-types/blob/master/def/">definition files</a>.</p>
- <h3>Collections and Traversal</h3><p>In order to transform the AST, you have to traverse it and find the nodes that
- need to be changed. jscodeshift is built around the idea of <strong>collections</strong> of
- paths and thus provides a different way of processing an AST than recast or
- ast-types.</p>
- <p>A collection has methods to process the nodes inside a collection, often
- resulting in a new collection. This results in a fluent interface, which can
- make the transform more readable.</p>
- <p>Collections are "typed" which means that the type of a collection is the
- "lowest" type all AST nodes in the collection have in common. That means you
- cannot call a method for a <code>FunctionExpression</code> collection on an <code>Identifier</code>
- collection.</p>
- <p>Here is an example of how one would find/traverse all <code>Identifier</code> nodes with
- jscodeshift and with recast:</p>
- <pre class="prettyprint source lang-js"><code>// recast
- var ast = recast.parse(src);
- recast.visit(ast, {
- visitIdentifier: function(path) {
- // do something with path
- return false;
- }
- });
- // jscodeshift
- jscodeshift(src)
- .find(jscodeshift.Identifier)
- .forEach(function(path) {
- // do something with path
- });</code></pre><p>To learn about the provided methods, have a look at the
- <a href="src/Collection.js">Collection.js</a> and its <a href="src/collections/">extensions</a>.</p>
- <h3>Extensibility</h3><p>jscodeshift provides an API to extend collections. By moving common operators
- into helper functions (which can be stored separately in other modules), a
- transform can be made more readable.</p>
- <p>There are two types of extensions: generic extensions and type-specific
- extensions. <strong>Generic extensions</strong> are applicable to all collections. As such,
- they typically don't access specific node data, but rather traverse the AST from
- the nodes in the collection. <strong>Type-specific</strong> extensions work only on specific
- node types and are not callable on differently typed collections.</p>
- <h4>Examples</h4><pre class="prettyprint source lang-js"><code>// Adding a method to all Identifiers
- jscodeshift.registerMethods({
- logNames: function() {
- return this.forEach(function(path) {
- console.log(path.node.name);
- });
- }
- }, jscodeshift.Identifier);
- // Adding a method to all collections
- jscodeshift.registerMethods({
- findIdentifiers: function() {
- return this.find(jscodeshift.Identifier);
- }
- });
- jscodeshift(ast).findIdentifiers().logNames();
- jscodeshift(ast).logNames(); // error, unless `ast` only consists of Identifier nodes</code></pre><h3>Passing options to <a href="https://github.com/benjamn/recast">recast</a></h3><p>You may want to change some of the output settings (like setting <code>'</code> instead of <code>"</code>).
- This can be done by passing config options to <a href="https://github.com/benjamn/recast">recast</a>.</p>
- <pre class="prettyprint source lang-js"><code>.toSource({quote: 'single'}); // sets strings to use single quotes in transformed code.</code></pre><p>You can also pass options to recast's <code>parse</code> method by passing an object to
- jscodeshift as second argument:</p>
- <pre class="prettyprint source lang-js"><code>jscodeshift(source, {...})</code></pre><p>More on config options <a href="https://github.com/benjamn/recast/blob/52a7ec3eaaa37e78436841ed8afc948033a86252/lib/options.js#L61">here</a></p>
- <h3>Unit Testing</h3><p>jscodeshift comes with a simple utility to allow easy unit testing with <a href="https://facebook.github.io/jest/">Jest</a>, without having to write a lot of boilerplate code. This utility makes some assumptions in order to reduce the amount of configuration required:</p>
- <ul>
- <li>The test is located in a subdirectory under the directory the transform itself is located in (eg. <code>__tests__</code>)</li>
- <li>Test fixtures are located in a <code>__testfixtures__</code> directory</li>
- </ul>
- <p>This results in a directory structure like this:</p>
- <pre class="prettyprint source"><code>/MyTransform.js
- /__tests__/MyTransform-test.js
- /__testfixtures__/MyTransform.input.js
- /__testfixtures__/MyTransform.output.js</code></pre><p>To define a test, use <code>defineTest</code> from the <code>testUtils</code> module:</p>
- <pre class="prettyprint source lang-js"><code>jest.autoMockOff();
- const defineTest = require('jscodeshift/dist/testUtils').defineTest;
- defineTest(__dirname, 'MyTransform');</code></pre><p>An alternate fixture filename can be provided as the fourth argument to <code>defineTest</code>. This also means that multiple test fixtures can be provided:</p>
- <pre class="prettyprint source lang-js"><code>defineTest(__dirname, 'MyTransform', null, 'FirstFixture');
- defineTest(__dirname, 'MyTransform', null, 'SecondFixture');</code></pre><p>This will run two tests: One for <code>__testfixtures__/FirstFixture.input.js</code> and one for <code>__testfixtures__/SecondFixture.input.js</code></p>
- <p>A simple example is bundled in the <a href="sample">sample directory</a>.</p>
- <h3>Example Codemods</h3><ul>
- <li><a href="https://github.com/reactjs/react-codemod">react-codemod</a> - React codemod scripts to update React APIs.</li>
- <li><a href="https://github.com/cpojer/js-codemod/">js-codemod</a> - Codemod scripts to transform code to next generation JS.</li>
- <li><a href="https://github.com/jhgg/js-transforms">js-transforms</a> - Some documented codemod experiments to help you learn.</li>
- </ul>
- <h3>Recipes</h3><ul>
- <li><a href="recipes/retain-first-comment.md">Retain leading comment(s) in file when replacing/removing first statement</a></li>
- </ul>
- <h3>Support</h3><ul>
- <li>Discord - <a href="https://discordapp.com/channels/102860784329052160/103748721107292160">#codemod</a> on <a href="http://www.reactiflux.com/">Reactiflux</a></li>
- </ul></article>
- </section>
- </div>
- <nav>
- <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-jscodeshift.html">jscodeshift</a></li></ul><h3>Externals</h3><ul><li><a href="external-astTypes.html">astTypes</a></li></ul><h3>Classes</h3><ul><li><a href="Collection.html">Collection</a></li></ul><h3>Mixins</h3><ul><li><a href="globalMethods.html">globalMethods</a></li><li><a href="mutationMethods.html">mutationMethods</a></li><li><a href="transformMethods.html">transformMethods</a></li><li><a href="traversalMethods.html">traversalMethods</a></li></ul><h3>Global</h3><ul><li><a href="global.html#registerMethods">registerMethods</a></li></ul>
- </nav>
- <br class="clear">
- <footer>
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.1</a> on Wed Sep 21 2016 16:53:09 GMT-0400 (EDT)
- </footer>
- <script> prettyPrint(); </script>
- <script src="scripts/linenumber.js"> </script>
- </body>
- </html>
|