Recently our development team decided to enforce the role for function naming. Meaning, all function name should start with the prefix defined in the eslint rule.
Instead of giving some random names to the function, strict developers follow some pre-defined conventions.
Example:
<button onclick=”someFunction()”>Login</button>
function someFunction() {}
<button onclick=”onLogin()”>Login</button>
function onLogin() {}
In the HTML button click, we can give any name we want. but when we read the code, the second function makes more sense. Let’s write a plugin that will warn us about wrong function naming.
JavaScript Naming Convention Best Practices
Boolean: is, are, has
Events: init, pre, on, post
verb as a prefix: get, set, post, put, push, apply, calculate, compute, to, etc.
We’ll be using eslint for this project.
ESLint Introduction:
ESLint statically analyzes your code to quickly find problems. ESLint is built into most text editors and you can run ESLint as part of your continuous integration pipeline.
Definition referred from eslint official site, Check more details about ESlint here
Prerequisite:
- Make sure you have installed the latest Node.js ( Download link )
- Basic knowledge of javascript, eslint
- Code editor (vs code)
There are 2 sections to this article in the
Section 1. We’ll be creating a Node.js project and setup eslint for it. If you have already created a project and eslint setup. you can skip this section and directly jump into section 2.
Section 2. We’ll create an eslint plugin and use that in the project.
Section 1: Setup Node.js project
Step 1:
Open the terminal and run the following command
mkdir my-lint //creating directory
cd my-lint
Step 2:
Initialize the Node.js project using the following command from the terminal
npm init
My package.json looks like this.
package.json:
{
"name": "my-lint",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Step 3:
It’s time to add ESLint dependencies
npm install -D eslint
Add eslint script to the package.json
{
"name": "my-lint",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "eslint src/**/*.js"
},
"devDependencies": {
"eslint": "^7.21.0"
},
"author": "",
"license": "ISC"
}
Step 4:
Next, We have to create a .eslintrc.js with the following configuration - this is similar to what you already do in your apps:
module.exports = {
parserOptions: {
ecmaVersion: 2018,
},
extends: ["eslint:recommended"],
plugins: [],
rules: {},
};
Step 5:
Create src and packages
directories in the root directory.
Create a src/index.js file inside the src directory and add the following code to it.
index.js
const someFunction = () => {
console.log("Hello World");
};
someFunction();
You can run the npm run lint or yarn lint to check eslint working or not.
So far we have created the Node.js project and setup eslint for it.
Section 2: Create eslint plugin
An ESLint rule contains 2 main parts:
- meta: an object where we will specify the usage of our rule.
- create: a function that will return an object with all the methods that ESLint will use to parse our statement. Each method returned is an AST(Abstract Syntax Tree) node.
NOTE: Plugin should follow name format of
eslint-plugin-<plugin-name>
Let’s get started…
Step 1:
Create a eslint
directory in your packages directory.
Run the following command in your terminal
cd packages/eslint
npm init // I'm giving project name to eslint-plugin-my-lint
Step 2:
Create an index.js file inside the packages/eslint directory.
const {onFuncPrefixMatchingCreate}= require("./funcPrefixMatching");
module.exports = {
rules: {
"func-prefix-matching": {
create: onFuncPrefixMatchingCreate,
},
},
};
Don’t worry about funcPrefixMatching import will be creating that in the next step.
Step 3:
Create a javascript file called funcPrefixMatching.js in your packages/eslint directory, put the below code in it:
const rulePrefix = ["is", "pre", "on", "post", "get", "set"];
const isValidName = (name, { prefix, exclude }) => {
const isValid = (prefix) => name.indexOf(prefix) === 0;
return exclude.some(isValid) || prefix.some(isValid);
};
const onFuncPrefixMatchingCreate = (context) => {
const { options } = context;
const {include = [], exclude = [] } = options[0]||{};
return {
Identifier: (node) => {
if (node.parent.init &&
node.parent.init.type === "ArrowFunctionExpression"
// You can add more checks here
) {
const { name } = node;
const allPrefix = [...include, ...rulePrefix].sort();
// Sorting is optional
if (!isValidName(name, { prefix: allPrefix, exclude })) {
context.report(node, `${name} should start with ${allPrefix.join(", ")}.`);
}
}
},
};
};
module.exports = { onFuncPrefixMatchingCreate };
Step 4:
It’s time to add our ESLint plugin to the dependencies
npm i file:packages/eslint -D
Step 5:
Update .eslintrc.js
module.exports = {
parserOptions: {
ecmaVersion: 2018,
},
extends: ["eslint:recommended"],
plugins: ["my-lint"],
rules: {
"my-lint/func-prefix-matching":
[ 1, { include: [], exclude: [] } ]
// We can include or exclude prefix
// You can add more option here like message, ignore case etc.
},
};
Step 6:
Time to check our plugin.
Custom prefix
module.exports = {
parserOptions: {
ecmaVersion: 2018,
},
extends: ["eslint:recommended"],
plugins: ["my-lint"],
rules: {
"my-lint/func-prefix-matching":
[ 1, {
include: ["to"],
exclude: ["excludeSomeFunction"],
message: ""
}
]
},
};
index.js
// Custom include
const toSomeFunction = () => {
console.log("Hello");
};
// Custom exclude
const excludeSomeFunction = () => {
console.log("Hello");
};
toSomeFunction();
excludeSomeFunction();
Working without error. 😎
Repo: func-prefix-matching
Got any questions or additional? please leave a comment.
Thank you for reading 😊
Must Read If you haven't
React redux best practice to reduce code
Rahul Sharma ・ May 3 '22
How to cancel Javascript API request with AbortController
Rahul Sharma ・ Apr 9 '22
13 Typescript Utility: A Cheat Sheet for Developer
Rahul Sharma ・ Apr 2 '22
How to solve REST API routing problem with decorators?
Rahul Sharma ・ Mar 23 '22
3 steps to create custom state management library with React Hooks and Context API
Rahul Sharma ・ Mar 15 '22
Catch me on
Youtube Github LinkedIn Medium Stackblitz Hashnode HackerNoon
Top comments (2)
Hi. What about types and TypeScript for plugin creation? Does it have any type declaration?
Figured out.