Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/futpib/eslint-template-visitor
Simplify eslint rules by visiting templates
https://github.com/futpib/eslint-template-visitor
Last synced: 6 days ago
JSON representation
Simplify eslint rules by visiting templates
- Host: GitHub
- URL: https://github.com/futpib/eslint-template-visitor
- Owner: futpib
- Created: 2019-04-20T11:51:16.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2023-01-06T05:57:12.000Z (almost 2 years ago)
- Last Synced: 2024-09-29T12:46:27.167Z (about 2 months ago)
- Language: JavaScript
- Homepage:
- Size: 586 KB
- Stars: 20
- Watchers: 3
- Forks: 3
- Open Issues: 10
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# ESLint Template Visitor
[![Build Status](https://travis-ci.org/futpib/eslint-template-visitor.svg?branch=master)](https://travis-ci.org/futpib/eslint-template-visitor) [![Coverage Status](https://coveralls.io/repos/github/futpib/eslint-template-visitor/badge.svg?branch=master)](https://coveralls.io/github/futpib/eslint-template-visitor?branch=master)Simplify eslint rules by visiting templates
## Install
```
npm install eslint-template-visitor# or
yarn add eslint-template-visitor
```## Showcase
```diff
+const eslintTemplateVisitor = require('eslint-template-visitor');
+
+const templates = eslintTemplateVisitor();
+
+const objectVariable = templates.variable();
+const argumentsVariable = templates.spreadVariable();
+
+const substrCallTemplate = templates.template`${objectVariable}.substr(${argumentsVariable})`;const create = context => {
const sourceCode = context.getSourceCode();- return {
- CallExpression(node) {
- if (node.callee.type !== 'MemberExpression'
- || node.callee.property.type !== 'Identifier'
- || node.callee.property.name !== 'substr'
- ) {
- return;
- }
-
- const objectNode = node.callee.object;
+ return templates.visitor({
+ [substrCallTemplate](node) {
+ const objectNode = substrCallTemplate.context.getMatch(objectVariable);
+ const argumentNodes = substrCallTemplate.context.getMatch(argumentsVariable);const problem = {
node,
message: 'Prefer `String#slice()` over `String#substr()`.',
};- const canFix = node.arguments.length === 0;
+ const canFix = argumentNodes.length === 0;if (canFix) {
problem.fix = fixer => fixer.replaceText(node, sourceCode.getText(objectNode) + '.slice()');
}context.report(problem);
},
- };
+ });
};
```See [examples](https://github.com/futpib/eslint-template-visitor/tree/master/examples) for more.
## API
### `eslintTemplateVisitor(options?)`
Craete a template visitor.
Example:
```js
const eslintTemplateVisitor = require('eslint-template-visitor');const templates = eslintTemplateVisitor();
```#### `options`
Type: `object`
##### `parserOptions`
Options for the template parser. Passed down to [`@babel/eslint-parser`](https://github.com/babel/@babel/eslint-parser#additional-parser-configuration).
Example:
```js
const templates = eslintTemplateVisitor({
parserOptions: {
ecmaVersion: 2018,
},
});
```### `templates.variable()`
Create a variable to be used in a template. Such a variable can match exactly one AST node.
### `templates.spreadVariable()`
Create a spread variable. Spread variable can match an array of AST nodes.
This is useful for matching a number of arguments in a call or a number of statements in a block.
### `templates.variableDeclarationVariable()`
Create a variable declaration variable. Variable declaration variable can match any type of variable declaration node.
This is useful for matching any variable declaration, be it `const`, `let` or `var`.
Use it in place of a variable declaration keyword:
```js
const variableDeclarationVariable = templates.variableDeclarationVariable();const template = templates.template`() => {
${variableDeclarationVariable} x = y;
}`;
```### `templates.template` tag
Creates a template possibly containing variables.
Example:
```js
const objectVariable = templates.variable();
const argumentsVariable = templates.spreadVariable();const substrCallTemplate = templates.template`${objectVariable}.substr(${argumentsVariable})`;
const create = () => templates.visitor({
[substrCallTemplate](node) {
// `node` here is the matching `.substr` call (i.e. `CallExpression`)
}
});
```### `templates.visitor({ /* visitors */ })`
Used to merge template visitors with [common ESLint visitors](https://eslint.org/docs/developer-guide/selectors#listening-for-selectors-in-rules).
Example:
```js
const create = () => templates.visitor({
[substrCallTemplate](node) {
// Template visitor
},FunctionDeclaration(node) {
// Simple node type visitor
},'IfStatement > BlockStatement'(node) {
// ESLint selector visitor
},
});
```### `template.context`
A template match context. This property is defined only within a visitor call (in other words, only when working on a matching node).
Example:
```js
const create = () => templates.visitor({
[substrCallTemplate](node) {
// `substrCallTemplate.context` can be used here
},FunctionDeclaration(node) {
// `substrCallTemplate.context` is not defined here, and it does not make sense to use it here,
// since we `substrCallTemplate` did not match an AST node.
},
});
```#### `template.context.getMatch(variable)`
Used to get a match for a variable.
Example:
```js
const objectVariable = templates.variable();
const argumentsVariable = templates.spreadVariable();const substrCallTemplate = templates.template`${objectVariable}.substr(${argumentsVariable})`;
const create = () => templates.visitor({
[substrCallTemplate](node) {
const objectNode = substrCallTemplate.context.getMatch(objectVariable);// For example, let's check if `objectNode` is an `Identifier`: `objectNode.type === 'Identifier'`
const argumentNodes = substrCallTemplate.context.getMatch(argumentsVariable);
// `Array.isArray(argumentNodes) === true`
},
});
```### `template.narrow(selector, targetMatchIndex = 0)`
Narrow the template to a part of the AST matching the selector.
Sometimes you can not define a wanted template at the top level due to JS syntax limitations.
For example, you can't have `await` or `yield` at the top level of a script.Use a wrapper function in the template and then `narrow` it to a wanted AST node:
```js
const template = templates.template`
async () => { await 1; }
`.narrow('BlockStatement > :has(AwaitExpression)');
```The `template` above is equivalent to this:
```js
const template = templates.template`await 1`;
```Except the latter can not be defined directly due to [`espree` limitations](https://github.com/eslint/espree/issues/409).