The problem
// It is used for testing
let url = 'ceshi/dasdadaadsa'
// TODO incomplete logic, subsequent optimization
for(a of b) {
...
}
Copy the code
When we submit code, sometimes we just want to do temporary submission, or modify some fields for testing, or even we have added remarks to remind ourselves that we need to modify later, but there are still some cases that we forget
So, can we use ESLint to customize rules to validate code when we submit it
plan
Scenario 1: Find out if ESLint has a ready-made API
'no-warning-comments': [{terms: ['todo'.'Joe'].location: 'anywhere'}] // There can be no warning remarks
Copy the code
Warning if the remarks contain certain strings
attribute | value | meaning |
---|---|---|
terms | [“todo”, “fixme”, “xxx”] | Fields responsible for verification (case insensitive) |
location | start/anywhere | Check position |
The current sample
'no-warning-comments': [{terms: ['todo'.'ceshi'].location: 'start'}] // There can be no warning remarks
Copy the code
Incorrect code example
/*eslint no-warning-comments: "error"*/
function callback(err, results) {
if (err) {
console.error(err);
return;
}
// TODO
/ / zhang SAN
}
Copy the code
Error reported because todo and three fields were present
/*eslint no-warning-comments: "error"*/
function callback(err, results) {
if (err) {
console.error(err);
return;
}
// xyb TODO
}
Copy the code
The no-warning-Comments check will split up multiple words, so toDO will still hit
Correct code examples
/*eslint no-warning-comments: "error"*/
function callback(err, results) {
if (err) {
console.error(err);
return;
}
// mnbdjklmbasdbjkTODO
}
Copy the code
In this case, the value of location is start, which means that the validation starts at the beginning of the string, while the todo field appears at the end, so it is correct to pass. If you want to change the value to error, you need to change localtion to anywhere
Pass: verifies only remarks, which is different from actual requirements
Scenario 2: Customize esLint plugins
Eslint custom rules can be introduced via NPM or customized by creating a new directory rule in a project and adding its own validation logic inside ybxu.js
Again inpackage.json
Changes in thelint
Add –rulesdir./rules SRC Specifies the official way to write custom methods, pointing to your own folder
Again in.eslintrc.js
In the filerules
Add an attribute to theybxu: 1
, pay attention to what you addjs
The same name
Pass: Yarn Lint needs to be executed when it is executed. It is too different from the current script (check.js), and the above node node is the AST tree. There is no complete code directly corresponding to the node node used in the above code, so it is too troublesome to reverse build the code.
Plan 3: Quit and give up
As long as I give up fast enough that failure will never catch up with me
Option 4: Based on existingcheck.js
Now the check.js logic
Package. The json file
"husky": {
"hooks": {
"pre-commit": "lint-staged"."pre-push": "npm run push-lint"."commit-msg": "commitlint -E HUSKY_GIT_PARAMS"}},"lint-staged": {
"*.{js,css,less,sass,scss,json,md,vue}": [
"prettier --write"."node check.js"."git add"]}Copy the code
You can see that our Git commit actually executes node check.js
Check the js file
// check.js
const exec = require('child_process').exec;
const CLIEngine = require('eslint').CLIEngine;
const cli = new CLIEngine({});
function getErrorLevel(number) {
switch (number) {
case 2:
return 'error';
case 1:
return 'warn';
default:}return 'undefined';
}
let pass = 0;
// Check only js and vue code in SRC directory
exec('git diff --cached --name-only src| grep -E ".js$|.vue$"'.(error, stdout) = > {
if (stdout.length) {
const array = stdout.split('\n');
array.pop();
let index = array.indexOf('.eslintrc.js');
const results = cli.executeOnFiles(array).results;
let errorCount = 0;
let warningCount = 0;
results.forEach(result= > {
errorCount += result.errorCount;
warningCount += result.warningCount;
if (result.messages.length > 0) {
console.log('\n');
console.log(result.filePath);
result.messages.forEach(obj= > {
const level = getErrorLevel(obj.severity);
console.log(
` ${obj.line}:${obj.column} ${level} ${obj.message} ${obj.ruleId}`
);
pass = 1; }); }});if (warningCount > 0 || errorCount > 0) {
console.log(
`\n ${errorCount + warningCount} problems (${errorCount} The ${'errors'} ${warningCount} warnings)`
);
}
process.exit(pass);
}
if(error ! = =null) {
console.log(`exec error: ${error}`); }});Copy the code
Check in js
const CLIEngine = require('eslint').CLIEngine;
const cli = new CLIEngine({});
Copy the code
Use it directly through the Node API
Finally, throw in the directory data of the modified file below to obtain the verification result results
// array is the address array for modifying files
const results = cli.executeOnFiles(array).results;
Copy the code
Can we plug our custom method into the new CLIEngine({}) procedure?
I didn’t understand the official document and gave up
On second thought, in the Node environment, we also know the path to modify the code, so we can pull out the code and do the verification ourselves
Paste code directly
// check.js
const exec = require('child_process').exec;
const rf = require('fs');
const path = require('path');
const CLIEngine = require('eslint').CLIEngine;
const cli = new CLIEngine({});
function getErrorLevel(number) {
switch (number) {
case 2:
return 'error';
case 1:
return 'warn';
default:}return 'undefined';
}
let pass = 0;
// Encapsulate the method to get file contents
function read(dir) {
return new Promise((resolve, reject) = > {
rf.readFile(dir, 'utf-8'.(err, data) = > {
if (err) {
reject(err);
} else{ resolve(data); }}); }); }// Check only js and vue code in SRC directory
exec('git diff --cached --name-only src| grep -E ".js$|.vue$"'.async (error, stdout) => {
let errorCount = 0;
let warningCount = 0;
// Need to prompt warning word
const warnWordArray = ['todo'];
if (stdout.length) {
const array = stdout.split('\n');
array.pop();
const publicPath = path.resolve(__dirname); // Get the public path
let eslintData = [];
for (let srcItem of array) {
// Use path.join to join paths to solve Windows and ios compatibility problems
let eslintPath = path.join(publicPath, srcItem);
// This is done asynchronously, in case the file does not reach the bottom of the process.exit(pass); Just quit
await read(eslintPath).then(data= > {
// Concatenate the content and path into eslintData
eslintData.push({
code: String(data).split('\n'), // Each value is the number of lines in the code, subscript +1 is the number of lines
path: eslintPath
});
});
}
for (let codeData of eslintData) {
console.log('\n');
// Ensure that a module displays path only once
let isShowPath = false;
// Ensure that a module displays warn only once
let isWarn = false;
let beforeItem = ' '
codeData.code.forEach((item, line) = > {
// If the special field is found in the corresponding row
for (let warnItem of warnWordArray) {
// column is the position matching the string in question
let column = item.toLowerCase().indexOf(warnItem.toLowerCase());
// Whether to skip
let isPass = beforeItem.includes('// pass warnWord');
// If the field is hit and there is no need to skip, an error message is printed
if (column > -1 && !isPass) {
pass = 1;
isWarn = true;
if(! isShowPath) {console.log(codeData.path);
isShowPath = true;
}
// Print the error message, including the number of lines of code, the location of the code, and the specific field
console.log(` ${line + 1}:${column + 1} warn ${warnItem}Field not processed ');
warningCount += 1;
}
}
beforeItem = item
});
if(isShowPath && isWarn) {
console.log(👿 If this module code needs to be uploaded, add // pass warnWord 'at the top of the corresponding verification line); }}// let index = array.indexOf('.eslintrc.js');
const results = cli.executeOnFiles(array).results;
results.forEach(result= > {
errorCount += result.errorCount;
warningCount += result.warningCount;
if (result.messages.length > 0) {
console.log('\n');
console.log(result.filePath);
result.messages.forEach(obj= > {
const level = getErrorLevel(obj.severity);
console.log(
` ${obj.line}:${obj.column} ${level} ${obj.message} ${obj.ruleId}`
);
pass = 1; }); }});if (warningCount > 0 || errorCount > 0) {
console.log(
`\n ${errorCount + warningCount} problems (${errorCount} The ${'errors'} ${warningCount} warnings)`
);
}
process.exit(pass);
}
if(error ! = =null) {
console.log(`exec error: ${error}`); }});Copy the code
So let’s just do itnode check.js
It says gogit commit
It will eventually come to executionnode check.js
C)
Add a comment to skip verification
perfect