@automattic/eslint-plugin-wpvip 0.5.6 → 0.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +3 -16
- package/README.md +28 -14
- package/package.json +10 -5
- package/prettierrc.js +8 -1
- package/rules/README.md +12 -12
- package/utils/is-package-installed.js +17 -1
package/CONTRIBUTING.md
CHANGED
|
@@ -1,22 +1,9 @@
|
|
|
1
|
-
# Contributing
|
|
1
|
+
# Contributing
|
|
2
2
|
|
|
3
3
|
## Getting Started
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
The rules for this shared config are declared in [index.js](./index.js) and are automatically applied to the code in this repo.
|
|
5
|
+
This repo provides custom ESLint rules (in `./rules`) and configs (`./configs`). Generally speaking, any change is welcome for discussion, but keep in mind that these rules and configs are used across all of our projects, so they need to be practical and flexible.
|
|
8
6
|
|
|
9
7
|
## Automated Testing
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
When you modify the rules, please add cases to the following files:
|
|
14
|
-
|
|
15
|
-
* `__fixtures__/**/allowed.js` -- Syntax that should be allowed according to the rule(s) affected by your proposed change
|
|
16
|
-
* `__fixtures__/**/disallowed.js` -- Syntax that should *NOT* be allowed according to the rule(s) affected by your proposed change
|
|
17
|
-
|
|
18
|
-
After changing the rules or the `disallowed` fixture, run the following to update the snapshot of jest errors found:
|
|
19
|
-
|
|
20
|
-
`npm run update-snapshot`
|
|
21
|
-
|
|
22
|
-
...and commit the change to the snapshot file in your branch / PR.
|
|
9
|
+
This repo lints itself! Try to add code in `__fixtures__` that will produce errors, confirm that the errors are caught, then run `npm run jest:update-snapshot` to expect the errors.
|
package/README.md
CHANGED
|
@@ -18,9 +18,7 @@ Create an `.eslintrc.js` file. **Note:** The `init` file allows you to avoid ins
|
|
|
18
18
|
require( '@automattic/eslint-plugin-wpvip/init' );
|
|
19
19
|
|
|
20
20
|
module.exports = {
|
|
21
|
-
extends: [
|
|
22
|
-
'plugin:@automattic/wpvip/recommended',
|
|
23
|
-
],
|
|
21
|
+
extends: [ 'plugin:@automattic/wpvip/recommended' ],
|
|
24
22
|
root: true,
|
|
25
23
|
};
|
|
26
24
|
```
|
|
@@ -29,6 +27,24 @@ And that's it! It works automatically with most Babel and TypeScript projects. C
|
|
|
29
27
|
|
|
30
28
|
You may also wish to define an `.eslintignore` file if there are files or paths that you do not want to lint.
|
|
31
29
|
|
|
30
|
+
Package scripts can be useful to run linting and formatting commands automatically. Here are some suggested scripts for your project's `package.json`—only copy the ones that are useful to you. The `cmd:` scripts help you compose commands without repeating verbose CLI arguments.
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"scripts": {
|
|
35
|
+
"cmd:format": "prettier '**/*.(js|json|jsx|md|ts|tsx|yml|yaml)'",
|
|
36
|
+
"cmd:lint": "eslint --ext 'js,jsx,ts,tsx'",
|
|
37
|
+
"format": "npm run cmd:format -- --write",
|
|
38
|
+
"format:check": "npm run cmd:format -- --check",
|
|
39
|
+
"lint": "npm run cmd:lint .",
|
|
40
|
+
"lint:fix": "npm run cmd:lint . -- --fix",
|
|
41
|
+
"lint:ignore-warnings": "npm run cmd:lint . -- --quiet"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Note:** ESLint automatically ignores files listed in `.eslintignore` or you can target `.gitignore` using `--ignore-path`. Similarly, Prettier automatically ignores files listed in `.prettierignore` or you can target `.gitignore` using `--ignore-path`.
|
|
47
|
+
|
|
32
48
|
## Recommended config
|
|
33
49
|
|
|
34
50
|
The "recommended" config includes rules for JavaScript, TypeScript, Jest, and React, including rules related to formatting and white space. It is intended to be strict! Opinionated defaults keep our codebases consistent and reduce the friction we experience when context-switching between projects.
|
|
@@ -41,9 +57,9 @@ module.exports = {
|
|
|
41
57
|
'plugin:@automattic/wpvip/javascript',
|
|
42
58
|
'plugin:@automattic/wpvip/typescript', // when "typescript" is installed
|
|
43
59
|
'plugin:@automattic/wpvip/formatting',
|
|
44
|
-
'plugin:@automattic/wpvip/testing',
|
|
45
|
-
'plugin:@automattic/wpvip/react',
|
|
46
|
-
'plugin:@automattic/wpvip/prettier',
|
|
60
|
+
'plugin:@automattic/wpvip/testing', // when "jest" is installed
|
|
61
|
+
'plugin:@automattic/wpvip/react', // when "react" is installed
|
|
62
|
+
'plugin:@automattic/wpvip/prettier', // when "prettier" is installed
|
|
47
63
|
],
|
|
48
64
|
};
|
|
49
65
|
```
|
|
@@ -66,16 +82,17 @@ This repo also provides a Prettier config, which you can use with the following
|
|
|
66
82
|
|
|
67
83
|
For maximum benefit, see [Prettier's documentation on enabling format-on-save in your editor](https://prettier.io/docs/en/editors.html). This enables you to concentrate on coding while Prettier handles formatting.
|
|
68
84
|
|
|
85
|
+
### Editorconfig
|
|
86
|
+
|
|
87
|
+
[Editorconfig](https://editorconfig.org/) provides additional formatting rules and works well with Prettier. Copy the [`.editorconfig` file](./.editorconfig) from this repo into your project.
|
|
88
|
+
|
|
69
89
|
## CLI
|
|
70
90
|
|
|
71
91
|
The `cli` config allows certain behaviors that are usually against best practice but are useful in a codebase that produces a CLI tool:
|
|
72
92
|
|
|
73
93
|
```js
|
|
74
94
|
module.exports = {
|
|
75
|
-
extends: [
|
|
76
|
-
'plugin:@automattic/wpvip/recommended',
|
|
77
|
-
'plugin:@automattic/wpvip/cli',
|
|
78
|
-
],
|
|
95
|
+
extends: [ 'plugin:@automattic/wpvip/recommended', 'plugin:@automattic/wpvip/cli' ],
|
|
79
96
|
};
|
|
80
97
|
```
|
|
81
98
|
|
|
@@ -93,10 +110,7 @@ JSDoc is considered optional, especially compared to better alternatives like Ty
|
|
|
93
110
|
|
|
94
111
|
```js
|
|
95
112
|
module.exports = {
|
|
96
|
-
extends: [
|
|
97
|
-
'plugin:@automattic/wpvip/recommended',
|
|
98
|
-
'plugin:@automattic/wpvip/jsdoc',
|
|
99
|
-
],
|
|
113
|
+
extends: [ 'plugin:@automattic/wpvip/recommended', 'plugin:@automattic/wpvip/jsdoc' ],
|
|
100
114
|
};
|
|
101
115
|
```
|
|
102
116
|
|
package/package.json
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/eslint-plugin-wpvip",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.8",
|
|
4
4
|
"description": "ESLint plugin for internal WordPress VIP projects",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"check-types": "tsc __tests__/**/*.ts",
|
|
8
|
-
"format": "prettier --ignore-path .gitignore
|
|
9
|
-
"jest": "npm run link-plugin && jest",
|
|
10
|
-
"
|
|
8
|
+
"cmd:format": "prettier --ignore-path .gitignore '**/*.(js|json|jsx|md|ts|tsx|yml|yaml)'",
|
|
9
|
+
"cmd:jest": "npm run link-plugin && jest",
|
|
10
|
+
"cmd:lint": "npm run link-plugin && eslint --ext 'js,jsx,ts,tsx'",
|
|
11
|
+
"format": "npm run cmd:format -- --write",
|
|
12
|
+
"format:check": "npm run cmd:format -- --check",
|
|
13
|
+
"jest": "npm run cmd:jest",
|
|
14
|
+
"jest:update-snapshot": "npm run cmd:jest -- --updateSnapshot",
|
|
11
15
|
"link-plugin": "mkdir -p ./node_modules/@automattic; ln -fns $(pwd) ./node_modules/@automattic/eslint-plugin-wpvip",
|
|
12
|
-
"lint": "npm run
|
|
16
|
+
"lint": "npm run cmd:lint .",
|
|
17
|
+
"lint:fix": "npm run cmd:lint . -- --fix",
|
|
13
18
|
"test": "npm run jest"
|
|
14
19
|
},
|
|
15
20
|
"repository": {
|
package/prettierrc.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
arrowParens: 'avoid',
|
|
3
3
|
bracketSpacing: true,
|
|
4
|
-
jsxBracketSameLine: false,
|
|
5
4
|
parenSpacing: true,
|
|
6
5
|
printWidth: 100,
|
|
7
6
|
semi: true,
|
|
8
7
|
singleQuote: true,
|
|
9
8
|
trailingComma: 'es5',
|
|
10
9
|
useTabs: true,
|
|
10
|
+
overrides: [
|
|
11
|
+
{
|
|
12
|
+
files: [ '*.json', '*.yml', '*.yaml' ],
|
|
13
|
+
options: {
|
|
14
|
+
useTabs: false,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
],
|
|
11
18
|
};
|
package/rules/README.md
CHANGED
|
@@ -8,29 +8,29 @@ If you want to await a collection of tasks run in series (which is rarely the ca
|
|
|
8
8
|
|
|
9
9
|
```js
|
|
10
10
|
async function* doTasks() {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
let i = 0;
|
|
12
|
+
while ( i < 10 ) {
|
|
13
|
+
yield i++;
|
|
14
|
+
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
for await (const count of doTasks()) {
|
|
18
|
-
console.log(count);
|
|
17
|
+
for await ( const count of doTasks() ) {
|
|
18
|
+
console.log( count );
|
|
19
19
|
}
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
### The problem
|
|
23
23
|
|
|
24
|
-
`Array.prototype.forEach` is not designed for async/await/promises. Even if the function passed to `.forEach` is `async`, each iteration does not `await` the result.
|
|
24
|
+
`Array.prototype.forEach` is not designed for async/await/promises. Even if the function passed to `.forEach` is `async`, each iteration does not `await` the result.
|
|
25
25
|
|
|
26
26
|
```js
|
|
27
|
-
const letters = ['a', 'b', 'c'];
|
|
27
|
+
const letters = [ 'a', 'b', 'c' ];
|
|
28
28
|
|
|
29
|
-
letters.forEach(async letter => {
|
|
30
|
-
|
|
31
|
-
});
|
|
29
|
+
letters.forEach( async letter => {
|
|
30
|
+
await processLetter( letter );
|
|
31
|
+
} );
|
|
32
32
|
|
|
33
|
-
console.log('done! but not really');
|
|
33
|
+
console.log( 'done! but not really' );
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
In the example above, `'done! but not really'` is logged before the promises returned by `processLetter` have resolved. This is because the array is iterated immediately and execution proceeds without awaiting promise resolution.
|
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
const debugLog = require( './debug-log' );
|
|
2
2
|
const findPackageJson = require( 'find-package-json' );
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// Get a list of all package.json files in the current directory tree, ascending
|
|
5
|
+
// up the tree from the current directory. Note that this code behaves differently
|
|
6
|
+
// when it is installed as a package vs. when we are linting the code in this repo.
|
|
7
|
+
//
|
|
8
|
+
// When installed as a package, the current directory is inside node_modules and is
|
|
9
|
+
// not the "package root" as we are thinking about it. In this case, we need to ignore
|
|
10
|
+
// all package.json files that are inside node_modules directories.
|
|
11
|
+
//
|
|
12
|
+
// When we are linting the code in this repo, the current directory is not inside
|
|
13
|
+
// node_modules and the first found "package.json" is the "package root."
|
|
14
|
+
//
|
|
15
|
+
// This problem is basically impossible to solve for all edge cases (like someone who
|
|
16
|
+
// runs `npm run lint` from inside "node_modules") but this code should work for
|
|
17
|
+
// most cases.
|
|
18
|
+
const packages = [ ...findPackageJson( __dirname ) ];
|
|
19
|
+
const parent =
|
|
20
|
+
packages.find( pkg => ! pkg.__path.includes( '/node_modules/' ) ) || packages.pop() || {};
|
|
5
21
|
|
|
6
22
|
debugLog( `Found package.json: ${ parent.__path || 'none' }` );
|
|
7
23
|
|