├── .eslintignore ├── .eslintrc ├── .github └── CODE_OF_CONDUCT.md ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .transformignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── coverage ├── clover.xml ├── coverage-final.json ├── lcov-report │ ├── base.css │ ├── block-navigation.js │ ├── favicon.png │ ├── fix-js │ │ ├── coverage │ │ │ └── lcov-report │ │ │ │ ├── block-navigation.js.html │ │ │ │ ├── index.html │ │ │ │ ├── prettify.js.html │ │ │ │ └── sorter.js.html │ │ ├── example │ │ │ ├── asPackage.js.html │ │ │ ├── index.html │ │ │ └── withJSCodeshift.js.html │ │ ├── index.html │ │ ├── index.js.html │ │ ├── transforms │ │ │ ├── __testfixtures__ │ │ │ │ ├── index.html │ │ │ │ ├── no-lonely-if.input.js.html │ │ │ │ ├── no-lonely-if.output.js.html │ │ │ │ ├── no-nested-ternary.input.js.html │ │ │ │ ├── no-nested-ternary.output.js.html │ │ │ │ ├── no-unused-vars.input.js.html │ │ │ │ ├── no-unused-vars.output.js.html │ │ │ │ ├── react-action-as.input.js.html │ │ │ │ └── react-action-as.output.js.html │ │ │ ├── index.html │ │ │ ├── no-lonely-if.js.html │ │ │ ├── no-nested-ternary.js.html │ │ │ ├── no-unused-vars.js.html │ │ │ ├── react-action-as.js.html │ │ │ ├── react-destruct-assign.js.html │ │ │ └── with-globals │ │ │ │ ├── block-scoped-vars.js.html │ │ │ │ ├── index.html │ │ │ │ ├── leaking-global-vars.js.html │ │ │ │ ├── no-camelcase-vars.js.html │ │ │ │ ├── no-underscore-dangle.js.html │ │ │ │ └── unused-assigned-vars.js.html │ │ └── utils │ │ │ ├── find-globals-exposed.js.html │ │ │ └── index.html │ ├── index.html │ ├── no-lonely-if.js.html │ ├── no-nested-ternary.js.html │ ├── no-unused-vars.js.html │ ├── prettify.css │ ├── prettify.js │ ├── react-action-as.js.html │ ├── react-destruct-assign.js.html │ ├── sort-arrow-sprite.png │ └── sorter.js └── lcov.info ├── example ├── asPackage.js ├── dependencies.json └── withJSCodeshift.js ├── index.js ├── package-lock.json ├── package.json ├── static └── constants.json ├── transforms ├── __testfixtures__ │ ├── block-scoped-vars.input.js │ ├── block-scoped-vars.output.js │ ├── no-camelcase-fix-dependencies.input.js │ ├── no-camelcase-fix-dependencies.output.js │ ├── no-camelcase-fix-exposed-functions.input.js │ ├── no-camelcase-fix-exposed-functions.output.js │ ├── no-camelcase.input.js │ ├── no-camelcase.output.js │ ├── no-lonely-if.input.js │ ├── no-lonely-if.output.js │ ├── no-nested-ternary.input.js │ ├── no-nested-ternary.output.js │ ├── no-unused-vars-skip-disable-comments.input.js │ ├── no-unused-vars-skip-disable-comments.output.js │ ├── no-unused-vars.input.js │ ├── no-unused-vars.output.js │ ├── react-action-as.input.js │ ├── react-action-as.output.js │ ├── react-destruct-assign.input.js │ └── react-destruct-assign.output.js ├── __tests__ │ ├── block-scoped-vars-test.js │ ├── no-camelcase-test.js │ ├── no-lonely-if-test.js │ ├── no-nested-ternary-test.js │ ├── no-unused-vars-test.js │ ├── react-action-as-test.js │ └── react-destruct-assign-test.js ├── block-scoped-vars.js ├── no-camelcase.js ├── no-lonely-if.js ├── no-nested-ternary.js ├── no-unused-vars.js ├── react-action-as.js ├── react-destruct-assign.js └── with-globals │ ├── leaking-global-vars.js │ ├── no-underscore-dangle.js │ └── unused-assigned-vars.js └── utils └── find-globals-exposed.js /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | example/ 4 | __tests__/ 5 | __testfixtures__/ 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es6": true, 6 | "mocha": true 7 | }, 8 | "extends": [ 9 | "airbnb-base", 10 | "prettier" 11 | ], 12 | "globals": { 13 | "Atomics": "readonly", 14 | "SharedArrayBuffer": "readonly" 15 | }, 16 | "parserOptions": { 17 | "ecmaVersion": 2018 18 | }, 19 | "plugins": [ 20 | "prettier" 21 | ], 22 | "rules": { 23 | "comma-dangle": [ 24 | "error", 25 | "never" 26 | ], 27 | "import/no-cycle": "warn", 28 | "import/no-extraneous-dependencies": [ 29 | "warn", 30 | { 31 | "devDependencies": true 32 | } 33 | ], 34 | "import/no-unresolved": "error", 35 | "max-len": [ 36 | "error", 37 | { 38 | "code": 120 39 | } 40 | ], 41 | "no-tabs": [ 42 | "error", 43 | { 44 | "allowIndentationTabs": true 45 | } 46 | ], 47 | "no-console": "off", 48 | "no-plusplus": "off", 49 | "no-param-reassign": "off", 50 | "prettier/prettier": "error", 51 | "no-use-before-define": ["error", { "variables": false }] 52 | } 53 | } -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contribute to creating a positive environment include: 10 | 11 | - Using welcoming and inclusive language 12 | - Being respectful of differing viewpoints and experiences 13 | - Gracefully accepting constructive criticism 14 | - Focusing on what is best for the community 15 | - Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | - The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | - Trolling, insulting/derogatory comments, and personal or political attacks 21 | - Public or private harassment 22 | - Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | - Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at anshgm123@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .nyc_output/ 3 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | example/ 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "printWidth": 120, 4 | "semi": true, 5 | "singleQuote": true, 6 | "tabWidth": 2, 7 | "trailingComma": "none" 8 | } -------------------------------------------------------------------------------- /.transformignore: -------------------------------------------------------------------------------- 1 | ^socket 2 | .min.js 3 | polyfill 4 | prettify 5 | run_prettify 6 | libraries 7 | google-code-prettify 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 10.13.0 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Readme Markdown Generator 2 | 3 | 👍🎉 First off, thanks for taking the time to contribute! 🎉👍 4 | 5 | When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. 6 | Please note we have a [code of conduct](https://github.com/anshckr/fix-js/blob/master/.github/CODE_OF_CONDUCT.md), please follow it in all your interactions with the project. 7 | 8 | ## Table of Contents 9 | 10 | - [Setting Up the project locally](#setting-up-the-project-locally) 11 | - [Submitting a Pull Request](#submitting-a-pull-request) 12 | 13 | ## Setting Up the project locally 14 | 15 | To install the project you need to have `node` and `npm` 16 | 17 | 1. [Fork](https://help.github.com/articles/fork-a-repo/) the project, clone 18 | your fork: 19 | 20 | ```sh 21 | # Clone your fork 22 | git clone https://github.com//fix-js.git 23 | 24 | # Navigate to the newly cloned directory 25 | cd fix-js 26 | ``` 27 | 28 | 2. from the root of the project: `npm` to install all dependencies 29 | 30 | - make sure you have latest `npm` version 31 | 32 | > Tip: Keep your `master` branch pointing at the original repository and make 33 | > pull requests from branches on your fork. To do this, run: 34 | > 35 | > ```sh 36 | > git remote add upstream https://github.com/anshckr/fix-js.git 37 | > git fetch upstream 38 | > git branch --set-upstream-to=upstream/master master 39 | > ``` 40 | > 41 | > This will add the original repository as a "remote" called "upstream," then 42 | > fetch the git information from that remote, then set your local `master` 43 | > branch to use the upstream master branch whenever you run `git pull`. Then you 44 | > can make all of your pull request branches based on this `master` branch. 45 | > Whenever you want to update your version of `master`, do a regular `git pull`. 46 | 47 | ## Submitting a Pull Request 48 | 49 | Please go through existing issues and pull requests to check if somebody else is already working on it. 50 | 51 | Also, make sure to check linting issues in the code before you commit your 52 | changes. 53 | 54 | ```sh 55 | npm run lint:check 56 | ``` -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Anshul Nema 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/anshckr/fix-js.svg?branch=master)](https://travis-ci.org/anshckr/fix-js) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) [![GitHub license](https://img.shields.io/github/license/anshckr/fix-js)](https://github.com/anshckr/fix-js/blob/master/LICENSE) [![GitHub stars](https://img.shields.io/github/stars/anshckr/fix-js)](https://github.com/anshckr/fix-js/stargazers) 2 | 3 | This repository contains a collection of codemod scripts for use with 4 | [JSCodeshift](https://github.com/facebook/jscodeshift) + it can also be added as a package to use the other transformers it exposes 5 | 6 | ## Setup & Run When Using 'jscodeshift' 7 | 8 | ```sh 9 | npm install -g jscodeshift 10 | git clone https://github.com/anshckr/fix-js.git 11 | jscodeshift -t 12 | ``` 13 | 14 | Use the `-d` option for a dry-run and use `-p` to print the output for 15 | comparison. 16 | 17 | ### Recast Options 18 | 19 | [Options to recast's printer](https://github.com/benjamn/recast/blob/master/lib/options.ts) can be provided through the `printOptions` command line argument 20 | 21 | ```sh 22 | jscodeshift -t transform.js --printOptions='{"quote":"double"}' 23 | ``` 24 | 25 | ### Included Scripts 26 | 27 | #### `no-lonely-if` 28 | 29 | Fixes eslint no-lonely-if rule 30 | 31 | ```sh 32 | jscodeshift -t ./transforms/no-lonely-if.js 33 | ``` 34 | 35 | ```js 36 | else { 37 | if (someCondition) { 38 | ... 39 | } else { 40 | ... 41 | } 42 | } 43 | ``` 44 | 45 | The above will get converted to 46 | 47 | ```js 48 | else if (someCondition) { 49 | ... 50 | } else { 51 | ... 52 | } 53 | ``` 54 | 55 | #### `no-nested-ternary` 56 | 57 | Fixes eslint no-nested-ternary rule by converting the nested ConditionalExpressions into an IIFE block with If/Else Statements 58 | 59 | ```sh 60 | jscodeshift -t ./transforms/no-nested-ternary.js 61 | ``` 62 | 63 | ```js 64 | a ? 'a' : b ? 'b' : 'c' 65 | ``` 66 | 67 | The above will get converted to 68 | 69 | ```js 70 | (function() { 71 | if (a) { 72 | return 'a'; 73 | } 74 | 75 | if (b) { 76 | return 'b'; 77 | } 78 | 79 | return 'c'; 80 | })() 81 | ``` 82 | 83 | #### `no-unused-vars` 84 | 85 | Fixes eslint no-unused-vars rule. Adds disable comment/block wherever the function/variable getting fixed is globally exposed 86 | 87 | ```sh 88 | jscodeshift -t ./transforms/no-unused-vars.js 89 | ``` 90 | 91 | ```js 92 | function someFunc(index) {} 93 | var someUsedVar = 0, someUnUsedVar = false; 94 | var someVar = (function(){ 95 | var someInternalVar; 96 | 97 | function someInternalFunc() {}; 98 | 99 | someUsedVar = 1; 100 | return someUsedVar; 101 | })(); 102 | ``` 103 | 104 | The above will get converted to 105 | 106 | ```js 107 | // eslint-disable-next-line no-unused-vars 108 | function someFunc() {} 109 | var someUsedVar = 0; 110 | window.someUnUsedVar = false; 111 | 112 | window.someVar = (function(){ 113 | someUsedVar = 1; 114 | return someUsedVar; 115 | })(); 116 | ``` 117 | 118 | ##### Options: 119 | 120 | `--skip-disable-comments=true`: Doesn't add eslint disable comment/block to globals exposed 121 | 122 | #### `react-action-as` 123 | 124 | Transforms all named export actions use 'as' while importing. Also converts the 'bindActionCreators' objectExpressionNode to use the as imported action 125 | 126 | ```sh 127 | jscodeshift -t ./transforms/react-action-as.js 128 | ``` 129 | 130 | ```jsx 131 | import { someAction } from '../actions'; 132 | 133 | const mapDispatchToProps = (dispatch) => 134 | bindActionCreators( 135 | { 136 | someAction 137 | }, 138 | dispatch 139 | ); 140 | ``` 141 | 142 | The above will get converted to 143 | 144 | ```jsx 145 | import { someAction as someActionAction } from '../actions'; 146 | 147 | const mapDispatchToProps = (dispatch) => 148 | bindActionCreators( 149 | { 150 | someAction: someActionAction 151 | }, 152 | dispatch 153 | ); 154 | ``` 155 | 156 | #### `react-destruct-assign` 157 | 158 | Transformer to fix react/destructuring-assignment rule 159 | 160 | ```sh 161 | jscodeshift -t ./transforms/react-destruct-assign.js 162 | ``` 163 | 164 | ```jsx 165 | render() { 166 | if (this.props.someProp) { 167 | return this.state.someState; 168 | } 169 | } 170 | ``` 171 | 172 | The above will get converted to 173 | 174 | ```jsx 175 | render() { 176 | const { someProp } = this.props; 177 | const { someState } = this.state; 178 | if (someProp) { 179 | return someState; 180 | } 181 | } 182 | ``` 183 | 184 | #### `block-scoped-var` 185 | 186 | Transformer that moves all the variable declarators to their scope level 187 | 188 | ```sh 189 | jscodeshift -t ./transforms/block-scoped-var.js 190 | ``` 191 | 192 | ```js 193 | function someFunc() { 194 | if (someCondition) { 195 | var i = 1; 196 | } else { 197 | var i = 2; 198 | } 199 | 200 | for (var j = 0; j < i; j++) { 201 | ... 202 | } 203 | 204 | for (var k in someObj) { 205 | ... 206 | } 207 | } 208 | ``` 209 | 210 | The above will get converted to 211 | 212 | ```js 213 | function someFunc() { 214 | var i, j, k; 215 | if (someCondition) { 216 | i = 1; 217 | } else { 218 | i = 2; 219 | } 220 | 221 | for (j = 0; j < i; j++) { 222 | ... 223 | } 224 | 225 | for (k in someObj) { 226 | ... 227 | } 228 | } 229 | ``` 230 | 231 | #### `no-camelcase` 232 | 233 | Transformer to fix all the non camel cased variables and function names in a JS file 234 | 235 | ```sh 236 | jscodeshift -t ./transforms/no-camelcase.js 237 | ``` 238 | 239 | ##### Options: 240 | 241 | `--fix-exposed-functions=true`: Fixes non camel-cased functions that are exposed from the file 242 | 243 | `--fix-dependencies=true`: Finds all the dependencies needed by the file and fixes them if they are not camel-cased 244 | 245 | ```js 246 | var _some_var, $some_var; 247 | function some_func() {} 248 | some_func(); 249 | ``` 250 | 251 | The above will get converted to (with no options passed) 252 | 253 | ```js 254 | var someVar, $someVar; 255 | function some_func() {} 256 | some_func(); 257 | ``` 258 | 259 | ## Setup & Run When Using As A Package 260 | 261 | ```sh 262 | $ npm i @anshckr/fix-js 263 | ``` 264 | In Node.js: 265 | 266 | ```js 267 | 268 | var { 269 | fixJSsAtPath, 270 | transformLeakingGlobalsVars, 271 | transformUnusedAssignedVars, 272 | transformNoUnderscoreDangle 273 | } = require('@anshckr/fix-js'); 274 | 275 | ``` 276 | 277 | ## API 278 | 279 | ### 1. `fixJSsAtPath` (Transforms all the JS files at the dirPath) 280 | 281 | | Parameter | Type | Description | 282 | | :--- | :--- | :--- | 283 | | `dirPath` | `String` | **Required**. The directory path where you want to run the transform at | 284 | | `transformer` | `Function` | **Required**. The transformer which will modify the JS files | 285 | | `paramsIgnoreFilesRegex` | `Regex` | **Optional**. Regular expression to match file names to ignore during transform. **Default:** /$^/ | 286 | | `paramsIgnoreFoldersRegex` | `Regex` | **Optional**. Regular expression to match folder names to ignore during transform. **Default:** /$^/ | 287 | | `paramsIgnoreableExternalDeps` | `Array` | **Optional**. Array of dependencies to ignore during transform. **Default:** [] | 288 | 289 | 290 | ### 2. `transformLeakingGlobalsVars` (Transformer to fix all the leaking globals from a JS file) 291 | 292 | | Parameter | Type | Description | 293 | | :--- | :--- | :--- | 294 | | `filePath ` | `String` | **Required**. The file path you want to fix | 295 | | `dependencies ` | `Function` | **Optional**. Array of dependencies you want to fix for the file at filePath. **Default:** All the global dependencies for the file | 296 | | `updateInplace ` | `Boolean` | **Optional**. Whether to update the file or not. **Default:** false | 297 | 298 | **Returns** 299 | 300 | | Type | Description | 301 | | :--- | :--- | 302 | | `String` | Transformed file content | 303 | 304 | **Example** 305 | 306 | ```js 307 | for (i = 0; i < 10; i++) {....} 308 | ``` 309 | 310 | In the above code if we don't declare `i` in the upper scope like `var i` then `i` becomes a global leak 311 | 312 | The utility will declare these types leaking variables 313 | 314 | 315 | ### 3. `transformUnusedAssignedVars` (Transformer to fix all the unused assigned variables from a JS file) 316 | 317 | | Parameter | Type | Description | 318 | | :--- | :--- | :--- | 319 | | `filePath ` | `String` | **Required**. The file path you want to fix | 320 | | `updateInplace ` | `Boolean` | **Optional**. Whether to update the file or not. **Default:** false | 321 | 322 | **Returns** 323 | 324 | | Type | Description | 325 | | :--- | :--- | 326 | | `String` | Transformed file content | 327 | 328 | ### 4. `transformNoUnderscoreDangle` (Transformer to fix leading '__' in function names to "\_", removes "\_" from function params) 329 | 330 | | Parameter | Type | Description | 331 | | :--- | :--- | :--- | 332 | | `filePath ` | `String` | **Required**. The file path you want to fix | 333 | | `updateInplace ` | `Boolean` | **Optional**. Whether to update the file or not. **Default:** false | 334 | | `collectedGlobals ` | `Object` | **Optional**. Contains two keys globalsExposed, dependencies for the file. **Default:** {} | 335 | 336 | **Returns** 337 | 338 | | Type | Description | 339 | | :--- | :--- | 340 | | `String` | Transformed file content | 341 | 342 | **Example** 343 | 344 | ```js 345 | function __someFunc(_someParam) { 346 | ..._someParam 347 | } 348 | __someFunc(); 349 | ``` 350 | 351 | The above will get converted to 352 | 353 | ```js 354 | function _someFunc(someParam) { 355 | ...someParam 356 | } 357 | _someFunc(); 358 | ``` 359 | 360 | ## Usage 361 | 362 | Refer the [example folder](https://github.com/anshckr/fix-js/tree/master/example) 363 | 364 | ## 🤝 Contributing 365 | 366 | Contributions, issues and feature requests are welcome!
Feel free to check [issues page](https://github.com/anshckr/fix-js/issues). You can also take a look at the [contributing guide](https://github.com/anshckr/fix-js/blob/master/CONTRIBUTING.md). 367 | 368 | ## Show your support 369 | 370 | Give a ⭐️ if this project helped you! 371 | 372 | ## License 373 | 374 | @anshckr/fix-js is freely distributable under the terms of the [MIT license](https://github.com/anshckr/fix-js/blob/master/LICENSE) 375 | -------------------------------------------------------------------------------- /coverage/lcov-report/base.css: -------------------------------------------------------------------------------- 1 | body, html { 2 | margin:0; padding: 0; 3 | height: 100%; 4 | } 5 | body { 6 | font-family: Helvetica Neue, Helvetica, Arial; 7 | font-size: 14px; 8 | color:#333; 9 | } 10 | .small { font-size: 12px; } 11 | *, *:after, *:before { 12 | -webkit-box-sizing:border-box; 13 | -moz-box-sizing:border-box; 14 | box-sizing:border-box; 15 | } 16 | h1 { font-size: 20px; margin: 0;} 17 | h2 { font-size: 14px; } 18 | pre { 19 | font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; 20 | margin: 0; 21 | padding: 0; 22 | -moz-tab-size: 2; 23 | -o-tab-size: 2; 24 | tab-size: 2; 25 | } 26 | a { color:#0074D9; text-decoration:none; } 27 | a:hover { text-decoration:underline; } 28 | .strong { font-weight: bold; } 29 | .space-top1 { padding: 10px 0 0 0; } 30 | .pad2y { padding: 20px 0; } 31 | .pad1y { padding: 10px 0; } 32 | .pad2x { padding: 0 20px; } 33 | .pad2 { padding: 20px; } 34 | .pad1 { padding: 10px; } 35 | .space-left2 { padding-left:55px; } 36 | .space-right2 { padding-right:20px; } 37 | .center { text-align:center; } 38 | .clearfix { display:block; } 39 | .clearfix:after { 40 | content:''; 41 | display:block; 42 | height:0; 43 | clear:both; 44 | visibility:hidden; 45 | } 46 | .fl { float: left; } 47 | @media only screen and (max-width:640px) { 48 | .col3 { width:100%; max-width:100%; } 49 | .hide-mobile { display:none!important; } 50 | } 51 | 52 | .quiet { 53 | color: #7f7f7f; 54 | color: rgba(0,0,0,0.5); 55 | } 56 | .quiet a { opacity: 0.7; } 57 | 58 | .fraction { 59 | font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; 60 | font-size: 10px; 61 | color: #555; 62 | background: #E8E8E8; 63 | padding: 4px 5px; 64 | border-radius: 3px; 65 | vertical-align: middle; 66 | } 67 | 68 | div.path a:link, div.path a:visited { color: #333; } 69 | table.coverage { 70 | border-collapse: collapse; 71 | margin: 10px 0 0 0; 72 | padding: 0; 73 | } 74 | 75 | table.coverage td { 76 | margin: 0; 77 | padding: 0; 78 | vertical-align: top; 79 | } 80 | table.coverage td.line-count { 81 | text-align: right; 82 | padding: 0 5px 0 20px; 83 | } 84 | table.coverage td.line-coverage { 85 | text-align: right; 86 | padding-right: 10px; 87 | min-width:20px; 88 | } 89 | 90 | table.coverage td span.cline-any { 91 | display: inline-block; 92 | padding: 0 5px; 93 | width: 100%; 94 | } 95 | .missing-if-branch { 96 | display: inline-block; 97 | margin-right: 5px; 98 | border-radius: 3px; 99 | position: relative; 100 | padding: 0 4px; 101 | background: #333; 102 | color: yellow; 103 | } 104 | 105 | .skip-if-branch { 106 | display: none; 107 | margin-right: 10px; 108 | position: relative; 109 | padding: 0 4px; 110 | background: #ccc; 111 | color: white; 112 | } 113 | .missing-if-branch .typ, .skip-if-branch .typ { 114 | color: inherit !important; 115 | } 116 | .coverage-summary { 117 | border-collapse: collapse; 118 | width: 100%; 119 | } 120 | .coverage-summary tr { border-bottom: 1px solid #bbb; } 121 | .keyline-all { border: 1px solid #ddd; } 122 | .coverage-summary td, .coverage-summary th { padding: 10px; } 123 | .coverage-summary tbody { border: 1px solid #bbb; } 124 | .coverage-summary td { border-right: 1px solid #bbb; } 125 | .coverage-summary td:last-child { border-right: none; } 126 | .coverage-summary th { 127 | text-align: left; 128 | font-weight: normal; 129 | white-space: nowrap; 130 | } 131 | .coverage-summary th.file { border-right: none !important; } 132 | .coverage-summary th.pct { } 133 | .coverage-summary th.pic, 134 | .coverage-summary th.abs, 135 | .coverage-summary td.pct, 136 | .coverage-summary td.abs { text-align: right; } 137 | .coverage-summary td.file { white-space: nowrap; } 138 | .coverage-summary td.pic { min-width: 120px !important; } 139 | .coverage-summary tfoot td { } 140 | 141 | .coverage-summary .sorter { 142 | height: 10px; 143 | width: 7px; 144 | display: inline-block; 145 | margin-left: 0.5em; 146 | background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; 147 | } 148 | .coverage-summary .sorted .sorter { 149 | background-position: 0 -20px; 150 | } 151 | .coverage-summary .sorted-desc .sorter { 152 | background-position: 0 -10px; 153 | } 154 | .status-line { height: 10px; } 155 | /* yellow */ 156 | .cbranch-no { background: yellow !important; color: #111; } 157 | /* dark red */ 158 | .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } 159 | .low .chart { border:1px solid #C21F39 } 160 | .highlighted, 161 | .highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ 162 | background: #C21F39 !important; 163 | } 164 | /* medium red */ 165 | .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } 166 | /* light red */ 167 | .low, .cline-no { background:#FCE1E5 } 168 | /* light green */ 169 | .high, .cline-yes { background:rgb(230,245,208) } 170 | /* medium green */ 171 | .cstat-yes { background:rgb(161,215,106) } 172 | /* dark green */ 173 | .status-line.high, .high .cover-fill { background:rgb(77,146,33) } 174 | .high .chart { border:1px solid rgb(77,146,33) } 175 | /* dark yellow (gold) */ 176 | .status-line.medium, .medium .cover-fill { background: #f9cd0b; } 177 | .medium .chart { border:1px solid #f9cd0b; } 178 | /* light yellow */ 179 | .medium { background: #fff4c2; } 180 | 181 | .cstat-skip { background: #ddd; color: #111; } 182 | .fstat-skip { background: #ddd; color: #111 !important; } 183 | .cbranch-skip { background: #ddd !important; color: #111; } 184 | 185 | span.cline-neutral { background: #eaeaea; } 186 | 187 | .coverage-summary td.empty { 188 | opacity: .5; 189 | padding-top: 4px; 190 | padding-bottom: 4px; 191 | line-height: 1; 192 | color: #888; 193 | } 194 | 195 | .cover-fill, .cover-empty { 196 | display:inline-block; 197 | height: 12px; 198 | } 199 | .chart { 200 | line-height: 0; 201 | } 202 | .cover-empty { 203 | background: white; 204 | } 205 | .cover-full { 206 | border-right: none !important; 207 | } 208 | pre.prettyprint { 209 | border: none !important; 210 | padding: 0 !important; 211 | margin: 0 !important; 212 | } 213 | .com { color: #999 !important; } 214 | .ignore-none { color: #999; font-weight: normal; } 215 | 216 | .wrapper { 217 | min-height: 100%; 218 | height: auto !important; 219 | height: 100%; 220 | margin: 0 auto -48px; 221 | } 222 | .footer, .push { 223 | height: 48px; 224 | } 225 | -------------------------------------------------------------------------------- /coverage/lcov-report/block-navigation.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | var jumpToCode = (function init() { 3 | // Classes of code we would like to highlight in the file view 4 | var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; 5 | 6 | // Elements to highlight in the file listing view 7 | var fileListingElements = ['td.pct.low']; 8 | 9 | // We don't want to select elements that are direct descendants of another match 10 | var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` 11 | 12 | // Selecter that finds elements on the page to which we can jump 13 | var selector = 14 | fileListingElements.join(', ') + 15 | ', ' + 16 | notSelector + 17 | missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` 18 | 19 | // The NodeList of matching elements 20 | var missingCoverageElements = document.querySelectorAll(selector); 21 | 22 | var currentIndex; 23 | 24 | function toggleClass(index) { 25 | missingCoverageElements 26 | .item(currentIndex) 27 | .classList.remove('highlighted'); 28 | missingCoverageElements.item(index).classList.add('highlighted'); 29 | } 30 | 31 | function makeCurrent(index) { 32 | toggleClass(index); 33 | currentIndex = index; 34 | missingCoverageElements.item(index).scrollIntoView({ 35 | behavior: 'smooth', 36 | block: 'center', 37 | inline: 'center' 38 | }); 39 | } 40 | 41 | function goToPrevious() { 42 | var nextIndex = 0; 43 | if (typeof currentIndex !== 'number' || currentIndex === 0) { 44 | nextIndex = missingCoverageElements.length - 1; 45 | } else if (missingCoverageElements.length > 1) { 46 | nextIndex = currentIndex - 1; 47 | } 48 | 49 | makeCurrent(nextIndex); 50 | } 51 | 52 | function goToNext() { 53 | var nextIndex = 0; 54 | 55 | if ( 56 | typeof currentIndex === 'number' && 57 | currentIndex < missingCoverageElements.length - 1 58 | ) { 59 | nextIndex = currentIndex + 1; 60 | } 61 | 62 | makeCurrent(nextIndex); 63 | } 64 | 65 | return function jump(event) { 66 | switch (event.which) { 67 | case 78: // n 68 | case 74: // j 69 | goToNext(); 70 | break; 71 | case 66: // b 72 | case 75: // k 73 | case 80: // p 74 | goToPrevious(); 75 | break; 76 | } 77 | }; 78 | })(); 79 | window.addEventListener('keydown', jumpToCode); 80 | -------------------------------------------------------------------------------- /coverage/lcov-report/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anshckr/fix-js/eeadc0f150501f4aecfb3ee9bd76a76e32da7c42/coverage/lcov-report/favicon.png -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/coverage/lcov-report/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/coverage/lcov-report 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files fix-js/coverage/lcov-report

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/641 29 |
30 | 31 | 32 |
33 | 0% 34 | Branches 35 | 0/323 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/52 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/106 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 |
FileStatementsBranchesFunctionsLines
block-navigation.js 78 |
79 |
0%0/280%0/150%0/60%0/28
prettify.js 93 |
94 |
0%0/5360%0/2860%0/290%0/1
sorter.js 108 |
109 |
0%0/770%0/220%0/170%0/77
122 |
123 |
124 |
125 | 130 | 131 | 132 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/example 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files fix-js/example

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/7 29 |
30 | 31 | 32 |
33 | 100% 34 | Branches 35 | 0/0 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/1 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/7 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 |
FileStatementsBranchesFunctionsLines
asPackage.js 78 |
79 |
0%0/7100%0/00%0/10%0/7
withJSCodeshift.js 93 |
94 |
0%0/00%0/00%0/00%0/0
107 |
108 |
109 |
110 | 115 | 116 | 117 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/example/withJSCodeshift.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/example/withJSCodeshift.js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files / fix-js/example withJSCodeshift.js

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/0 29 |
30 | 31 | 32 |
33 | 0% 34 | Branches 35 | 0/0 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/0 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/0 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |

60 | 
1 61 | 2 62 | 3 63 | 4  64 |   65 |   66 |  
// Example of how to use it with jscodeshift
67 |  
68 | // jscodeshift -t ./transforms/no-lonely-if.js /Users/Anshul/railsApp/app/assets/javascripts --ignore-config=./.transformignore
69 |  
70 | 71 |
72 |
73 | 78 | 79 | 80 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files fix-js

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/87 29 |
30 | 31 | 32 |
33 | 0% 34 | Branches 35 | 0/31 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/16 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/84 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |
FileStatementsBranchesFunctionsLines
index.js 78 |
79 |
0%0/870%0/310%0/160%0/84
92 |
93 |
94 |
95 | 100 | 101 | 102 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/transforms/__testfixtures__/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/transforms/__testfixtures__ 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files fix-js/transforms/__testfixtures__

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/15 29 |
30 | 31 | 32 |
33 | 0% 34 | Branches 35 | 0/16 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/5 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/15 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 |
FileStatementsBranchesFunctionsLines
no-lonely-if.input.js 78 |
79 |
0%0/20%0/40%0/10%0/2
no-lonely-if.output.js 93 |
94 |
0%0/20%0/40%0/10%0/2
no-nested-ternary.input.js 108 |
109 |
0%0/10%0/4100%0/00%0/1
no-nested-ternary.output.js 123 |
124 |
0%0/60%0/40%0/10%0/6
no-unused-vars.input.js 138 |
139 |
0%0/00%0/00%0/00%0/0
no-unused-vars.output.js 153 |
154 |
0%0/00%0/00%0/00%0/0
react-action-as.input.js 168 |
169 |
0%0/2100%0/00%0/10%0/2
react-action-as.output.js 183 |
184 |
0%0/2100%0/00%0/10%0/2
197 |
198 |
199 |
200 | 205 | 206 | 207 | 212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/transforms/__testfixtures__/no-lonely-if.input.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/transforms/__testfixtures__/no-lonely-if.input.js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files / fix-js/transforms/__testfixtures__ no-lonely-if.input.js

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/2 29 |
30 | 31 | 32 |
33 | 0% 34 | Branches 35 | 0/4 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/1 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/2 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |

 60 | 
1 61 | 2 62 | 3 63 | 4 64 | 5 65 | 6 66 | 7 67 | 8 68 | 9  69 |   70 |   71 |   72 |   73 |   74 |   75 |   76 |  
function someFunc() {
 77 |   if (true) {
 78 |   } else {
 79 |   	if (someCondition) {
 80 | 	  } else {
 81 | 	  }
 82 |   }
 83 | }
 84 |  
85 | 86 |
87 |
88 | 93 | 94 | 95 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/transforms/__testfixtures__/no-lonely-if.output.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/transforms/__testfixtures__/no-lonely-if.output.js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files / fix-js/transforms/__testfixtures__ no-lonely-if.output.js

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/2 29 |
30 | 31 | 32 |
33 | 0% 34 | Branches 35 | 0/4 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/1 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/2 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |

60 | 
1 61 | 2 62 | 3 63 | 4 64 | 5 65 | 6 66 | 7  67 |   68 |   69 |   70 |   71 |   72 |  
function someFunc() {
73 |   if (true) {
74 |   } else if (someCondition) {
75 |     } else {
76 |     }
77 | }
78 |  
79 | 80 |
81 |
82 | 87 | 88 | 89 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/transforms/__testfixtures__/no-nested-ternary.input.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/transforms/__testfixtures__/no-nested-ternary.input.js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files / fix-js/transforms/__testfixtures__ no-nested-ternary.input.js

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/1 29 |
30 | 31 | 32 |
33 | 0% 34 | Branches 35 | 0/4 36 |
37 | 38 | 39 |
40 | 100% 41 | Functions 42 | 0/0 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/1 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |

60 | 
1 61 | 2  62 |  
const os = file.name.match(/\.(apk|aab)$/) ? 'android' : file.name.match(/.ipa$/) ? 'ios' : null;
63 |  
64 | 65 |
66 |
67 | 72 | 73 | 74 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/transforms/__testfixtures__/no-nested-ternary.output.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/transforms/__testfixtures__/no-nested-ternary.output.js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files / fix-js/transforms/__testfixtures__ no-nested-ternary.output.js

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/6 29 |
30 | 31 | 32 |
33 | 0% 34 | Branches 35 | 0/4 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/1 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/6 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |

 60 | 
1 61 | 2 62 | 3 63 | 4 64 | 5 65 | 6 66 | 7 67 | 8 68 | 9 69 | 10 70 | 11 71 | 12  72 |   73 |   74 |   75 |   76 |   77 |   78 |   79 |   80 |   81 |   82 |  
const os = function() {
 83 |   if (file.name.match(/\.(apk|aab)$/)) {
 84 |     return 'android';
 85 |   } else {
 86 |     if (file.name.match(/.ipa$/)) {
 87 |       return 'ios';
 88 |     } else {
 89 |       return null;
 90 |     }
 91 |   }
 92 | }();
 93 |  
94 | 95 |
96 |
97 | 102 | 103 | 104 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/transforms/__testfixtures__/no-unused-vars.input.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/transforms/__testfixtures__/no-unused-vars.input.js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files / fix-js/transforms/__testfixtures__ no-unused-vars.input.js

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/0 29 |
30 | 31 | 32 |
33 | 0% 34 | Branches 35 | 0/0 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/0 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/0 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |

60 | 
1 
 
61 | 62 |
63 |
64 | 69 | 70 | 71 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/transforms/__testfixtures__/no-unused-vars.output.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/transforms/__testfixtures__/no-unused-vars.output.js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files / fix-js/transforms/__testfixtures__ no-unused-vars.output.js

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/0 29 |
30 | 31 | 32 |
33 | 0% 34 | Branches 35 | 0/0 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/0 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/0 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |

60 | 
1 
 
61 | 62 |
63 |
64 | 69 | 70 | 71 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/transforms/__testfixtures__/react-action-as.input.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/transforms/__testfixtures__/react-action-as.input.js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files / fix-js/transforms/__testfixtures__ react-action-as.input.js

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/2 29 |
30 | 31 | 32 |
33 | 100% 34 | Branches 35 | 0/0 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/1 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/2 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |

 60 | 
1 61 | 2 62 | 3 63 | 4 64 | 5 65 | 6 66 | 7 67 | 8 68 | 9 69 | 10 70 | 11  71 |   72 |   73 |   74 |   75 |   76 |   77 |   78 |   79 |   80 |  
import { someAction } from '../actions';
 81 |  
 82 | const mapDispatchToProps = (dispatch) => (
 83 |   bindActionCreators(
 84 |     {
 85 |       someAction
 86 |     },
 87 |     dispatch
 88 |   )
 89 | )
 90 |  
91 | 92 |
93 |
94 | 99 | 100 | 101 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/transforms/__testfixtures__/react-action-as.output.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/transforms/__testfixtures__/react-action-as.output.js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files / fix-js/transforms/__testfixtures__ react-action-as.output.js

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/2 29 |
30 | 31 | 32 |
33 | 100% 34 | Branches 35 | 0/0 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/1 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/2 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |

 60 | 
1 61 | 2 62 | 3 63 | 4 64 | 5 65 | 6 66 | 7 67 | 8 68 | 9 69 | 10 70 | 11  71 |   72 |   73 |   74 |   75 |   76 |   77 |   78 |   79 |   80 |  
import { someAction as someActionAction } from '../actions';
 81 |  
 82 | const mapDispatchToProps = (dispatch) => (
 83 |   bindActionCreators(
 84 |     {
 85 |       someAction: someActionAction
 86 |     },
 87 |     dispatch
 88 |   )
 89 | )
 90 |  
91 | 92 |
93 |
94 | 99 | 100 | 101 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/transforms/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/transforms 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files fix-js/transforms

23 |
24 | 25 |
26 | 69.73% 27 | Statements 28 | 129/185 29 |
30 | 31 | 32 |
33 | 54.12% 34 | Branches 35 | 46/85 36 |
37 | 38 | 39 |
40 | 69.09% 41 | Functions 42 | 38/55 43 |
44 | 45 | 46 |
47 | 69.73% 48 | Lines 49 | 129/185 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 |
FileStatementsBranchesFunctionsLines
no-lonely-if.js 78 |
79 |
94.12%16/1781.82%9/11100%5/594.12%16/17
no-nested-ternary.js 93 |
94 |
95.83%23/2475%9/12100%6/695.83%23/24
no-unused-vars.js 108 |
109 |
26.83%11/4125%5/208.33%1/1226.83%11/41
react-action-as.js 123 |
124 |
85.71%18/2164.29%9/14100%8/885.71%18/21
react-destruct-assign.js 138 |
139 |
74.39%61/8250%14/2875%18/2474.39%61/82
152 |
153 |
154 |
155 | 160 | 161 | 162 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/transforms/no-lonely-if.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/transforms/no-lonely-if.js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files / fix-js/transforms no-lonely-if.js

23 |
24 | 25 |
26 | 94.12% 27 | Statements 28 | 16/17 29 |
30 | 31 | 32 |
33 | 81.82% 34 | Branches 35 | 9/11 36 |
37 | 38 | 39 |
40 | 100% 41 | Functions 42 | 5/5 43 |
44 | 45 | 46 |
47 | 94.12% 48 | Lines 49 | 16/17 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |

 60 | 
1 61 | 2 62 | 3 63 | 4 64 | 5 65 | 6 66 | 7 67 | 8 68 | 9 69 | 10 70 | 11 71 | 12 72 | 13 73 | 14 74 | 15 75 | 16 76 | 17 77 | 18 78 | 19 79 | 20 80 | 21 81 | 22 82 | 23 83 | 24 84 | 25 85 | 26 86 | 27 87 | 28 88 | 29 89 | 30 90 | 31 91 | 32 92 | 33 93 | 34 94 | 35 95 | 36 96 | 37 97 | 38 98 | 39 99 | 40 100 | 41 101 | 42 102 | 431x 103 | 1x 104 |   105 | 1x 106 | 1x 107 |   108 |   109 |   110 | 1x 111 |   112 |   113 | 2x 114 |   115 | 2x 116 | 2x 117 |   118 | 2x 119 |   120 |   121 |   122 |   123 |   124 |   125 |   126 |   127 |   128 | 2x 129 |   130 | 2x 131 |   132 | 2x 133 | 1x 134 |   135 |   136 | 2x 137 | 1x 138 |   139 |   140 |   141 |   142 | 1x 143 |   144 |  
module.exports = (file, api, options) => {
145 |   const j = api.jscodeshift;
146 |  
147 |   const printOptions = options.printOptions || { quote: 'single' };
148 |   const root = j(file.source);
149 |  
150 |   // console.log('\nFixing FilePath - %s\n', file.path);
151 |  
152 |   const didTransform = root
153 |     .find(j.IfStatement)
154 |     .filter((nodePath) => {
155 |       const closestBlockStatementCollec = j(nodePath).closest(j.BlockStatement);
156 |  
157 |       Eif (closestBlockStatementCollec.length) {
158 |         const blockStatementBody = closestBlockStatementCollec.nodes()[0].body;
159 |  
160 |         return (
161 |           closestBlockStatementCollec.length &&
162 |           blockStatementBody.length === 1 &&
163 |           blockStatementBody[0].type === 'IfStatement'
164 |         );
165 |       }
166 |  
167 |       return false;
168 |     })
169 |     .forEach((nodePath) => {
170 |       const closestBlockStatementCollec = j(nodePath).closest(j.BlockStatement);
171 |  
172 |       const closestBlockStatementStart = closestBlockStatementCollec.nodes()[0].start;
173 |  
174 |       const closestIfStatementCollec = j(nodePath).closest(j.IfStatement, (node) => {
175 |         return node.alternate && node.alternate.start === closestBlockStatementStart;
176 |       });
177 |  
178 |       closestIfStatementCollec.forEach((ifStatementNodePath) => {
179 |         ifStatementNodePath.value.alternate = nodePath.value;
180 |       });
181 |     })
182 |     .size();
183 |  
184 |   return didTransform ? root.toSource(printOptions) : null;
185 | };
186 |  
187 | 188 |
189 |
190 | 195 | 196 | 197 | 202 | 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/transforms/with-globals/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/transforms/with-globals 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files fix-js/transforms/with-globals

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/480 29 |
30 | 31 | 32 |
33 | 0% 34 | Branches 35 | 0/223 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/101 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/471 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 |
FileStatementsBranchesFunctionsLines
block-scoped-vars.js 78 |
79 |
0%0/1480%0/640%0/260%0/146
leaking-global-vars.js 93 |
94 |
0%0/1420%0/610%0/240%0/139
no-camelcase-vars.js 108 |
109 |
0%0/770%0/430%0/210%0/76
no-underscore-dangle.js 123 |
124 |
0%0/770%0/400%0/240%0/76
unused-assigned-vars.js 138 |
139 |
0%0/360%0/150%0/60%0/34
152 |
153 |
154 |
155 | 160 | 161 | 162 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /coverage/lcov-report/fix-js/utils/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for fix-js/utils 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files fix-js/utils

23 |
24 | 25 |
26 | 0% 27 | Statements 28 | 0/43 29 |
30 | 31 | 32 |
33 | 0% 34 | Branches 35 | 0/24 36 |
37 | 38 | 39 |
40 | 0% 41 | Functions 42 | 0/5 43 |
44 | 45 | 46 |
47 | 0% 48 | Lines 49 | 0/42 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |
FileStatementsBranchesFunctionsLines
find-globals-exposed.js 78 |
79 |
0%0/430%0/240%0/50%0/42
92 |
93 |
94 |
95 | 100 | 101 | 102 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /coverage/lcov-report/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for All files 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files

23 |
24 | 25 |
26 | 69.73% 27 | Statements 28 | 129/185 29 |
30 | 31 | 32 |
33 | 54.12% 34 | Branches 35 | 46/85 36 |
37 | 38 | 39 |
40 | 69.09% 41 | Functions 42 | 38/55 43 |
44 | 45 | 46 |
47 | 69.73% 48 | Lines 49 | 129/185 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 |
FileStatementsBranchesFunctionsLines
no-lonely-if.js 78 |
79 |
94.12%16/1781.82%9/11100%5/594.12%16/17
no-nested-ternary.js 93 |
94 |
95.83%23/2475%9/12100%6/695.83%23/24
no-unused-vars.js 108 |
109 |
26.83%11/4125%5/208.33%1/1226.83%11/41
react-action-as.js 123 |
124 |
85.71%18/2164.29%9/14100%8/885.71%18/21
react-destruct-assign.js 138 |
139 |
74.39%61/8250%14/2875%18/2474.39%61/82
152 |
153 |
154 |
155 | 160 | 161 | 162 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /coverage/lcov-report/no-lonely-if.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for no-lonely-if.js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files no-lonely-if.js

23 |
24 | 25 |
26 | 94.12% 27 | Statements 28 | 16/17 29 |
30 | 31 | 32 |
33 | 81.82% 34 | Branches 35 | 9/11 36 |
37 | 38 | 39 |
40 | 100% 41 | Functions 42 | 5/5 43 |
44 | 45 | 46 |
47 | 94.12% 48 | Lines 49 | 16/17 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |

 60 | 
1 61 | 2 62 | 3 63 | 4 64 | 5 65 | 6 66 | 7 67 | 8 68 | 9 69 | 10 70 | 11 71 | 12 72 | 13 73 | 14 74 | 15 75 | 16 76 | 17 77 | 18 78 | 19 79 | 20 80 | 21 81 | 22 82 | 23 83 | 24 84 | 25 85 | 26 86 | 27 87 | 28 88 | 29 89 | 30 90 | 31 91 | 32 92 | 33 93 | 34 94 | 35 95 | 36 96 | 37 97 | 38 98 | 39 99 | 40 100 | 41 101 | 42 102 | 431x 103 | 1x 104 |   105 | 1x 106 | 1x 107 |   108 |   109 |   110 | 1x 111 |   112 |   113 | 2x 114 |   115 | 2x 116 | 2x 117 |   118 | 2x 119 |   120 |   121 |   122 |   123 |   124 |   125 |   126 |   127 |   128 | 2x 129 |   130 | 2x 131 |   132 | 2x 133 | 1x 134 |   135 |   136 | 2x 137 | 1x 138 |   139 |   140 |   141 |   142 | 1x 143 |   144 |  
module.exports = (file, api, options) => {
145 |   const j = api.jscodeshift;
146 |  
147 |   const printOptions = options.printOptions || { quote: 'single' };
148 |   const root = j(file.source);
149 |  
150 |   // console.log('\nFixing FilePath - %s\n', file.path);
151 |  
152 |   const didTransform = root
153 |     .find(j.IfStatement)
154 |     .filter((nodePath) => {
155 |       const closestBlockStatementCollec = j(nodePath).closest(j.BlockStatement);
156 |  
157 |       Eif (closestBlockStatementCollec.length) {
158 |         const blockStatementBody = closestBlockStatementCollec.nodes()[0].body;
159 |  
160 |         return (
161 |           closestBlockStatementCollec.length &&
162 |           blockStatementBody.length === 1 &&
163 |           blockStatementBody[0].type === 'IfStatement'
164 |         );
165 |       }
166 |  
167 |       return false;
168 |     })
169 |     .forEach((nodePath) => {
170 |       const closestBlockStatementCollec = j(nodePath).closest(j.BlockStatement);
171 |  
172 |       const closestBlockStatementStart = closestBlockStatementCollec.nodes()[0].start;
173 |  
174 |       const closestIfStatementCollec = j(nodePath).closest(j.IfStatement, (node) => {
175 |         return node.alternate && node.alternate.start === closestBlockStatementStart;
176 |       });
177 |  
178 |       closestIfStatementCollec.forEach((ifStatementNodePath) => {
179 |         ifStatementNodePath.value.alternate = nodePath.value;
180 |       });
181 |     })
182 |     .size();
183 |  
184 |   return didTransform ? root.toSource(printOptions) : null;
185 | };
186 |  
187 | 188 |
189 |
190 | 195 | 196 | 197 | 202 | 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /coverage/lcov-report/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} 2 | -------------------------------------------------------------------------------- /coverage/lcov-report/react-action-as.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for react-action-as.js 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files react-action-as.js

