{"id":13532169,"url":"https://github.com/JamieMason/codemods","last_synced_at":"2025-04-01T20:31:28.311Z","repository":{"id":38709903,"uuid":"58357941","full_name":"JamieMason/codemods","owner":"JamieMason","description":"A collection of transforms for use with JSCodeshift","archived":false,"fork":false,"pushed_at":"2023-03-31T11:29:34.000Z","size":373,"stargazers_count":59,"open_issues_count":2,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-18T19:35:12.915Z","etag":null,"topics":["add-react-import","astexplorer","automated-refactoring","code-transformation","codemod","codemods","default-props","jscodeshift","named-exports","named-imports","prop-types","proptypes","refactoring","sort-jsx","sort-objects"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JamieMason.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"github":"JamieMason"}},"created_at":"2016-05-09T07:40:59.000Z","updated_at":"2024-03-29T04:32:06.000Z","dependencies_parsed_at":"2024-01-14T00:50:29.481Z","dependency_job_id":"cb7f3c69-7157-471a-b301-616002d42ede","html_url":"https://github.com/JamieMason/codemods","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JamieMason%2Fcodemods","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JamieMason%2Fcodemods/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JamieMason%2Fcodemods/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JamieMason%2Fcodemods/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JamieMason","download_url":"https://codeload.github.com/JamieMason/codemods/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246709923,"owners_count":20821297,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["add-react-import","astexplorer","automated-refactoring","code-transformation","codemod","codemods","default-props","jscodeshift","named-exports","named-imports","prop-types","proptypes","refactoring","sort-jsx","sort-objects"],"created_at":"2024-08-01T07:01:08.740Z","updated_at":"2025-04-01T20:31:23.299Z","avatar_url":"https://github.com/JamieMason.png","language":"JavaScript","readme":"# codemods\n\n\u003e A collection of transforms for use with\n\u003e [facebook/jscodeshift](https://github.com/facebook/jscodeshift).\n\n[![Follow JamieMason on GitHub](https://img.shields.io/github/followers/JamieMason.svg?style=social\u0026label=Follow)](https://github.com/JamieMason)\n[![Follow fold_left on Twitter](https://img.shields.io/twitter/follow/fold_left.svg?style=social\u0026label=Follow)](https://twitter.com/fold_left)\n\n* [🌩 Installation](#-installation)\n* [🕹 Usage](#-usage)\n* [⚙️ Contributing](#️-contributing)\n* [📝 API](#-api)\n  * [use-string-literal-props](#use-string-literal-props)\n  * [add-react-import](#add-react-import)\n  * [import-from-root](#import-from-root)\n  * [remove-react-prop-types](#remove-react-prop-types)\n  * [remove-react-default-props](#remove-react-default-props)\n  * [sort-jsx-props](#sort-jsx-props)\n  * [sort-object-props](#sort-object-props)\n  * [use-named-exports](#use-named-exports)\n  * [use-named-imports](#use-named-imports)\n* [❓ Quick Intro To Making A Codemod](#-quick-intro-to-making-a-codemod)\n* [🙋🏾‍♀️ Getting Help](#️-getting-help)\n\n## 🌩 Installation\n\n```sh\ngit clone https://github.com/JamieMason/codemods.git\ncd codemods\nyarn install\n```\n\n## 🕹 Usage\n\n```\n# yarn\nyarn name-of-the-transform \u003cpath-to-file\u003e\n\n# npm\nnpm run name-of-the-transform -- \u003cpath-to-file\u003e\n\n# jscodeshift\njscodeshift -t ./transforms/name-of-the-transform.js \u003cpath-to-file\u003e\n```\n\n## ⚙️ Contributing\n\nTransforms can be created at `./transforms/\u003ctransform-name\u003e.js` and tested by\nadding example input files at\n`./test/fixtures/\u003ctransform-name\u003e/\u003cscenario-name\u003e.input.js` with the\ncorresponding expected output alongside it at\n`./test/fixtures/\u003ctransform-name\u003e/\u003cscenario-name\u003e.output.js`.\n\nAll fixtures are discovered and tested when running `yarn test`.\n\n## 📝 API\n\n### use-string-literal-props\n\nConvert JSX props which are expressions for a string literal, into just a string literal.\n\n```jsx\n/* INPUT */\nconst SomeComponent = () =\u003e (\n  \u003cAnotherComponent\n    foo={'string'}\n    label={`template with 0 substitutions`}\n    whatever={`template with ${1} substitution`}\n  /\u003e\n);\n\n/* OUTPUT */\nconst SomeComponent = () =\u003e (\n  \u003cAnotherComponent\n    foo=\"string\"\n    label=\"template with 0 substitutions\"\n    whatever={`template with ${1} substitution`}\n  /\u003e\n);\n```\n\n### add-react-import\n\nImport React if it is missing from a file which uses JSX.\n\n```jsx\n/* INPUT */\nexport const Component = () =\u003e \u003cdiv /\u003e\n\n/* OUTPUT */\nimport React from \"react\";\nexport const Component = () =\u003e \u003cdiv /\u003e\n```\n\n### import-from-root\n\nRewrite deep imports to import from a packages' root index.\n\n\u003e Set the Environment Variable `IMPORT_FROM_ROOT` to apply this transform only\n\u003e to packages whose name starts with that string:\n\u003e `IMPORT_FROM_ROOT=some-package yarn import-from-root \u003cpath-to-file\u003e`\n\n```js\n/* INPUT */\nimport { foo } from \"some-package/foo/bar/baz\";\n\n/* OUTPUT */\nimport { foo } from \"some-package\";\n```\n\n### remove-react-prop-types\n\nRemove use of React PropTypes.\n\n```jsx\n/* INPUT */\nimport React from 'react'\nimport PropTypes from 'prop-types'\n\nexport const Greet = ({ name }) =\u003e \u003cspan\u003eHi {name}\u003c/span\u003e\nGreet.propTypes = { name: PropTypes.string }\n/* OUTPUT */\nimport React from 'react'\n\nexport const Greet = ({ name }) =\u003e \u003cspan\u003eHi {name}\u003c/span\u003e\n```\n\n### remove-react-default-props\n\nRemove use of React defaultProps.\n\n```jsx\n/* INPUT */\nimport React from 'react'\n\nexport const Greet = ({ name }) =\u003e \u003cspan\u003eHi {name}\u003c/span\u003e\nGreet.defaultProps = { name: 'Stranger' }\n/* OUTPUT */\nimport React from 'react'\n\nexport const Greet = ({ name }) =\u003e \u003cspan\u003eHi {name}\u003c/span\u003e\n```\n\n### sort-jsx-props\n\nSort props of JSX Components alphabetically.\n\n```jsx\n/* INPUT */\n\u003cMusic zootWoman={true} rickJames={true} zapp={true} /\u003e\n\n/* OUTPUT */\n\u003cMusic rickJames={true} zapp={true} zootWoman={true} /\u003e\n```\n\n### sort-object-props\n\nSort members of Object Literals alphabetically.\n\n```js\n/* INPUT */\nconst players = { messi: true, bergkamp: true, ginola: true };\n\n/* OUTPUT */\nconst players = { bergkamp: true, ginola: true, messi: true };\n```\n\n### use-named-exports\n\nNaively convert a default export to a named export using the name of the file,\nwhich may clash with other variable names in the file. This codemod would need\nfollowing up on with ESLint and some manual fixes.\n\n```js\n/* INPUT */\n// ~/Dev/repo/src/apps/health/server.js\nexport default mount(\"/health\", app);\n\n/* OUTPUT */\n// ~/Dev/repo/src/apps/health/server.js\nexport const server = mount(\"/health\", app);\n```\n\n### use-named-imports\n\nNaively convert a default import to a named import using the original name,\nwhich may not match what the module is actually exporting. This codemod would\nneed following up on with ESLint and some manual fixes.\n\n```js\n/* INPUT */\nimport masthead from \"@sky-uk/koa-masthead\";\n\n/* OUTPUT */\nimport { masthead } from \"@sky-uk/koa-masthead\";\n```\n\n## ❓ Quick Intro To Making A Codemod\n\n1. Open [ASTExplorer][astexplorer] with the Parser set to `esprima` and\n   Transform set to `jscodeshift`.\n2. Paste some **Source** in the Top-Left Panel which you want to Transform.\n3. Edit your **Codemod** in the Bottom-Left Panel.\n\nThere will be 4 Panels:\n\n| Panel        | Purpose                                                        |\n| :----------- | :------------------------------------------------------------- |\n| Top-Left     | **Source** you want to transform                               |\n| Top-Right    | The **AST** of your **Source**                                 |\n| Bottom-Left  | Your **Codemod** Script                                        |\n| Bottom-Right | The **Result** of applying your **Codemod** to your **Source** |\n\nThe [docs for jscodeshift](https://github.com/facebook/jscodeshift) aren't\nenough and you will need to refer to ast-type [definitions] to know what is\navailable. Using [VariableDeclaration][variabledeclaration] as an example, you\ncan find all variable declarations using the PascalCase `j.VariableDeclaration`\n\n```js\nj(file.source).find(j.VariableDeclaration);\n```\n\nand create new variable declarations using the camelCase `j.variableDeclarator`.\n\n```js\nj.variableDeclaration(\"const\", [\n  j.variableDeclarator(j.identifier(fileName), exportedValue)\n]);\n```\n\nThe [VariableDeclaration][variabledeclaration] definition shows what `fields` it\ntakes, which are the arguments the `j.variableDeclarator` function takes, which\nare an `Identifier` (a variable with a name but no value), or a\n`VariableDeclarator` (a variable with a name as well as a value assigned).\n\nIf we look up the definition of [VariableDeclarator][variabledeclarator] we see\nit takes two arguments called `id` and `init`. The `id` is an identifier\n`j.identifier('varName')` and `init` is a value to initialise the variable with,\nwhich should be the AST of whatever value you want to assign. For a simple\nliteral value, that would be `j.literal('hello')`.\n\nPutting that all together you have a Hello World Codemod of:\n\n```js\nexport default (file, api) =\u003e {\n  const j = api.jscodeshift;\n\n  // Have a look in the console at what APIs are available\n  console.log({\n    jscodeshiftAPI: j,\n    fileAPI: j(file.source)\n  });\n\n  return j(file.source)\n    .find(j.Program)\n    .forEach(path =\u003e {\n      // Unwrap the AST node from this wrapper\n      const emptyFile = path.value;\n\n      // add a comment\n      const singleLineComment = j.commentLine(\" Hello World\");\n      const varName = j.identifier(\"hello\");\n      emptyFile.comments = [singleLineComment];\n\n      // add a const\n      const literalString = j.literal(\"world\");\n      const nameValuePair = j.variableDeclarator(varName, literalString);\n      const constVarStatement = j.variableDeclaration(\"const\", [nameValuePair]);\n      emptyFile.body = [constVarStatement];\n    })\n    .toSource();\n};\n```\n\nGood luck!\n\n## 🙋🏾‍♀️ Getting Help\n\n- Get help with issues by creating a\n  [Bug Report](https://github.com/JamieMason/codemods/issues/new?template=bug_report.md).\n- Discuss ideas by opening a\n  [Feature Request](https://github.com/JamieMason/codemods/issues/new?template=feature_request.md).\n\n\u003c!-- Links --\u003e\n\n[astexplorer]:\n  https://astexplorer.net/#/gist/47f549f753f541aff11c492c89ae82fa/e56b2df09a8e868c86139bc39ea631a0a725cbf6\n[definitions]: https://github.com/benjamn/ast-types/tree/master/def\n[variabledeclaration]:\n  https://github.com/benjamn/ast-types/blob/v0.11.7/def/esprima.js#L9-L13\n[variabledeclarator]:\n  https://github.com/benjamn/ast-types/blob/a7eaba5ecc79a58acb469cbbf9fe7603cec9f57e/def/core.js#L190-L194\n","funding_links":["https://github.com/sponsors/JamieMason"],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJamieMason%2Fcodemods","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJamieMason%2Fcodemods","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJamieMason%2Fcodemods/lists"}