Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

eslint-codemod-utils

Package Overview
Dependencies
Maintainers
1
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-codemod-utils - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2

README.MD

7

package.json
{
"name": "eslint-codemod-utils",
"version": "0.0.1",
"description": "Library for managing <....>",
"version": "0.0.2",
"description": "A collection of AST helper functions for more complex ESLint rule fixes.",
"source": "lib/index.ts",

@@ -27,3 +27,4 @@ "main": "dist/index.js",

},
"typings": "dist/index.d.ts"
"typings": "dist/index.d.ts",
"readme": "# ESLint Codemod Utilities\n\n<p align=\"center\">\n <a href=\"https://github.com/DarkPurple141/eslint-codemod-utils/actions/workflows/build-test.yml\">\n <img alt=\"Github Actions Build Status\" src=\"https://img.shields.io/github/workflow/status/DarkPurple141/eslint-codemod-utils/CI%20Build%20&%20Testing?style=flat-square\"></a>\n <a href=\"https://www.npmjs.com/package/eslint-codemod-utils\">\n <img alt=\"npm version\" src=\"https://img.shields.io/npm/v/eslint-codemod-utils?style=flat-square\"></a>\n</p>\n\nThe `eslint-codemod-utils` package is a collection of AST helper functions for more complex ESLint rule fixes. See the [motivation](#Motivation) section for more information.\n\n## Installation\n\n```\npnpm add -D eslint-codemod-utils\n```\n\n```\nyarn add -D eslint-codemod-utils\n```\n\n```\nnpm i --save-dev eslint-codemod-utls\n```\n\n## How it works\n\nThe library provides a 1-1 mapping for every `estree` node type. These are all lowercase complements to the underlying type they represent;\neg. `jsxIdentifier` produces a `JSXIdentifier` node representation. These nodes all implement their own `toString` which means they recursively produce the correct string output for any valid `estree` AST.\n\nThe full API (WIP) is below. I intend to clean up some of these types to make it clearer - each helper takes in a valid `estree` node and spits out a similar, but\nslightly altered node that can be more easily stringified.\n\n```ts\nexport const importDefaultSpecifier: ({\n local,\n}: Omit<\n ImportDefaultSpecifier,\n 'type'\n>) => StringableASTNode<ImportDefaultSpecifier>\nexport const importSpecifier: ({\n imported,\n local,\n}: Omit<ImportSpecifier, 'type'>) => StringableASTNode<ImportSpecifier>\nexport const importDeclaration: ({\n specifiers,\n source,\n}: Omit<ImportDeclaration, 'type'>) => StringableASTNode<ImportDeclaration>\nexport const literal: ({\n value,\n raw,\n}: Omit<Literal, 'type'>) => StringableASTNode<Literal>\nexport const identifier: ({\n name,\n}: Omit<Identifier, 'type'>) => StringableASTNode<Identifier>\nexport const jsxIdentifier: ({\n name,\n}: Omit<JSXIdentifier, 'type'>) => StringableASTNode<JSXIdentifier>\nexport const jsxMemberExpression: ({\n object,\n property,\n}: Omit<JSXMemberExpression, 'type'>) => StringableASTNode<JSXMemberExpression>\nexport const jsxElement: ({\n openingElement,\n closingElement,\n children,\n loc,\n}: Pick<JSXElement, 'openingElement'> &\n Partial<JSXElement>) => StringableASTNode<JSXElement>\nexport const jsxSpreadAttribute: ({\n argument,\n}: Omit<JSXSpreadAttribute, 'type'>) => StringableASTNode<JSXSpreadAttribute>\nexport const jsxOpeningElement: ({\n name,\n attributes,\n selfClosing,\n leadingComments,\n}: Pick<JSXOpeningElement, 'name'> &\n Partial<JSXOpeningElement>) => StringableASTNode<JSXOpeningElement>\nexport const jsxClosingElement: ({\n name,\n}: Omit<JSXClosingElement, 'type'>) => StringableASTNode<JSXClosingElement>\nexport const jsxText: ({\n value,\n raw,\n}: Omit<JSXText, 'type'>) => StringableASTNode<JSXText>\nexport const jsxExpressionContainer: ({\n expression,\n}: Omit<\n JSXExpressionContainer,\n 'type'\n>) => StringableASTNode<JSXExpressionContainer>\nexport const jsxAttribute: ({\n name,\n value,\n}: Omit<JSXAttribute, 'type'>) => StringableASTNode<JSXAttribute>\n```\n\n## Motivation\n\nThis idea came about after wrestling with the limitations of `ESLint` rule fixes. For context, `ESLint` rules rely heavily on string based utilities to apply\nfixes to code. For example this fix which appends a semi-colon to a `Literal` (from the `ESLint` documentation website itself):\n\n```js\ncontext.report({\n node: node,\n message: 'Missing semicolon',\n fix: function (fixer) {\n return fixer.insertTextAfter(node, ';')\n },\n})\n```\n\nThis works fine if your fixes are trivial, but it works less well for more complex uses cases. As soon as you need to traverse other AST nodes and combine information for a fix, combine fixes; the simplicity of the `RuleFixer` API starts to buckle.\n\nIn codemod tools like [jscodeshift](https://github.com/facebook/jscodeshift), the AST is baked in to the way fixes are applied - rather than applying fixes your script needs to return a collection of AST nodes which are then parsed and integrated into the source. This is a little more heavy duty but it also is more resillient.\n\nThe missing piece for `ESlint` is a matching set of utilties to allow the flexibility to dive into the AST approach where and when a developer feels it is appropriate.\nThis library aims to bridge some of that gap and with some different thinking around just how powerful `ESLint` can be.\n\nFixes can then theoretically deal with more complex use cases like this:\n\n```ts\n/**\n * This is part of a fix to demonstrate changing a prop in a specific element with\n * a much more surgical approach to node manipulation.\n */\nimport {\n jsxOpeningElement,\n jsxAttribute,\n jsxIdentifier,\n} from 'eslint-codemod-utils'\n\n// ... further down the file\ncontext.report({\n node: node,\n message: 'error',\n fix(fixer) {\n // The variables 'fixed' works with the estree AST to create\n // its own representation which can easily be stringified\n const fixed = jsxOpeningElement({\n name: node.name,\n selfClosing: node.selfClosing,\n attributes: node.attributes.map((attr) => {\n if (attr.type === 'JSXAttribute' && attr.name.name === 'open') {\n const internal = jsxAttribute({\n // estree nodes are spread into the util with no issues\n ...attr,\n // others are recreated or re-mapped\n name: jsxIdentifier({\n ...attr.name,\n name: 'isOpen',\n }),\n })\n return internal\n }\n\n return attr\n }),\n })\n\n return fixer.replaceText(node, fixed.toString())\n },\n})\n```\n"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc