In this chapter, let's learn to how create ESLint plugin.
First of all, put a new file as src/rules/no-literal.ts and edit it as the following:
import { Rule } from "eslint";
const rule: Rule.RuleModule = {
create: (context) => {
return {
Literal: (node) => {
context.report({
message: "😿",
node,
});
},
};
}
};
export = rule;Congrats! This is your first ESLint rule!
This is a very silly rule, which says crying cat emoji when it finds some literals(e.g. 1, 'hoge', ...).
However, it tells us various things.
- ESLint rule should implement
RuleModuleinterface- It should have
createfunction which has an argument,context
- It should have
createmethod should return an object- This object's keys represents AST node type which we are interested in (We learn the relation between AST node type and the keys later 😄)
- It's value is a function and an error message is thrown in this function
Next, let's test that this rule works.
Put another file, src/rules/no-literal.test.ts and edit:
import { RuleTester } from "eslint";
import rule from "./no-literal";
const tester = new RuleTester({ parserOptions: { ecmaVersion: 2015 } });
tester.run("no-reteral", rule, {
valid: [
{ code: `let x` },
],
invalid: [
{
code: `const x = 1;`,
errors: [{ message: "😿" }],
}
],
});And run this test code via:
$ npm testCan you see the following console output?
PASS src/rules/no-literal.test.ts
no-reteral
valid
✓ let x (29ms)
invalid
✓ const x = 1; (5ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 1.506s, estimated 2s
This code tests 2 assertions:
- If given a valid source code, your rule says nothing
- If given an invalid source code, your rules reports an error message(:crying_cat_face:)
So, let's prepare to publish our rule as an ESLint plugin.
A plugin needs an index file which tells the name of the rule module to ESLint
Put src/index.ts and edit as the following:
import noLiteral from "./rules/no-literal";
export = {
rules: {
"no-literal": noLiteral,
},
};Before executing npm publish, confirm our first plugin works within an NPM project.
Execute the following command under eslint-plugin-tutorial directory(Use yarn instead of npm if you prefer):
$ npm linkThen we can install this package via npm command.
Next, create a sample project to use our plugin.
$ cd ..
$ mkdir example-prj
$ cd example-prj
$ npm init -f
$ npm i eslint --devWe add our plugin into the sample project:
$ npm link @quramy/eslint-plugin-tutorialFinally, put .eslintrc and configure to use our plugin.
{
"plugins": ["@quramy/tutorial"],
"parserOptions": {
"ecmaVersion": 2015
},
"rules": {
"@quramy/tutorial/no-literal": 2
}
}An ESLint plugin package should have "eslint-plugin" prefix. Now, our plugin's package is named as "@quramy/eslint-plugin-tutorial" so ESLint recognises it as "@quramy/tutorial" using this naming convention.
Ok come on, run it!
$ echo "const x = 1;" | npx eslint --stdinCan you see the following ?
<text>
1:11 error 😿 @quramy/tutorial/no-literal
✖ 1 problem (1 error, 0 warnings)
- You implement
Rule.RuleModuleto create a ESLint rule - ESLint plugin NPM package should have "eslint-plugin" prefix