23 |
24 | 25 |
26 | 85.71% 27 | Statements 28 | 18/21 29 |
30 | 31 | 32 |
33 | 64.29% 34 | Branches 35 | 9/14 36 |
37 | 38 | 39 |
40 | 100% 41 | Functions 42 | 8/8 43 |
44 | 45 | 46 |
47 | 85.71% 48 | Lines 49 | 18/21 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 |
58 |
59 |

 60 | 
1 61 | 2 62 | 3 63 | 4 64 | 5 65 | 6 66 | 7 67 | 8 68 | 9 69 | 10 70 | 11 71 | 12 72 | 13 73 | 14 74 | 15 75 | 16 76 | 17 77 | 18 78 | 19 79 | 20 80 | 21 81 | 22 82 | 23 83 | 24 84 | 25 85 | 26 86 | 27 87 | 28 88 | 29 89 | 30 90 | 31 91 | 32 92 | 33 93 | 34 94 | 35 95 | 36 96 | 37 97 | 38 98 | 39 99 | 40 100 | 41 101 | 42 102 | 43 103 | 44 104 | 45 105 | 46 106 | 47 107 | 48 108 | 49 109 | 50 110 | 51 111 | 521x 112 | 1x 113 |   114 | 1x 115 | 1x 116 |   117 |   118 |   119 | 1x 120 |   121 | 1x 122 |   123 |   124 | 1x 125 | 1x 126 |   127 |   128 | 1x 129 | 1x 130 | 1x 131 |   132 |   133 |   134 |   135 |   136 |   137 |   138 | 1x 139 |   140 | 1x 141 |   142 |   143 | 1x 144 | 1x 145 |   146 |   147 |   148 | 1x 149 | 1x 150 |   151 |   152 |   153 |   154 |   155 |   156 |   157 |   158 |   159 |   160 | 1x 161 |   162 |  
module.exports = (file, api, options) => {
163 |   const j = api.jscodeshift;
164 |  
165 |   const printOptions = options.printOptions || { quote: 'single' };
166 |   const root = j(file.source);
167 |  
168 |   // console.log('\nFixing FilePath - %s\n', file.path);
169 |  
170 |   const didTransformObjExpression = root
171 |     .find(j.CallExpression, (node) => {
172 |       return node.callee.name === 'bindActionCreators';
173 |     })
174 |     .forEach((nodePath) => {
175 |       const objectExpressNode = nodePath.value.arguments.find((node) => {
176 |         return node.type === 'ObjectExpression';
177 |       });
178 |  
179 |       objectExpressNode.properties = objectExpressNode.properties.map((property) => {
180 |         Eif (property.key.name === property.value.name) {
181 |           return j.property('init', j.identifier(property.key.name), j.identifier(`${property.key.name}Action`));
182 |         }
183 |  
184 |         return property;
185 |       });
186 |     })
187 |     .size();
188 |  
189 |   const didTransformImports = root
190 |     .find(j.ImportDeclaration, (node) => {
191 |       return node.source.type === 'Literal' && node.source.value.indexOf('actions') !== -1;
192 |     })
193 |     .forEach((nodePath) => {
194 |       nodePath.value.specifiers = nodePath.value.specifiers.map((specifier) => {
195 |         Iif (specifier.type !== 'ImportSpecifier') {
196 |           return specifier;
197 |         }
198 |  
199 |         Eif (specifier.imported.name === specifier.local.name) {
200 |           return j.importSpecifier(
201 |             j.identifier(specifier.imported.name),
202 |             j.identifier(`${specifier.imported.name}Action`)
203 |           );
204 |         }
205 |  
206 |         return specifier;
207 |       });
208 |     })
209 |     .size();
210 |  
211 |   return didTransformImports || didTransformObjExpression ? root.toSource(printOptions) : null;
212 | };
213 |  
214 | 215 |
216 |
217 | 222 | 223 | 224 | 229 | 230 | 231 | 232 | 233 | -------------------------------------------------------------------------------- /coverage/lcov-report/sort-arrow-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anshckr/fix-js/eeadc0f150501f4aecfb3ee9bd76a76e32da7c42/coverage/lcov-report/sort-arrow-sprite.png -------------------------------------------------------------------------------- /coverage/lcov-report/sorter.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | var addSorting = (function() { 3 | 'use strict'; 4 | var cols, 5 | currentSort = { 6 | index: 0, 7 | desc: false 8 | }; 9 | 10 | // returns the summary table element 11 | function getTable() { 12 | return document.querySelector('.coverage-summary'); 13 | } 14 | // returns the thead element of the summary table 15 | function getTableHeader() { 16 | return getTable().querySelector('thead tr'); 17 | } 18 | // returns the tbody element of the summary table 19 | function getTableBody() { 20 | return getTable().querySelector('tbody'); 21 | } 22 | // returns the th element for nth column 23 | function getNthColumn(n) { 24 | return getTableHeader().querySelectorAll('th')[n]; 25 | } 26 | 27 | // loads all columns 28 | function loadColumns() { 29 | var colNodes = getTableHeader().querySelectorAll('th'), 30 | colNode, 31 | cols = [], 32 | col, 33 | i; 34 | 35 | for (i = 0; i < colNodes.length; i += 1) { 36 | colNode = colNodes[i]; 37 | col = { 38 | key: colNode.getAttribute('data-col'), 39 | sortable: !colNode.getAttribute('data-nosort'), 40 | type: colNode.getAttribute('data-type') || 'string' 41 | }; 42 | cols.push(col); 43 | if (col.sortable) { 44 | col.defaultDescSort = col.type === 'number'; 45 | colNode.innerHTML = 46 | colNode.innerHTML + ''; 47 | } 48 | } 49 | return cols; 50 | } 51 | // attaches a data attribute to every tr element with an object 52 | // of data values keyed by column name 53 | function loadRowData(tableRow) { 54 | var tableCols = tableRow.querySelectorAll('td'), 55 | colNode, 56 | col, 57 | data = {}, 58 | i, 59 | val; 60 | for (i = 0; i < tableCols.length; i += 1) { 61 | colNode = tableCols[i]; 62 | col = cols[i]; 63 | val = colNode.getAttribute('data-value'); 64 | if (col.type === 'number') { 65 | val = Number(val); 66 | } 67 | data[col.key] = val; 68 | } 69 | return data; 70 | } 71 | // loads all row data 72 | function loadData() { 73 | var rows = getTableBody().querySelectorAll('tr'), 74 | i; 75 | 76 | for (i = 0; i < rows.length; i += 1) { 77 | rows[i].data = loadRowData(rows[i]); 78 | } 79 | } 80 | // sorts the table using the data for the ith column 81 | function sortByIndex(index, desc) { 82 | var key = cols[index].key, 83 | sorter = function(a, b) { 84 | a = a.data[key]; 85 | b = b.data[key]; 86 | return a < b ? -1 : a > b ? 1 : 0; 87 | }, 88 | finalSorter = sorter, 89 | tableBody = document.querySelector('.coverage-summary tbody'), 90 | rowNodes = tableBody.querySelectorAll('tr'), 91 | rows = [], 92 | i; 93 | 94 | if (desc) { 95 | finalSorter = function(a, b) { 96 | return -1 * sorter(a, b); 97 | }; 98 | } 99 | 100 | for (i = 0; i < rowNodes.length; i += 1) { 101 | rows.push(rowNodes[i]); 102 | tableBody.removeChild(rowNodes[i]); 103 | } 104 | 105 | rows.sort(finalSorter); 106 | 107 | for (i = 0; i < rows.length; i += 1) { 108 | tableBody.appendChild(rows[i]); 109 | } 110 | } 111 | // removes sort indicators for current column being sorted 112 | function removeSortIndicators() { 113 | var col = getNthColumn(currentSort.index), 114 | cls = col.className; 115 | 116 | cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); 117 | col.className = cls; 118 | } 119 | // adds sort indicators for current column being sorted 120 | function addSortIndicators() { 121 | getNthColumn(currentSort.index).className += currentSort.desc 122 | ? ' sorted-desc' 123 | : ' sorted'; 124 | } 125 | // adds event listeners for all sorter widgets 126 | function enableUI() { 127 | var i, 128 | el, 129 | ithSorter = function ithSorter(i) { 130 | var col = cols[i]; 131 | 132 | return function() { 133 | var desc = col.defaultDescSort; 134 | 135 | if (currentSort.index === i) { 136 | desc = !currentSort.desc; 137 | } 138 | sortByIndex(i, desc); 139 | removeSortIndicators(); 140 | currentSort.index = i; 141 | currentSort.desc = desc; 142 | addSortIndicators(); 143 | }; 144 | }; 145 | for (i = 0; i < cols.length; i += 1) { 146 | if (cols[i].sortable) { 147 | // add the click event handler on the th so users 148 | // dont have to click on those tiny arrows 149 | el = getNthColumn(i).querySelector('.sorter').parentElement; 150 | if (el.addEventListener) { 151 | el.addEventListener('click', ithSorter(i)); 152 | } else { 153 | el.attachEvent('onclick', ithSorter(i)); 154 | } 155 | } 156 | } 157 | } 158 | // adds sorting functionality to the UI 159 | return function() { 160 | if (!getTable()) { 161 | return; 162 | } 163 | cols = loadColumns(); 164 | loadData(); 165 | addSortIndicators(); 166 | enableUI(); 167 | }; 168 | })(); 169 | 170 | window.addEventListener('load', addSorting); 171 | -------------------------------------------------------------------------------- /coverage/lcov.info: -------------------------------------------------------------------------------- 1 | TN: 2 | SF:transforms/no-lonely-if.js 3 | FN:1,(anonymous_0) 4 | FN:11,(anonymous_1) 5 | FN:26,(anonymous_2) 6 | FN:31,(anonymous_3) 7 | FN:35,(anonymous_4) 8 | FNF:5 9 | FNH:5 10 | FNDA:1,(anonymous_0) 11 | FNDA:2,(anonymous_1) 12 | FNDA:2,(anonymous_2) 13 | FNDA:1,(anonymous_3) 14 | FNDA:1,(anonymous_4) 15 | DA:1,1 16 | DA:2,1 17 | DA:4,1 18 | DA:5,1 19 | DA:9,1 20 | DA:12,2 21 | DA:14,2 22 | DA:15,2 23 | DA:17,2 24 | DA:24,0 25 | DA:27,2 26 | DA:29,2 27 | DA:31,2 28 | DA:32,1 29 | DA:35,2 30 | DA:36,1 31 | DA:41,1 32 | LF:17 33 | LH:16 34 | BRDA:4,0,0,1 35 | BRDA:4,0,1,1 36 | BRDA:14,1,0,2 37 | BRDA:14,1,1,0 38 | BRDA:18,2,0,2 39 | BRDA:18,2,1,2 40 | BRDA:18,2,2,2 41 | BRDA:32,3,0,1 42 | BRDA:32,3,1,1 43 | BRDA:41,4,0,1 44 | BRDA:41,4,1,0 45 | BRF:11 46 | BRH:9 47 | end_of_record 48 | TN: 49 | SF:transforms/no-nested-ternary.js 50 | FN:1,(anonymous_0) 51 | FN:9,(anonymous_1) 52 | FN:27,(anonymous_2) 53 | FN:37,(anonymous_3) 54 | FN:45,(anonymous_4) 55 | FN:50,(anonymous_5) 56 | FNF:6 57 | FNH:6 58 | FNDA:1,(anonymous_0) 59 | FNDA:4,(anonymous_1) 60 | FNDA:2,(anonymous_2) 61 | FNDA:1,(anonymous_3) 62 | FNDA:2,(anonymous_4) 63 | FNDA:1,(anonymous_5) 64 | DA:1,1 65 | DA:2,1 66 | DA:4,1 67 | DA:5,1 68 | DA:9,1 69 | DA:10,4 70 | DA:12,4 71 | DA:13,1 72 | DA:16,3 73 | DA:17,0 74 | DA:21,3 75 | DA:24,4 76 | DA:27,1 77 | DA:28,2 78 | DA:34,2 79 | DA:37,1 80 | DA:38,1 81 | DA:40,1 82 | DA:42,1 83 | DA:45,1 84 | DA:46,2 85 | DA:49,1 86 | DA:51,1 87 | DA:55,1 88 | LF:24 89 | LH:23 90 | BRDA:4,0,0,1 91 | BRDA:4,0,1,1 92 | BRDA:9,1,0,0 93 | BRDA:12,2,0,1 94 | BRDA:12,2,1,3 95 | BRDA:16,3,0,0 96 | BRDA:16,3,1,3 97 | BRDA:27,4,0,1 98 | BRDA:46,5,0,2 99 | BRDA:46,5,1,2 100 | BRDA:55,6,0,1 101 | BRDA:55,6,1,0 102 | BRF:12 103 | BRH:9 104 | end_of_record 105 | TN: 106 | SF:transforms/no-unused-vars.js 107 | FN:1,(anonymous_0) 108 | FN:9,(anonymous_1) 109 | FN:10,(anonymous_2) 110 | FN:21,(anonymous_3) 111 | FN:22,(anonymous_4) 112 | FN:33,(anonymous_5) 113 | FN:36,(anonymous_6) 114 | FN:47,(anonymous_7) 115 | FN:58,(anonymous_8) 116 | FN:59,(anonymous_9) 117 | FN:76,(anonymous_10) 118 | FN:83,(anonymous_11) 119 | FNF:12 120 | FNH:1 121 | FNDA:1,(anonymous_0) 122 | FNDA:0,(anonymous_1) 123 | FNDA:0,(anonymous_2) 124 | FNDA:0,(anonymous_3) 125 | FNDA:0,(anonymous_4) 126 | FNDA:0,(anonymous_5) 127 | FNDA:0,(anonymous_6) 128 | FNDA:0,(anonymous_7) 129 | FNDA:0,(anonymous_8) 130 | FNDA:0,(anonymous_9) 131 | FNDA:0,(anonymous_10) 132 | FNDA:0,(anonymous_11) 133 | DA:1,1 134 | DA:2,1 135 | DA:4,1 136 | DA:5,1 137 | DA:9,1 138 | DA:10,0 139 | DA:11,0 140 | DA:12,0 141 | DA:15,0 142 | DA:18,0 143 | DA:21,1 144 | DA:22,0 145 | DA:23,0 146 | DA:24,0 147 | DA:27,0 148 | DA:30,0 149 | DA:33,1 150 | DA:34,0 151 | DA:36,0 152 | DA:37,0 153 | DA:39,0 154 | DA:40,0 155 | DA:44,0 156 | DA:47,1 157 | DA:48,0 158 | DA:50,0 159 | DA:51,0 160 | DA:53,0 161 | DA:56,0 162 | DA:58,0 163 | DA:59,0 164 | DA:60,0 165 | DA:61,0 166 | DA:64,0 167 | DA:67,0 168 | DA:69,0 169 | DA:74,1 170 | DA:77,0 171 | DA:81,1 172 | DA:84,0 173 | DA:88,1 174 | LF:41 175 | LH:11 176 | BRDA:4,0,0,1 177 | BRDA:4,0,1,1 178 | BRDA:11,1,0,0 179 | BRDA:11,1,1,0 180 | BRDA:23,2,0,0 181 | BRDA:23,2,1,0 182 | BRDA:39,3,0,0 183 | BRDA:39,3,1,0 184 | BRDA:50,4,0,0 185 | BRDA:50,4,1,0 186 | BRDA:60,5,0,0 187 | BRDA:60,5,1,0 188 | BRDA:60,6,0,0 189 | BRDA:60,6,1,0 190 | BRDA:67,7,0,0 191 | BRDA:67,7,1,0 192 | BRDA:88,8,0,0 193 | BRDA:88,8,1,1 194 | BRDA:88,9,0,1 195 | BRDA:88,9,1,1 196 | BRF:20 197 | BRH:5 198 | end_of_record 199 | TN: 200 | SF:transforms/react-action-as.js 201 | FN:1,(anonymous_0) 202 | FN:10,(anonymous_1) 203 | FN:13,(anonymous_2) 204 | FN:14,(anonymous_3) 205 | FN:18,(anonymous_4) 206 | FN:29,(anonymous_5) 207 | FN:32,(anonymous_6) 208 | FN:33,(anonymous_7) 209 | FNF:8 210 | FNH:8 211 | FNDA:1,(anonymous_0) 212 | FNDA:1,(anonymous_1) 213 | FNDA:1,(anonymous_2) 214 | FNDA:1,(anonymous_3) 215 | FNDA:1,(anonymous_4) 216 | FNDA:1,(anonymous_5) 217 | FNDA:1,(anonymous_6) 218 | FNDA:1,(anonymous_7) 219 | DA:1,1 220 | DA:2,1 221 | DA:4,1 222 | DA:5,1 223 | DA:9,1 224 | DA:11,1 225 | DA:14,1 226 | DA:15,1 227 | DA:18,1 228 | DA:19,1 229 | DA:20,1 230 | DA:23,0 231 | DA:28,1 232 | DA:30,1 233 | DA:33,1 234 | DA:34,1 235 | DA:35,0 236 | DA:38,1 237 | DA:39,1 238 | DA:45,0 239 | DA:50,1 240 | LF:21 241 | LH:18 242 | BRDA:4,0,0,1 243 | BRDA:4,0,1,1 244 | BRDA:19,1,0,1 245 | BRDA:19,1,1,0 246 | BRDA:30,2,0,1 247 | BRDA:30,2,1,1 248 | BRDA:34,3,0,0 249 | BRDA:34,3,1,1 250 | BRDA:38,4,0,1 251 | BRDA:38,4,1,0 252 | BRDA:50,5,0,1 253 | BRDA:50,5,1,0 254 | BRDA:50,6,0,1 255 | BRDA:50,6,1,0 256 | BRF:14 257 | BRH:9 258 | end_of_record 259 | TN: 260 | SF:transforms/react-destruct-assign.js 261 | FN:3,(anonymous_0) 262 | FN:11,(anonymous_1) 263 | FN:13,(anonymous_2) 264 | FN:15,(anonymous_3) 265 | FN:18,(anonymous_4) 266 | FN:24,(anonymous_5) 267 | FN:29,(anonymous_6) 268 | FN:36,(anonymous_7) 269 | FN:46,(anonymous_8) 270 | FN:50,(anonymous_9) 271 | FN:58,(anonymous_10) 272 | FN:62,(anonymous_11) 273 | FN:76,(anonymous_12) 274 | FN:80,(anonymous_13) 275 | FN:88,(anonymous_14) 276 | FN:102,(anonymous_15) 277 | FN:112,(anonymous_16) 278 | FN:133,(anonymous_17) 279 | FN:134,(anonymous_18) 280 | FN:138,(anonymous_19) 281 | FN:139,(anonymous_20) 282 | FN:147,(anonymous_21) 283 | FN:165,(anonymous_22) 284 | FN:173,(anonymous_23) 285 | FNF:24 286 | FNH:18 287 | FNDA:1,(anonymous_0) 288 | FNDA:1,(anonymous_1) 289 | FNDA:2,(anonymous_2) 290 | FNDA:10,(anonymous_3) 291 | FNDA:3,(anonymous_4) 292 | FNDA:3,(anonymous_5) 293 | FNDA:2,(anonymous_6) 294 | FNDA:3,(anonymous_7) 295 | FNDA:2,(anonymous_8) 296 | FNDA:3,(anonymous_9) 297 | FNDA:0,(anonymous_10) 298 | FNDA:0,(anonymous_11) 299 | FNDA:0,(anonymous_12) 300 | FNDA:0,(anonymous_13) 301 | FNDA:0,(anonymous_14) 302 | FNDA:0,(anonymous_15) 303 | FNDA:3,(anonymous_16) 304 | FNDA:2,(anonymous_17) 305 | FNDA:1,(anonymous_18) 306 | FNDA:1,(anonymous_19) 307 | FNDA:2,(anonymous_20) 308 | FNDA:2,(anonymous_21) 309 | FNDA:2,(anonymous_22) 310 | FNDA:1,(anonymous_23) 311 | DA:1,1 312 | DA:3,1 313 | DA:4,1 314 | DA:6,1 315 | DA:7,1 316 | DA:11,1 317 | DA:13,1 318 | DA:14,2 319 | DA:16,10 320 | DA:19,3 321 | DA:23,2 322 | DA:24,3 323 | DA:27,2 324 | DA:29,2 325 | DA:30,2 326 | DA:32,2 327 | DA:34,2 328 | DA:36,2 329 | DA:37,3 330 | DA:40,2 331 | DA:42,2 332 | DA:44,2 333 | DA:46,2 334 | DA:48,2 335 | DA:50,2 336 | DA:51,3 337 | DA:53,3 338 | DA:56,2 339 | DA:58,2 340 | DA:59,0 341 | DA:62,2 342 | DA:63,0 343 | DA:71,2 344 | DA:72,0 345 | DA:74,0 346 | DA:76,0 347 | DA:77,0 348 | DA:80,0 349 | DA:81,0 350 | DA:84,0 351 | DA:85,0 352 | DA:88,0 353 | DA:89,0 354 | DA:92,0 355 | DA:95,0 356 | DA:97,0 357 | DA:99,0 358 | DA:102,0 359 | DA:103,0 360 | DA:106,0 361 | DA:108,2 362 | DA:109,0 363 | DA:112,2 364 | DA:113,3 365 | DA:116,2 366 | DA:130,1 367 | DA:132,1 368 | DA:134,2 369 | DA:135,1 370 | DA:139,1 371 | DA:140,2 372 | DA:143,1 373 | DA:145,1 374 | DA:147,1 375 | DA:148,2 376 | DA:149,2 377 | DA:151,2 378 | DA:153,2 379 | DA:154,1 380 | DA:156,1 381 | DA:159,2 382 | DA:162,1 383 | DA:164,1 384 | DA:165,1 385 | DA:166,2 386 | DA:167,1 387 | DA:170,1 388 | DA:173,1 389 | DA:174,1 390 | DA:175,1 391 | DA:178,0 392 | DA:183,1 393 | LF:82 394 | LH:61 395 | BRDA:6,0,0,1 396 | BRDA:6,0,1,1 397 | BRDA:16,1,0,10 398 | BRDA:16,1,1,5 399 | BRDA:64,2,0,0 400 | BRDA:64,2,1,0 401 | BRDA:64,2,2,0 402 | BRDA:64,2,3,0 403 | BRDA:71,3,0,0 404 | BRDA:71,3,1,2 405 | BRDA:84,4,0,0 406 | BRDA:84,4,1,0 407 | BRDA:97,5,0,0 408 | BRDA:97,5,1,0 409 | BRDA:108,6,0,0 410 | BRDA:108,6,1,2 411 | BRDA:153,7,0,1 412 | BRDA:153,7,1,1 413 | BRDA:164,8,0,1 414 | BRDA:164,8,1,0 415 | BRDA:166,9,0,1 416 | BRDA:166,9,1,1 417 | BRDA:174,10,0,1 418 | BRDA:174,10,1,0 419 | BRDA:183,11,0,1 420 | BRDA:183,11,1,0 421 | BRDA:183,12,0,1 422 | BRDA:183,12,1,0 423 | BRF:28 424 | BRH:14 425 | end_of_record 426 | -------------------------------------------------------------------------------- /example/asPackage.js: -------------------------------------------------------------------------------- 1 | // Example of how to use it as a package 2 | 3 | const { 4 | fixJSsAtPath, 5 | transformLeakingGlobalsVars, 6 | transformUnusedAssignedVars, 7 | transformNoUnderscoreDangle 8 | } = require('../index'); 9 | const dependenciesObj = require('./dependencies.json'); 10 | 11 | // const directoryPath = '/Users/Anshul/railsApp/public/javascripts/'; 12 | const directoryPath = '/Users/Anshul/railsApp/app/assets/javascripts/'; 13 | // const directoryPath = '/Users/Anshul/railsApp/react/app/'; 14 | const ignoreFilesRegex = /^socket|\.min\.js/; 15 | const ignoreFoldersRegex = /\/libraries|google-code-prettify|polyfill|prettify|run_prettify/; 16 | 17 | const ignoreableExternalDeps = Object.keys(dependenciesObj).reduce( 18 | (accumulator, key) => accumulator.concat(dependenciesObj[key]), 19 | [] 20 | ); 21 | 22 | /** 23 | * { Example usage of fixJSsAtPath } 24 | */ 25 | // with minimal required params 26 | // fixJSsAtPath(directoryPath, transformLeakingGlobalsVars); 27 | // with all params 28 | // fixJSsAtPath(directoryPath, transformLeakingGlobalsVars, ignoreFilesRegex, ignoreFoldersRegex, ignoreableExternalDeps); 29 | // fixJSsAtPath(directoryPath, transformUnusedAssignedVars, ignoreFilesRegex, ignoreFoldersRegex, ignoreableExternalDeps); 30 | // fixJSsAtPath(directoryPath, transformNoUnderscoreDangle, ignoreFilesRegex, ignoreFoldersRegex, ignoreableExternalDeps); 31 | 32 | // /** 33 | // * { Example usage of transformLeakingGlobalsVars } 34 | // */ 35 | // const dependencies = ['jQuery']; 36 | 37 | // // with specific dependencies to fix 38 | // transformLeakingGlobalsVars('/Users/Anshul/railsApp/app/assets/javascripts/admin.js', dependencies); 39 | // // will update the file instead of returning the modified contents 40 | // transformLeakingGlobalsVars('/Users/Anshul/railsApp/app/assets/javascripts/admin.js', dependencies, true); 41 | // // without dependencies, will detect all the globals in the file and fix them 42 | // transformLeakingGlobalsVars('/Users/Anshul/railsApp/app/assets/javascripts/admin.js'); 43 | 44 | // /** 45 | // * { Example usage of transformUnusedAssignedVars } 46 | // */ 47 | 48 | // with specific dependencies to fix 49 | // // will update the file instead of returning the modified contents 50 | // transformUnusedAssignedVars('/Users/Anshul/railsApp/app/assets/javascripts/admin.js', true); 51 | // // will return the the modified contents file instead of directly fixing 52 | // transformUnusedAssignedVars('/Users/Anshul/railsApp/app/assets/javascripts/admin.js'); 53 | 54 | // /** 55 | // * { Example usage of transformNoUnderscoreDangle } 56 | // */ 57 | 58 | // // will update the file instead of returning the modified contents 59 | // transformNoUnderscoreDangle('/Users/Anshul/railsApp/app/assets/javascripts/static/report_bug/slack.js', true); 60 | // // will return the the modified contents file instead of directly fixing 61 | // transformNoUnderscoreDangle('/Users/Anshul/railsApp/app/assets/javascripts/admin.js'); 62 | -------------------------------------------------------------------------------- /example/dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "browser": [ 3 | "ActiveXObject", 4 | "RTCMultiConnection", 5 | "XDomainRequest", 6 | "chrome", 7 | "google", 8 | "grecaptcha", 9 | "importScripts", 10 | "mozRTCIceCandidate", 11 | "mozRTCPeerConnection", 12 | "mozRTCSessionDescription", 13 | "webkitMediaStream", 14 | "webkitRTCPeerConnection" 15 | ], 16 | "html": [ 17 | "__COUNTRIES", 18 | "__OS_NAME_CODE_MAPPING", 19 | "__REVERSE_OS_NAME_CODE_MAPPING", 20 | "_bsClientIp", 21 | "AdsConversionTracking", 22 | "amplitude_user_details", 23 | "AmplitudeAnalytics", 24 | "AppAutomateUserDetails", 25 | "auth_key", 26 | "auth_token", 27 | "BeamerConfig", 28 | "browserLimit", 29 | "BrowserStack", 30 | "BrowserStackConfig", 31 | "BrowserStackEnterprise", 32 | "bsGaDomain", 33 | "CheckoutUser", 34 | "chromeExtensionId", 35 | "CURRENT_USER", 36 | "eds_user_details", 37 | "EDSAppAutomateWebEventsThrottleThreshold", 38 | "EDSAppLiveTestSessionsThrottleThreshold", 39 | "EDSAppLiveWebEventsThrottleThreshold", 40 | "EDSCommonThrottleThreshold", 41 | "EdsConfig", 42 | "EDSFrontendPerformanceThreshold", 43 | "EDSLiveTestSessionsThrottleThreshold", 44 | "EDSLiveWebEventsThrottleThreshold", 45 | "EDSWebEventsPiiThrottleThreshold", 46 | "EDSWebEventsThrottleThreshold", 47 | "email_address", 48 | "existingCaps", 49 | "existingRows", 50 | "Experiments", 51 | "gauth_form", 52 | "iAmSubGroupUser", 53 | "landing_page_check_email", 54 | "ManageUsersBrowserStack", 55 | "NpsConfig", 56 | "page_anchor", 57 | "plandetail25plus", 58 | "preUploadedAppsHashID", 59 | "quickLaunchChromeExtensionId", 60 | "RefundData", 61 | "selected_tag", 62 | "stripeGlobalObject", 63 | "SubscriptionUser", 64 | "teamViewActivated", 65 | "triggerPop", 66 | "user_referral_reward", 67 | "workable_url" 68 | ], 69 | "ignore": [ 70 | "webrtc", 71 | "bodyDropzone", 72 | "__toggleSuggestToolForm", 73 | "PassExtensionDetails", 74 | "changeReportBugName", 75 | "Cookie", 76 | "BrowserDetect", 77 | "customTimestamp", 78 | "LocalStorage", 79 | "flashBlockDetect", 80 | "Drawing", 81 | "videojs", 82 | "bsFeedback" 83 | ], 84 | "libraries": [ 85 | "$", 86 | "jQuery", 87 | "__e", 88 | "__g", 89 | "_vis_opt_goal_conversion", 90 | "amplitude", 91 | "AppendableWidget", 92 | "Chart", 93 | "Clipboard", 94 | "define", 95 | "delighted", 96 | "Dexie", 97 | "Dropzone", 98 | "EditableWidget", 99 | "fabric", 100 | "ga", 101 | "gapi", 102 | "Handlebars", 103 | "initFreshChat", 104 | "InstallTrigger", 105 | "io", 106 | "io120", 107 | "io201", 108 | "localTurn", 109 | "Mustache", 110 | "parseUri", 111 | "PerformanceWatcherBrowser", 112 | "PR", 113 | "QUOTA_EXCEEDED_ERR", 114 | "Raven", 115 | "Reactor", 116 | "reactWant", 117 | "ReplaceableWidget", 118 | "Sentry", 119 | "Stripe", 120 | "svgeezy", 121 | "tinycolor", 122 | "turnTunnel", 123 | "WebVTT", 124 | "Widgets" 125 | ] 126 | } -------------------------------------------------------------------------------- /example/withJSCodeshift.js: -------------------------------------------------------------------------------- 1 | // Example of how to use it with jscodeshift 2 | 3 | // jscodeshift -t ./transforms/no-lonely-if.js /Users/Anshul/railsApp/app/assets/javascripts --ignore-config=./.transformignore 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { resolve, extname } = require('path'); 3 | const acorn = require('acorn'); 4 | const findGlobals = require('acorn-globals'); 5 | 6 | // In newer Node.js versions where process is already global this isn't necessary. 7 | const process = require('process'); 8 | 9 | // utils 10 | const findGlobalsExposed = require('./utils/find-globals-exposed'); 11 | 12 | // global objects 13 | const constants = require('./static/constants.json'); 14 | 15 | // transformers 16 | const transformLeakingGlobalsVars = require('./transforms/with-globals/leaking-global-vars'); 17 | const transformUnusedAssignedVars = require('./transforms/with-globals/unused-assigned-vars'); 18 | const transformNoUnderscoreDangle = require('./transforms/with-globals/no-underscore-dangle'); 19 | 20 | /* will be ignored in dependencies -- start */ 21 | 22 | const allExternalDeps = Object.keys(constants).reduce((accumulator, key) => accumulator.concat(constants[key]), []); 23 | 24 | let ignoreableExternalDeps = []; 25 | 26 | let ignoreFilesRegex; 27 | let ignoreFoldersRegex; 28 | 29 | /* will be ignored in dependencies -- end */ 30 | 31 | let allGlobalDeps = []; 32 | 33 | let allGlobalsExposed = []; 34 | 35 | let fixOnlyDependencies = false; 36 | 37 | function recursiveDirFilesIterator(dirPath, cb) { 38 | const files = fs.readdirSync(resolve(__dirname, dirPath), { withFileTypes: true }); 39 | 40 | files.forEach((file) => { 41 | const filePath = resolve(dirPath, file.name); 42 | 43 | if (file.isFile()) { 44 | if (ignoreFilesRegex.test(file.name) || !['.js', '.jsx'].includes(extname(file.name))) { 45 | console.log("Skipping file: '%s'", filePath); 46 | } else { 47 | cb(filePath); 48 | } 49 | } else if (file.isDirectory()) { 50 | if (!ignoreFoldersRegex.test(filePath)) { 51 | recursiveDirFilesIterator(filePath, cb); 52 | } else { 53 | console.log("Skipping directory: '%s'", filePath); 54 | } 55 | } 56 | }); 57 | } 58 | 59 | function fillAllGlobalsConstants(filePath) { 60 | const source = fs.readFileSync(resolve(__dirname, filePath), { encoding: 'utf8' }); 61 | 62 | const ast = acorn.parse(source, { 63 | loc: true 64 | }); 65 | 66 | const globalsExposed = Object.keys(findGlobalsExposed(ast)); 67 | 68 | const dependencies = findGlobals(ast) 69 | .filter((dep) => allExternalDeps.indexOf(dep.name) === -1) 70 | .filter((dep) => ignoreableExternalDeps.indexOf(dep.name) === -1); 71 | 72 | const depNames = dependencies.map(({ name }) => name); 73 | 74 | // set allGlobalsExposed && allGlobalDeps in first iteration 75 | allGlobalsExposed = allGlobalsExposed.concat(globalsExposed); 76 | allGlobalDeps = allGlobalDeps.concat(depNames); 77 | } 78 | 79 | function executeTransformer(filePath) { 80 | let results; 81 | 82 | const source = fs.readFileSync(resolve(__dirname, filePath), { encoding: 'utf8' }); 83 | 84 | const passCollectedGlobals = ['transformNoUnderscoreDangle'].includes(this.name); 85 | 86 | if (passCollectedGlobals) { 87 | const ast = acorn.parse(source, { 88 | loc: true 89 | }); 90 | 91 | const globalsExposed = Object.keys(findGlobalsExposed(ast)); 92 | 93 | let dependencies = findGlobals(ast) 94 | .filter((dep) => allExternalDeps.indexOf(dep.name) === -1) 95 | .filter((dep) => ignoreableExternalDeps.indexOf(dep.name) === -1); 96 | 97 | if (fixOnlyDependencies) { 98 | dependencies = [...new Set(dependencies.filter((e) => allGlobalsExposed.indexOf(e.name) === -1))]; 99 | 100 | results = this(filePath, dependencies); 101 | } else { 102 | dependencies = [...new Set(dependencies)]; 103 | 104 | results = this(filePath, false, { 105 | globalsExposed, 106 | dependencies 107 | }); 108 | } 109 | } else { 110 | results = this(filePath); 111 | } 112 | 113 | if (results) { 114 | fs.writeFileSync(resolve(__dirname, filePath), results.replace(/;;/g, ';')); 115 | } 116 | } 117 | 118 | function collectAllGlobals(dirPath) { 119 | return new Promise((res, rej) => { 120 | try { 121 | recursiveDirFilesIterator(dirPath, fillAllGlobalsConstants); 122 | 123 | allGlobalDeps = [...new Set(allGlobalDeps)]; 124 | allGlobalsExposed = [...new Set(allGlobalsExposed)]; 125 | 126 | res({ 127 | allGlobalDeps: [...new Set(allGlobalDeps)], 128 | allGlobalsExposed: [...new Set(allGlobalsExposed)] 129 | }); 130 | } catch (err) { 131 | rej(err); 132 | } 133 | }); 134 | } 135 | 136 | /** 137 | * { fixJSsAtPath: Transforms all the JS files at the dirPath } 138 | * 139 | * @param {} dirPath The directory where you want to run the transform at 140 | * @param {} transformer The transformer which will modify the JS files 141 | * @param {} [paramsIgnoreFilesRegex=/$^/] Regular expression to match filenames 142 | * to ignore during transform 143 | * @param {} [paramsIgnoreFoldersRegex=/$^/] Regular expression to match folder names 144 | * to ignore during transform 145 | * @param {} [paramsIgnoreableExternalDeps=[]] Array of dependencies to ignore during transform 146 | */ 147 | function fixJSsAtPath( 148 | dirPath, 149 | transformer, 150 | paramsIgnoreFilesRegex = /$^/, 151 | paramsIgnoreFoldersRegex = /$^/, 152 | paramsIgnoreableExternalDeps = [] 153 | ) { 154 | try { 155 | if (dirPath.constructor !== String) { 156 | throw new Error('dirPath should be a String'); 157 | } 158 | 159 | if (transformer.constructor !== Function) { 160 | throw new Error('transformer should be a Function'); 161 | } 162 | 163 | if (paramsIgnoreFilesRegex.constructor !== RegExp) { 164 | throw new Error('paramsIgnoreFilesRegex should be a RegExp'); 165 | } 166 | 167 | if (paramsIgnoreFoldersRegex.constructor !== RegExp) { 168 | throw new Error('paramsIgnoreFoldersRegex should be a RegExp'); 169 | } 170 | 171 | if (paramsIgnoreableExternalDeps.constructor !== Array) { 172 | throw new Error('paramsIgnoreableExternalDeps should be an Array'); 173 | } 174 | 175 | ignoreFilesRegex = paramsIgnoreFilesRegex; 176 | ignoreFoldersRegex = paramsIgnoreFoldersRegex; 177 | ignoreableExternalDeps = ignoreableExternalDeps.concat(paramsIgnoreableExternalDeps); 178 | 179 | console.log("Executing Transformer: '%s'", transformer.name); 180 | 181 | fixOnlyDependencies = ['transformLeakingGlobalsVars', 'transformUnusedAssignedVars'].includes(transformer.name); 182 | 183 | if (fixOnlyDependencies) { 184 | collectAllGlobals(dirPath) 185 | .then(() => { 186 | recursiveDirFilesIterator(dirPath, executeTransformer.bind(transformer)); 187 | }) 188 | .catch((err) => { 189 | // An error occurred 190 | console.error('Some Error Occured: ', err); 191 | process.exit(1); 192 | }); 193 | } else { 194 | recursiveDirFilesIterator(dirPath, executeTransformer.bind(transformer)); 195 | } 196 | } catch (err) { 197 | console.log(err); 198 | } 199 | } 200 | 201 | module.exports = { 202 | fixJSsAtPath, 203 | transformLeakingGlobalsVars, 204 | transformUnusedAssignedVars, 205 | transformNoUnderscoreDangle 206 | }; 207 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@anshckr/fix-js", 3 | "version": "1.6.4", 4 | "description": "Fix JS code", 5 | "main": "index.js", 6 | "scripts": { 7 | "coverage": "jest --coverage", 8 | "asPackage:debug": "nodemon --inspect-brk example/asPackage.js", 9 | "asPackage": "node example/asPackage.js", 10 | "lint:check": "eslint --format=table --max-warnings 0 \"**/*.js\"", 11 | "lint:fix": "npm run lint:check -- --fix", 12 | "prettier:check": "prettier --check \"**/*.js\"", 13 | "prettier:fix": "npm run prettier:check -- --write", 14 | "test": "f() { EXIT=0; npm run lint:fix || EXIT=$?; jest $@ || EXIT=$?; exit $EXIT; }; f" 15 | }, 16 | "keywords": [ 17 | "acorn", 18 | "camelCase", 19 | "cleanup", 20 | "codemod", 21 | "detect", 22 | "eslint rules", 23 | "fix", 24 | "global leaks", 25 | "import actions as", 26 | "javascripts", 27 | "JS", 28 | "jscodeshift", 29 | "react", 30 | "react/destructuring-assignment", 31 | "react-action-as", 32 | "unused assigned variables", 33 | "no-camelcase", 34 | "no-lonely-if", 35 | "block-scoped-var", 36 | "no-nested-ternary", 37 | "no-unused-vars", 38 | "block-scoped-var", 39 | "no-underscore-dangle" 40 | ], 41 | "author": "Anshul Nema", 42 | "license": "MIT", 43 | "dependencies": { 44 | "acorn": "7.1.1", 45 | "acorn-globals": "6.0.0", 46 | "acorn-walk": "7.1.1", 47 | "jscodeshift": "0.7.0", 48 | "lodash": "4.17.19" 49 | }, 50 | "devDependencies": { 51 | "eslint": "6.8.0", 52 | "eslint-config-airbnb-base": "14.1.0", 53 | "eslint-config-prettier": "6.10.1", 54 | "eslint-plugin-import": "2.20.2", 55 | "eslint-plugin-prettier": "3.1.2", 56 | "jest": "^25.3.0", 57 | "prettier": "2.0.2" 58 | }, 59 | "repository": { 60 | "type": "git", 61 | "url": "git+https://github.com/anshckr/fix-js.git" 62 | }, 63 | "bugs": { 64 | "url": "https://github.com/anshckr/fix-js/issues" 65 | }, 66 | "homepage": "https://github.com/anshckr/fix-js#readme", 67 | "jest": { 68 | "roots": [ 69 | "transforms/__tests__" 70 | ], 71 | "coverageThreshold": { 72 | "global": { 73 | "branches": 54, 74 | "functions": 69, 75 | "lines": 69, 76 | "statements": 69 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/block-scoped-vars.input.js: -------------------------------------------------------------------------------- 1 | function someFunc() { 2 | if (true) { 3 | var i = 1; 4 | } else { 5 | var i = 2; 6 | } 7 | 8 | for (var j = 0; j < i; j++) { 9 | } 10 | 11 | for (var k in someObj) { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/block-scoped-vars.output.js: -------------------------------------------------------------------------------- 1 | function someFunc() { 2 | var i, j, k; 3 | if (true) { 4 | i = 1; 5 | } else { 6 | i = 2; 7 | } 8 | 9 | for (j = 0; j < i; j++) { 10 | } 11 | 12 | for (k in someObj) { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-camelcase-fix-dependencies.input.js: -------------------------------------------------------------------------------- 1 | var _some_var, $some_var; 2 | function some_func() {} 3 | some_func(some_dependency); 4 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-camelcase-fix-dependencies.output.js: -------------------------------------------------------------------------------- 1 | var someVar, $someVar; 2 | function some_func() {} 3 | some_func(someDependency); 4 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-camelcase-fix-exposed-functions.input.js: -------------------------------------------------------------------------------- 1 | var _some_var, $some_var; 2 | function some_func() {} 3 | some_func(); 4 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-camelcase-fix-exposed-functions.output.js: -------------------------------------------------------------------------------- 1 | var someVar, $someVar; 2 | function someFunc() {} 3 | someFunc(); 4 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-camelcase.input.js: -------------------------------------------------------------------------------- 1 | var _some_var, $some_var; 2 | function some_func() {} 3 | some_func(); 4 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-camelcase.output.js: -------------------------------------------------------------------------------- 1 | var someVar, $someVar; 2 | function some_func() {} 3 | some_func(); 4 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-lonely-if.input.js: -------------------------------------------------------------------------------- 1 | function someFunc() { 2 | if (true) { 3 | } else { 4 | if (someCondition) { 5 | } else { 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-lonely-if.output.js: -------------------------------------------------------------------------------- 1 | function someFunc() { 2 | if (true) { 3 | } else if (someCondition) { 4 | } else { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-nested-ternary.input.js: -------------------------------------------------------------------------------- 1 | const os = file.name.match(/\.(apk|aab)$/) ? 'android' : file.name.match(/.ipa$/) ? 'ios' : null; 2 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-nested-ternary.output.js: -------------------------------------------------------------------------------- 1 | const os = function() { 2 | if (file.name.match(/\.(apk|aab)$/)) { 3 | return 'android'; 4 | } else { 5 | if (file.name.match(/.ipa$/)) { 6 | return 'ios'; 7 | } else { 8 | return null; 9 | } 10 | } 11 | }(); 12 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-unused-vars-skip-disable-comments.input.js: -------------------------------------------------------------------------------- 1 | function someFunc(index) {} 2 | var someUsedVar1 = 0, someUnUsedVar = 2, someUnUsedVar1 = false; 3 | var someVar = (function(){ 4 | var someInternalVar; 5 | 6 | function someInternalFunc() {}; 7 | 8 | someUsedVar1 = 1; 9 | return someUsedVar1 || someUsedVar3; 10 | })(); 11 | 12 | var someUsedVar3 = 0; 13 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-unused-vars-skip-disable-comments.output.js: -------------------------------------------------------------------------------- 1 | function someFunc() {} 2 | var someUsedVar1 = 0; 3 | var someUnUsedVar = 2, someUnUsedVar1 = false; 4 | 5 | window.someVar = (function(){ 6 | someUsedVar1 = 1; 7 | return someUsedVar1 || someUsedVar3; 8 | })(); 9 | 10 | var someUsedVar3 = 0; 11 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-unused-vars.input.js: -------------------------------------------------------------------------------- 1 | function someFunc(index) {} 2 | var someUsedVar1 = 0, someUnUsedVar = 2, someUnUsedVar1 = false; 3 | var someVar = (function(){ 4 | var someInternalVar; 5 | 6 | function someInternalFunc() {}; 7 | 8 | someUsedVar1 = 1; 9 | return someUsedVar1 || someUsedVar3; 10 | })(); 11 | 12 | var someUsedVar3 = 0; 13 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/no-unused-vars.output.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line no-unused-vars 2 | function someFunc() {} 3 | var someUsedVar1 = 0; 4 | 5 | /* eslint-disable no-unused-vars */ 6 | var someUnUsedVar = 2, someUnUsedVar1 = false;/* eslint-enable no-unused-vars */ 7 | 8 | window.someVar = (function(){ 9 | someUsedVar1 = 1; 10 | return someUsedVar1 || someUsedVar3; 11 | })(); 12 | 13 | var someUsedVar3 = 0; 14 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/react-action-as.input.js: -------------------------------------------------------------------------------- 1 | import { someAction } from '../actions'; 2 | 3 | const mapDispatchToProps = (dispatch) => ( 4 | bindActionCreators( 5 | { 6 | someAction 7 | }, 8 | dispatch 9 | ) 10 | ) 11 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/react-action-as.output.js: -------------------------------------------------------------------------------- 1 | import { someAction as someActionAction } from '../actions'; 2 | 3 | const mapDispatchToProps = (dispatch) => ( 4 | bindActionCreators( 5 | { 6 | someAction: someActionAction 7 | }, 8 | dispatch 9 | ) 10 | ) 11 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/react-destruct-assign.input.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class SomeClassComponent extends React.Component { 4 | someMethod = () => { 5 | return this.props.someProp; 6 | } 7 | 8 | render() { 9 | return (
{`${this.props.someProp} && ${this.props.someState}`}
); 10 | } 11 | } 12 | 13 | const SomeFunctionalComponent = (props) => { 14 | const someProp2 = props.someProp1; 15 | 16 | return ( 17 |
{props.someProp}
18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/react-destruct-assign.output.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class SomeClassComponent extends React.Component { 4 | someMethod = () => { 5 | const { 6 | someProp: someProp 7 | } = this.props; 8 | 9 | return someProp; 10 | } 11 | 12 | render() { 13 | const { 14 | someProp: someProp, 15 | someState: someState 16 | } = this.props; 17 | 18 | return
{`${someProp} && ${someState}`}
; 19 | } 20 | } 21 | 22 | const SomeFunctionalComponent = ( 23 | { 24 | someProp1: someProp2, 25 | someProp: someProp 26 | } 27 | ) => { 28 | return
{someProp}
; 29 | } 30 | -------------------------------------------------------------------------------- /transforms/__tests__/block-scoped-vars-test.js: -------------------------------------------------------------------------------- 1 | const { defineTest } = require('jscodeshift/dist/testUtils'); 2 | 3 | defineTest(__dirname, 'block-scoped-vars'); 4 | -------------------------------------------------------------------------------- /transforms/__tests__/no-camelcase-test.js: -------------------------------------------------------------------------------- 1 | const { defineTest } = require('jscodeshift/dist/testUtils'); 2 | 3 | defineTest(__dirname, 'no-camelcase'); 4 | 5 | defineTest(__dirname, 'no-camelcase', { 6 | 'fix-dependencies': true, 7 | }, 'no-camelcase-fix-dependencies'); 8 | 9 | defineTest(__dirname, 'no-camelcase', { 10 | 'fix-exposed-functions': true, 11 | }, 'no-camelcase-fix-exposed-functions'); 12 | 13 | -------------------------------------------------------------------------------- /transforms/__tests__/no-lonely-if-test.js: -------------------------------------------------------------------------------- 1 | const { defineTest } = require('jscodeshift/dist/testUtils'); 2 | 3 | defineTest(__dirname, 'no-lonely-if'); 4 | -------------------------------------------------------------------------------- /transforms/__tests__/no-nested-ternary-test.js: -------------------------------------------------------------------------------- 1 | const { defineTest } = require('jscodeshift/dist/testUtils'); 2 | 3 | defineTest(__dirname, 'no-nested-ternary'); 4 | -------------------------------------------------------------------------------- /transforms/__tests__/no-unused-vars-test.js: -------------------------------------------------------------------------------- 1 | const { defineTest } = require('jscodeshift/dist/testUtils'); 2 | 3 | defineTest(__dirname, 'no-unused-vars'); 4 | 5 | defineTest(__dirname, 'no-unused-vars', { 6 | 'skip-disable-comments': true, 7 | }, 'no-unused-vars-skip-disable-comments'); 8 | -------------------------------------------------------------------------------- /transforms/__tests__/react-action-as-test.js: -------------------------------------------------------------------------------- 1 | const { defineTest } = require('jscodeshift/dist/testUtils'); 2 | 3 | defineTest(__dirname, 'react-action-as'); 4 | -------------------------------------------------------------------------------- /transforms/__tests__/react-destruct-assign-test.js: -------------------------------------------------------------------------------- 1 | const { defineTest } = require('jscodeshift/dist/testUtils'); 2 | 3 | defineTest(__dirname, 'react-destruct-assign'); 4 | -------------------------------------------------------------------------------- /transforms/no-camelcase.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | const acorn = require('acorn'); 3 | const findGlobals = require('acorn-globals'); 4 | 5 | // global objects 6 | const constants = require('../static/constants.json'); 7 | 8 | const allExternalDeps = Object.keys(constants).reduce((accumulator, key) => accumulator.concat(constants[key]), []); 9 | 10 | module.exports = (file, api, options) => { 11 | const j = api.jscodeshift; 12 | 13 | const printOptions = options.printOptions || { quote: 'single' }; 14 | const root = j(file.source); 15 | 16 | // console.log('\nFixing FilePath - %s\n', filePath); 17 | 18 | const isNotCamelCased = (value) => { 19 | return allExternalDeps.indexOf(value) === -1 && /^[a-z]/.test(value) && !/^[a-z][A-Za-z]*$/.test(value); 20 | }; 21 | 22 | const isJqueryObjVar = (value) => { 23 | return allExternalDeps.indexOf(value) === -1 && /^\$[a-zA-Z_]+/.test(value); 24 | }; 25 | 26 | const isSnakeCasedVar = (value) => { 27 | return ( 28 | allExternalDeps.indexOf(value) === -1 && 29 | /^[a-zA-Z_]+_[a-zA-Z]+/.test(value) && 30 | value.toUpperCase() !== value && 31 | value.indexOf('__') === -1 32 | ); 33 | }; 34 | 35 | const getNonJqueryName = (jqueryObjName) => { 36 | return jqueryObjName.split('$').slice(-1).join('$'); 37 | }; 38 | 39 | const isFixableVariable = (variableName) => { 40 | let isEligibleVariable = false; 41 | 42 | if (isNotCamelCased(variableName) || isSnakeCasedVar(variableName)) { 43 | isEligibleVariable = true; 44 | } 45 | 46 | if (isJqueryObjVar(variableName)) { 47 | const nonJqueryName = getNonJqueryName(variableName); 48 | 49 | if (isNotCamelCased(nonJqueryName)) { 50 | isEligibleVariable = true; 51 | } 52 | } 53 | 54 | return isEligibleVariable; 55 | }; 56 | 57 | const getAndFixIdentifiers = (nodePathCollection, variableName) => { 58 | const depUsageCollec = nodePathCollection.find(j.Identifier, { name: variableName }).filter((depPath) => { 59 | if (depPath.name === 'property') { 60 | return depPath.parentPath.value.computed; 61 | } 62 | 63 | return !['key'].includes(depPath.name); 64 | }); 65 | 66 | depUsageCollec.forEach((depUsagePath) => { 67 | const depName = depUsagePath.value.name; 68 | 69 | if (isNotCamelCased(depName) || isSnakeCasedVar(depName)) { 70 | depUsagePath.value.name = _.camelCase(depName); 71 | } 72 | 73 | if (isJqueryObjVar(depName)) { 74 | const nonJqueryName = getNonJqueryName(depName); 75 | 76 | depUsagePath.value.name = `$${_.camelCase(nonJqueryName)}`; 77 | } 78 | }); 79 | }; 80 | 81 | const fixFunctionParams = (nodePath) => { 82 | nodePath.value.params.forEach((paramNode) => { 83 | const variableName = paramNode.name; 84 | 85 | if (isFixableVariable(variableName)) { 86 | getAndFixIdentifiers(j(nodePath), variableName); 87 | } 88 | }); 89 | }; 90 | 91 | const transformExposedFuncs = options['fix-exposed-functions'] || false; 92 | const transformDependencies = options['fix-dependencies'] || false; 93 | 94 | // Fix all variable declarators 95 | const transformsedVarDeclarators = root 96 | .find(j.VariableDeclarator, (node) => { 97 | const variableName = node.id.name; 98 | 99 | return isFixableVariable(variableName); 100 | }) 101 | .forEach((path) => { 102 | const variableName = path.value.id.name; 103 | 104 | const closestScopeCollec = j(path).closestScope(); 105 | 106 | getAndFixIdentifiers(closestScopeCollec, variableName); 107 | }) 108 | .size(); 109 | 110 | // fix dependencies 111 | if (transformDependencies) { 112 | // get dependencies and fix them 113 | const ast = acorn.parse(file.source, { 114 | loc: true 115 | }); 116 | 117 | let dependencies = findGlobals(ast).filter((dep) => allExternalDeps.indexOf(dep.name) === -1); 118 | 119 | dependencies = [...new Set(dependencies)]; 120 | 121 | dependencies.forEach(({ name: variableName }) => { 122 | if (isFixableVariable(variableName)) { 123 | getAndFixIdentifiers(root, variableName); 124 | } 125 | }); 126 | } 127 | 128 | // Fix all functional declarations 129 | const transformsedFuncDeclarations = root 130 | .find(j.FunctionDeclaration) 131 | .filter((nodePath) => { 132 | return transformExposedFuncs || !nodePath.scope.parent.isGlobal; 133 | }) 134 | .filter((nodePath) => { 135 | return ( 136 | isFixableVariable(nodePath.value.id.name) || 137 | nodePath.value.params.find((paramNode) => { 138 | const variableName = paramNode.name; 139 | 140 | return isFixableVariable(variableName); 141 | }) 142 | ); 143 | }) 144 | .forEach((nodePath) => { 145 | // Fix all functional params 146 | fixFunctionParams(nodePath); 147 | 148 | // fix function names 149 | const variableName = nodePath.value.id.name; 150 | 151 | if (isFixableVariable(variableName)) { 152 | // Function name is not camel cased 153 | nodePath.value.id.name = _.camelCase(variableName); 154 | 155 | // alter function invocations 156 | root 157 | .find(j.CallExpression, (callExpressionNode) => { 158 | return callExpressionNode.callee.name === variableName; 159 | }) 160 | .forEach((callExpressionNodePath) => { 161 | callExpressionNodePath.value.callee.name = _.camelCase(callExpressionNodePath.value.callee.name); 162 | }); 163 | 164 | // alter exposed property values 165 | root 166 | .find(j.Property, (propertyNode) => { 167 | return propertyNode.value.name === variableName; 168 | }) 169 | .forEach((propertyNodePath) => { 170 | propertyNodePath.value.value.name = _.camelCase(propertyNodePath.value.value.name); 171 | }); 172 | 173 | // alter call expression arguments 174 | root 175 | .find(j.Identifier, (identifierNode) => { 176 | return identifierNode.name === variableName; 177 | }) 178 | .filter((identifierNodePath) => { 179 | return identifierNodePath.parent.value.type === 'CallExpression'; 180 | }) 181 | .forEach((identifierNodePath) => { 182 | identifierNodePath.value.name = _.camelCase(identifierNodePath.value.name); 183 | }); 184 | 185 | // alter member expression with call, bind, apply 186 | root 187 | .find(j.MemberExpression, (memberExpNode) => { 188 | return ( 189 | memberExpNode.object.name === variableName && 190 | ['call', 'bind', 'apply'].includes(memberExpNode.property.name) 191 | ); 192 | }) 193 | .forEach((memberExpNodePath) => { 194 | memberExpNodePath.value.object.name = _.camelCase(memberExpNodePath.value.object.name); 195 | }); 196 | } 197 | }) 198 | .size(); 199 | 200 | // Fix all functional expressions 201 | const transformsedFuncExpressions = root 202 | .find(j.FunctionExpression) 203 | .filter((nodePath) => { 204 | return transformExposedFuncs || !nodePath.scope.parent.isGlobal; 205 | }) 206 | .filter((nodePath) => { 207 | return ( 208 | (nodePath.value.id && isFixableVariable(nodePath.value.id.name)) || 209 | nodePath.value.params.find((paramNode) => { 210 | const variableName = paramNode.name; 211 | 212 | return isFixableVariable(variableName); 213 | }) 214 | ); 215 | }) 216 | .forEach((nodePath) => { 217 | // Fix all functional params 218 | fixFunctionParams(nodePath); 219 | 220 | // fix function names 221 | if (nodePath.value.id) { 222 | const variableName = nodePath.value.id.name; 223 | 224 | if (isFixableVariable(variableName)) { 225 | // Function name is not camel cased 226 | nodePath.value.id.name = _.camelCase(variableName); 227 | } 228 | } 229 | }) 230 | .size(); 231 | 232 | return transformsedVarDeclarators || transformsedFuncDeclarations || transformsedFuncExpressions 233 | ? root.toSource(printOptions) 234 | : null; 235 | }; 236 | -------------------------------------------------------------------------------- /transforms/no-lonely-if.js: -------------------------------------------------------------------------------- 1 | module.exports = (file, api, options) => { 2 | const j = api.jscodeshift; 3 | 4 | const printOptions = options.printOptions || { quote: 'single' }; 5 | const root = j(file.source); 6 | 7 | // console.log('\nFixing FilePath - %s\n', file.path); 8 | 9 | const didTransform = root 10 | .find(j.IfStatement) 11 | .filter((nodePath) => { 12 | const closestBlockStatementCollec = j(nodePath).closest(j.BlockStatement); 13 | 14 | if (closestBlockStatementCollec.length) { 15 | const blockStatementBody = closestBlockStatementCollec.nodes()[0].body; 16 | 17 | return ( 18 | closestBlockStatementCollec.length && 19 | blockStatementBody.length === 1 && 20 | blockStatementBody[0].type === 'IfStatement' 21 | ); 22 | } 23 | 24 | return false; 25 | }) 26 | .forEach((nodePath) => { 27 | const closestBlockStatementCollec = j(nodePath).closest(j.BlockStatement); 28 | 29 | const closestBlockStatementStart = closestBlockStatementCollec.nodes()[0].start; 30 | 31 | const closestIfStatementCollec = j(nodePath).closest(j.IfStatement, (node) => { 32 | return node.alternate && node.alternate.start === closestBlockStatementStart; 33 | }); 34 | 35 | closestIfStatementCollec.forEach((ifStatementNodePath) => { 36 | ifStatementNodePath.value.alternate = nodePath.value; 37 | }); 38 | }) 39 | .size(); 40 | 41 | return didTransform ? root.toSource(printOptions) : null; 42 | }; 43 | -------------------------------------------------------------------------------- /transforms/no-nested-ternary.js: -------------------------------------------------------------------------------- 1 | module.exports = (file, api, options) => { 2 | const j = api.jscodeshift; 3 | 4 | const printOptions = options.printOptions || { quote: 'single' }; 5 | const root = j(file.source); 6 | 7 | // console.log('\nFixing FilePath - %s\n', file.path); 8 | 9 | const constructBlockStatement = (conditionExpressionNode, type, variableName = null) => { 10 | const blockStatementNodes = []; 11 | 12 | if (conditionExpressionNode[type].type === 'ConditionalExpression') { 13 | blockStatementNodes.push( 14 | constructIfElseBlockFromConditionalExpression(conditionExpressionNode[type], variableName) 15 | ); 16 | } else if (variableName) { 17 | blockStatementNodes.push( 18 | j.expressionStatement(j.assignmentExpression('=', j.identifier(variableName), conditionExpressionNode[type])) 19 | ); 20 | } else { 21 | blockStatementNodes.push(j.returnStatement(conditionExpressionNode[type])); 22 | } 23 | 24 | return j.blockStatement(blockStatementNodes); 25 | }; 26 | 27 | const constructIfElseBlockFromConditionalExpression = (conditionExpressionNode, variableName = null) => { 28 | const ifStatementNode = j.ifStatement( 29 | conditionExpressionNode.test, 30 | constructBlockStatement(conditionExpressionNode, 'consequent', variableName), 31 | constructBlockStatement(conditionExpressionNode, 'alternate', variableName) 32 | ); 33 | 34 | return ifStatementNode; 35 | }; 36 | 37 | const constructIIFE = (conditionExpressionNode) => { 38 | const blockStatementNodes = [constructIfElseBlockFromConditionalExpression(conditionExpressionNode)]; 39 | 40 | const blockStatement = j.blockStatement(blockStatementNodes); 41 | 42 | return j.callExpression(j.functionExpression(null, [], blockStatement), []); 43 | }; 44 | 45 | const conditionExpressionCollec = root.find(j.ConditionalExpression, (node) => { 46 | return node.consequent.type === 'ConditionalExpression' || node.alternate.type === 'ConditionalExpression'; 47 | }); 48 | 49 | const didTransform = conditionExpressionCollec 50 | .forEach((nodePath) => { 51 | nodePath.replace(constructIIFE(nodePath.value)); 52 | }) 53 | .size(); 54 | 55 | return didTransform ? root.toSource(printOptions) : null; 56 | }; 57 | -------------------------------------------------------------------------------- /transforms/react-action-as.js: -------------------------------------------------------------------------------- 1 | module.exports = (file, api, options) => { 2 | const j = api.jscodeshift; 3 | 4 | const printOptions = options.printOptions || { quote: 'single' }; 5 | const root = j(file.source); 6 | 7 | // console.log('\nFixing FilePath - %s\n', file.path); 8 | 9 | const didTransformObjExpression = root 10 | .find(j.CallExpression, (node) => { 11 | return node.callee.name === 'bindActionCreators'; 12 | }) 13 | .forEach((nodePath) => { 14 | const objectExpressNode = nodePath.value.arguments.find((node) => { 15 | return node.type === 'ObjectExpression'; 16 | }); 17 | 18 | objectExpressNode.properties = objectExpressNode.properties.map((property) => { 19 | if (property.key.name === property.value.name) { 20 | return j.property('init', j.identifier(property.key.name), j.identifier(`${property.key.name}Action`)); 21 | } 22 | 23 | return property; 24 | }); 25 | }) 26 | .size(); 27 | 28 | const didTransformImports = root 29 | .find(j.ImportDeclaration, (node) => { 30 | return node.source.type === 'Literal' && node.source.value.indexOf('actions') !== -1; 31 | }) 32 | .forEach((nodePath) => { 33 | nodePath.value.specifiers = nodePath.value.specifiers.map((specifier) => { 34 | if (specifier.type !== 'ImportSpecifier') { 35 | return specifier; 36 | } 37 | 38 | if (specifier.imported.name === specifier.local.name) { 39 | return j.importSpecifier( 40 | j.identifier(specifier.imported.name), 41 | j.identifier(`${specifier.imported.name}Action`) 42 | ); 43 | } 44 | 45 | return specifier; 46 | }); 47 | }) 48 | .size(); 49 | 50 | return didTransformImports || didTransformObjExpression ? root.toSource(printOptions) : null; 51 | }; 52 | -------------------------------------------------------------------------------- /transforms/react-destruct-assign.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | 3 | module.exports = (file, api, options) => { 4 | const j = api.jscodeshift; 5 | 6 | const printOptions = options.printOptions || { quote: 'single' }; 7 | const root = j(file.source); 8 | 9 | // console.log('\nFixing FilePath - %s\n', file.path); 10 | 11 | const transformedClassDeclaration = root.find(j.ClassDeclaration).forEach((classDeclarationNodePath) => { 12 | // exports a class component 13 | ['props', 'state'].forEach((type) => { 14 | const nodePathsCollection = j(classDeclarationNodePath) 15 | .find(j.MemberExpression, (node) => { 16 | return node.object.type === 'ThisExpression' && node.property.name === type; 17 | }) 18 | .filter((nodePath) => { 19 | return nodePath.parentPath.value.type === 'MemberExpression'; 20 | }); 21 | 22 | // group nodes with common scope together 23 | const groupedByScopeNodePathsObj = _.chain(nodePathsCollection.paths()) 24 | .groupBy((path) => j(path).closestScope().get(0).scope.path.value.start) 25 | .value(); 26 | 27 | const scopesStart = Object.keys(groupedByScopeNodePathsObj); 28 | 29 | scopesStart.forEach((start) => { 30 | const nodePaths = groupedByScopeNodePathsObj[start]; 31 | 32 | const groupedCollection = j(nodePaths); 33 | 34 | let closestScopeCollec = groupedCollection.closestScope(j.Node, { start: parseInt(start, 10) }); 35 | 36 | const classProp = ['MethodDefinition', 'ClassProperty'].find((typeProp) => { 37 | return closestScopeCollec.closest(j[typeProp]).length; 38 | }); 39 | 40 | closestScopeCollec = j(closestScopeCollec.closest(j[classProp]).get('value')); 41 | 42 | const blockStatementCollec = closestScopeCollec.find(j.BlockStatement); 43 | 44 | const blockStatementNode = blockStatementCollec 45 | .paths() 46 | .find((path) => path.parent === closestScopeCollec.paths()[0]).node; 47 | 48 | let dependencies = []; 49 | 50 | groupedCollection.forEach((nodePath) => { 51 | dependencies.push(nodePath.parentPath.value.property.name); 52 | 53 | j(nodePath).closest(j.MemberExpression).paths()[0].replace(nodePath.parentPath.value.property); 54 | }); 55 | 56 | dependencies = _.uniq(dependencies); 57 | 58 | const constDeclarationCollec = closestScopeCollec.find(j.VariableDeclaration, (node) => { 59 | return node.kind === 'const'; 60 | }); 61 | 62 | const thisDotTypeDeclaratorCollec = constDeclarationCollec.find(j.VariableDeclarator, (node) => { 63 | return ( 64 | node.init.type === 'MemberExpression' && 65 | node.init.object.type === 'ThisExpression' && 66 | node.init.property.type === 'Identifier' && 67 | node.init.property.name === type 68 | ); 69 | }); 70 | 71 | if (thisDotTypeDeclaratorCollec.length) { 72 | const thisDotTypeDeclarationCollec = thisDotTypeDeclaratorCollec.closest(j.VariableDeclaration); 73 | // there is already const declaration inside BlockStatement 74 | const objectExpressionProperties = thisDotTypeDeclaratorCollec.get('id').value.properties; 75 | 76 | const alreadyDeclaredProps = objectExpressionProperties.map((property) => { 77 | return property.value.name; 78 | }); 79 | 80 | dependencies = dependencies.filter((dep) => { 81 | return !alreadyDeclaredProps.includes(dep); 82 | }); 83 | 84 | if (!dependencies.length) { 85 | return; 86 | } 87 | 88 | const newProperties = dependencies.map((dep) => { 89 | return j.property('init', j.identifier(dep), j.identifier(dep)); 90 | }); 91 | 92 | thisDotTypeDeclaratorCollec.get('id').value.properties = objectExpressionProperties.concat(newProperties); 93 | 94 | // move this const decl to the top of the scope 95 | const thisDotTypeDeclarationNode = thisDotTypeDeclarationCollec.nodes()[0]; 96 | 97 | if (!thisDotTypeDeclarationNode.start) { 98 | // still hasn't got start 99 | return; 100 | } 101 | 102 | blockStatementNode.body = _.filter(blockStatementNode.body, (node) => { 103 | return node.start !== thisDotTypeDeclarationNode.start; 104 | }); 105 | 106 | blockStatementNode.body.unshift(thisDotTypeDeclarationNode); 107 | } else { 108 | if (!dependencies.length) { 109 | return; 110 | } 111 | 112 | const newProperties = dependencies.map((dep) => { 113 | return j.property('init', j.identifier(dep), j.identifier(dep)); 114 | }); 115 | // declare at each scope level 116 | blockStatementNode.body.unshift( 117 | j.variableDeclaration('const', [ 118 | j.variableDeclarator( 119 | j.objectPattern(newProperties), 120 | j.memberExpression(j.thisExpression(), j.identifier(type)) 121 | ) 122 | ]) 123 | ); 124 | } 125 | }); 126 | }); 127 | }); 128 | 129 | // exports a functional component 130 | const type = 'props'; 131 | 132 | const transformedArrowFunctionExpression = root 133 | .find(j.ArrowFunctionExpression, (node) => { 134 | return node.params.find((param) => { 135 | return param.name === type; 136 | }); 137 | }) 138 | .forEach((arrowFunctionNodePath) => { 139 | const nodePathsCollection = j(arrowFunctionNodePath).find(j.MemberExpression, (node) => { 140 | return node.object.name === type; 141 | }); 142 | 143 | let dependencies = []; 144 | 145 | const propAliasMap = {}; 146 | 147 | nodePathsCollection.forEach((nodePath) => { 148 | const propName = nodePath.value.property.name; 149 | dependencies.push(propName); 150 | 151 | const parentNode = nodePath.parentPath.value; 152 | 153 | if (parentNode.type === 'VariableDeclarator') { 154 | propAliasMap[propName] = parentNode.id.name; 155 | 156 | j(nodePath).closest(j.VariableDeclaration).paths()[0].replace(); 157 | } 158 | 159 | j(nodePath).paths()[0].replace(nodePath.value.property); 160 | }); 161 | 162 | dependencies = _.uniq(dependencies); 163 | 164 | if (dependencies.length) { 165 | const properties = dependencies.map((dep) => { 166 | if (propAliasMap[dep]) { 167 | return j.property('init', j.identifier(dep), j.identifier(propAliasMap[dep])); 168 | } 169 | 170 | return j.property('init', j.identifier(dep), j.identifier(dep)); 171 | }); 172 | 173 | arrowFunctionNodePath.value.params = arrowFunctionNodePath.value.params.map((node) => { 174 | if (node.name === type) { 175 | return j.objectPattern(properties); 176 | } 177 | 178 | return node; 179 | }); 180 | } 181 | }); 182 | 183 | return transformedClassDeclaration || transformedArrowFunctionExpression ? root.toSource(printOptions) : null; 184 | }; 185 | -------------------------------------------------------------------------------- /transforms/with-globals/no-underscore-dangle.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { resolve } = require('path'); 3 | const jscodeshift = require('jscodeshift'); 4 | // const _ = require('lodash'); 5 | 6 | const j = jscodeshift; 7 | 8 | // global objects 9 | const constants = require('../../static/constants.json'); 10 | 11 | const allExternalDeps = Object.keys(constants).reduce((accumulator, key) => accumulator.concat(constants[key]), []); 12 | 13 | const hasDanglingUnderscore = (value, isFunctionalParam = false) => { 14 | let leadingRegex = /^__[a-zA-Z]+/; 15 | 16 | if (isFunctionalParam) { 17 | leadingRegex = /^_[a-zA-Z_]+/; 18 | } 19 | 20 | return ( 21 | allExternalDeps.indexOf(value) === -1 && 22 | (leadingRegex.test(value) || /^[a-zA-Z]+_$/.test(value)) && 23 | value.toUpperCase() !== value 24 | ); 25 | }; 26 | 27 | const replaceDanglingUnderscore = (value, isFunctionalParam = false) => { 28 | if (/^__/.test(value) && !isFunctionalParam) { 29 | return value.replace(/__/g, '_'); 30 | } 31 | 32 | return value.replace(/_/g, ''); 33 | }; 34 | 35 | const isFixableVariable = (variableName, isFunctionalParam = false) => { 36 | let isEligibleVariable = false; 37 | 38 | if (hasDanglingUnderscore(variableName, isFunctionalParam)) { 39 | isEligibleVariable = true; 40 | } 41 | 42 | return isEligibleVariable; 43 | }; 44 | 45 | const getAndFixIdentifiers = (nodePathCollection, variableName, isFunctionalParam = false) => { 46 | const depUsageCollec = nodePathCollection.find(j.Identifier, { name: variableName }).filter((depPath) => { 47 | if (depPath.name === 'property') { 48 | return depPath.parentPath.value.computed; 49 | } 50 | 51 | return !['key'].includes(depPath.name); 52 | }); 53 | 54 | depUsageCollec.forEach((depUsagePath) => { 55 | const depName = depUsagePath.value.name; 56 | 57 | if (hasDanglingUnderscore(depName, isFunctionalParam)) { 58 | depUsagePath.value.name = replaceDanglingUnderscore(depName, isFunctionalParam); 59 | } 60 | }); 61 | }; 62 | 63 | const fixFunctionParams = (nodePath) => { 64 | nodePath.value.params.forEach((paramNode) => { 65 | const variableName = paramNode.name; 66 | 67 | if (isFixableVariable(variableName, true)) { 68 | getAndFixIdentifiers(j(nodePath), variableName, true); 69 | } 70 | }); 71 | }; 72 | 73 | /** 74 | * { Transformer to fix all the non camel cased variables from a JS file } 75 | * 76 | * @param {String} filePath Path of the file to fix 77 | * @param {Boolean} [updateInplace=false] Whether to update the file or not 78 | * @param {Object} [collectedGlobals={}] Contains two keys globalsExposed, dependencies for the file 79 | * @return {String} { Transformed string to write to the file } 80 | */ 81 | const transformNoUnderscoreDangle = (filePath, updateInplace = false, collectedGlobals = {}) => { 82 | if (filePath.constructor !== String) { 83 | throw new Error('filePath should be a String'); 84 | } 85 | 86 | // console.log('\nFixing FileName - %s\n', filePath); 87 | 88 | const source = fs.readFileSync(resolve(__dirname, filePath), { encoding: 'utf8' }); 89 | 90 | const root = j(source); 91 | 92 | // Fix all variable declaration 93 | root 94 | .find(j.VariableDeclarator, (node) => { 95 | const variableName = node.id.name; 96 | 97 | return isFixableVariable(variableName); 98 | }) 99 | .forEach((path) => { 100 | const variableName = path.value.id.name; 101 | 102 | const closestScopeCollec = j(path).closestScope(); 103 | 104 | getAndFixIdentifiers(closestScopeCollec, variableName); 105 | }); 106 | 107 | // fix dependencies 108 | if (collectedGlobals.dependencies) { 109 | collectedGlobals.dependencies.forEach(({ name: variableName }) => { 110 | if (isFixableVariable(variableName)) { 111 | getAndFixIdentifiers(root, variableName); 112 | } 113 | }); 114 | } 115 | 116 | // Fix all functional declarations 117 | const functionDeclaratorCollec = root.find(j.FunctionDeclaration); 118 | 119 | functionDeclaratorCollec.forEach((nodePath) => { 120 | // Fix all functional params 121 | fixFunctionParams(nodePath); 122 | 123 | // fix function names 124 | const variableName = nodePath.value.id.name; 125 | 126 | if ( 127 | !(collectedGlobals.globalsExposed && collectedGlobals.globalsExposed.includes(variableName)) && 128 | isFixableVariable(variableName) 129 | ) { 130 | // Function name is not camel cased 131 | nodePath.value.id.name = replaceDanglingUnderscore(variableName); 132 | 133 | // alter function invocations 134 | root 135 | .find(j.CallExpression, (callExpressionNode) => { 136 | return callExpressionNode.callee.name === variableName; 137 | }) 138 | .forEach((callExpressionNodePath) => { 139 | callExpressionNodePath.value.callee.name = replaceDanglingUnderscore( 140 | callExpressionNodePath.value.callee.name 141 | ); 142 | }); 143 | 144 | // alter exposed property values 145 | root 146 | .find(j.Property, (propertyNode) => { 147 | return propertyNode.value.name === variableName; 148 | }) 149 | .forEach((propertyNodePath) => { 150 | propertyNodePath.value.value.name = replaceDanglingUnderscore(propertyNodePath.value.value.name); 151 | }); 152 | 153 | // alter call expression arguments 154 | root 155 | .find(j.Identifier, (identifierNode) => { 156 | return identifierNode.name === variableName; 157 | }) 158 | .filter((identifierNodePath) => { 159 | return identifierNodePath.parent.value.type === 'CallExpression'; 160 | }) 161 | .forEach((identifierNodePath) => { 162 | identifierNodePath.value.name = replaceDanglingUnderscore(identifierNodePath.value.name); 163 | }); 164 | 165 | // alter member expression with call, bind, apply 166 | root 167 | .find(j.MemberExpression, (memberExpNode) => { 168 | return ( 169 | memberExpNode.object.name === variableName && 170 | ['call', 'bind', 'apply'].includes(memberExpNode.property.name) 171 | ); 172 | }) 173 | .forEach((memberExpNodePath) => { 174 | memberExpNodePath.value.object.name = replaceDanglingUnderscore(memberExpNodePath.value.object.name); 175 | }); 176 | } 177 | }); 178 | 179 | // Fix all functional expressions params 180 | const functionExpressionCollec = root.find(j.FunctionExpression); 181 | 182 | functionExpressionCollec.forEach((nodePath) => { 183 | // Fix all functional params 184 | fixFunctionParams(nodePath); 185 | }); 186 | 187 | const results = root.toSource(); 188 | 189 | if (updateInplace) { 190 | fs.writeFileSync(resolve(__dirname, filePath), results.replace(/;;/g, ';')); 191 | } 192 | 193 | return results; 194 | }; 195 | 196 | module.exports = transformNoUnderscoreDangle; 197 | -------------------------------------------------------------------------------- /transforms/with-globals/unused-assigned-vars.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { resolve } = require('path'); 3 | const jscodeshift = require('jscodeshift'); 4 | const _ = require('lodash'); 5 | const acorn = require('acorn'); 6 | const findGlobals = require('acorn-globals'); 7 | 8 | const j = jscodeshift; 9 | 10 | // global objects 11 | const constants = require('../../static/constants.json'); 12 | 13 | const allExternalDeps = Object.keys(constants).reduce((accumulator, key) => accumulator.concat(constants[key]), []); 14 | 15 | /** 16 | * { Transformer to fix all the unused assigned variables from a JS file } 17 | * 18 | * @param {String} filePath Path of the file to fix 19 | * @param {Boolean} [updateInplace=false] Whether to update the file or not 20 | * @return {String} { Transformed string to write to the file } 21 | */ 22 | const transformUnusedAssignedVars = (filePath, updateInplace = false) => { 23 | if (filePath.constructor !== String) { 24 | throw new Error('filePath should be a String'); 25 | } 26 | 27 | const source = fs.readFileSync(resolve(__dirname, filePath), { encoding: 'utf8' }); 28 | 29 | const ast = acorn.parse(source, { 30 | loc: true 31 | }); 32 | 33 | const dependencies = findGlobals(ast).filter((dep) => allExternalDeps.indexOf(dep.name) === -1); 34 | 35 | const root = j(source); 36 | 37 | // console.log('\nFixing FilePath - %s\n', filePath); 38 | 39 | dependencies.forEach(({ name, nodes }) => { 40 | console.log('Fixing Dependency - %s\n', name); 41 | 42 | const nodesStart = _.map(nodes, 'start'); 43 | 44 | const nodePathsCollection = root.find( 45 | j.Identifier, 46 | (path) => name === path.name && nodesStart.includes(path.start) 47 | ); 48 | 49 | if (!nodePathsCollection.length) { 50 | // console.log('\nFixing FilePath - %s\nNo matching nodes found for dependency - %s\n', filePath, name); 51 | return; 52 | } 53 | 54 | // fix only dependencies with AssignmentExpression, ex: a = 1; 55 | const identifiersWithinAssignExpCollection = nodePathsCollection.filter( 56 | (path) => path.parentPath.value.type === 'AssignmentExpression' 57 | ); 58 | 59 | if (identifiersWithinAssignExpCollection.length === nodePathsCollection.length) { 60 | const standaloneExpressionStatement = identifiersWithinAssignExpCollection.closest(j.ExpressionStatement); 61 | 62 | // only one references to the variable and that too not at Program level then directly remove its expression 63 | if ( 64 | standaloneExpressionStatement.length && 65 | standaloneExpressionStatement.closestScope().paths()[0].value.type !== 'Program' 66 | ) { 67 | standaloneExpressionStatement.paths()[0].replace(); 68 | } 69 | } 70 | }); 71 | 72 | const results = root.toSource(); 73 | 74 | if (updateInplace) { 75 | fs.writeFileSync(resolve(__dirname, filePath), results.replace(/;;/g, ';')); 76 | } 77 | 78 | return results; 79 | }; 80 | 81 | module.exports = transformUnusedAssignedVars; 82 | -------------------------------------------------------------------------------- /utils/find-globals-exposed.js: -------------------------------------------------------------------------------- 1 | function findGlobalsExposed(ast) { 2 | const out = {}; 3 | 4 | function makeRecord(name) { 5 | if (!(name in out)) { 6 | out[name] = { 7 | name, 8 | type: null, 9 | ast: null, 10 | isFunction: null, 11 | count: 0 12 | }; 13 | } 14 | return out[name]; 15 | } 16 | 17 | function scanVariableDeclaration(stmt) { 18 | stmt.declarations.forEach((decl) => { 19 | const record = makeRecord(decl.id.name); 20 | record.type = 'var'; 21 | record.ast = decl; 22 | record.isFunction = !!(decl.init && decl.init.type === 'FunctionExpression'); 23 | record.count++; 24 | }); 25 | } 26 | 27 | function scanBody(body, scopeType) { 28 | if (body.type === 'BlockStatement') { 29 | body = body.body; 30 | } 31 | 32 | for (let i = 0; i < body.length; ++i) { 33 | const stmt = body[i]; 34 | let record; 35 | switch (stmt.type) { 36 | // var foo = ... 37 | case 'VariableDeclaration': 38 | scanVariableDeclaration(stmt); 39 | break; 40 | // function foo() { ... } 41 | case 'FunctionDeclaration': 42 | record = makeRecord(stmt.id.name); 43 | record.type = 'function'; 44 | record.ast = stmt; 45 | record.isFunction = true; 46 | record.count++; 47 | break; 48 | case 'ForStatement': 49 | if (stmt.init.type === 'VariableDeclaration') { 50 | scanVariableDeclaration(stmt.init); 51 | } 52 | scanBody(stmt.body, stmt.type); 53 | break; 54 | case 'ForInStatement': 55 | if (stmt.left.type === 'VariableDeclaration') { 56 | scanVariableDeclaration(stmt.left); 57 | } 58 | scanBody(stmt.body, stmt.type); 59 | break; 60 | case 'WhileStatement': 61 | case 'DoWhileStatement': 62 | case 'ExpressionStatement': 63 | if (scopeType === 'Program' && stmt.expression.type === 'AssignmentExpression') { 64 | record = makeRecord(stmt.expression.left.name); 65 | record.type = 'var'; 66 | record.ast = stmt.expression.right; 67 | record.isFunction = !!(stmt.expression.right && stmt.expression.right.type === 'FunctionExpression'); 68 | record.count++; 69 | } 70 | break; 71 | default: 72 | break; 73 | } 74 | } 75 | } 76 | 77 | scanBody(ast.body, ast.type); 78 | 79 | return out; 80 | } 81 | 82 | module.exports = findGlobalsExposed; 83 | --------------------------------------------------------------------------------