@putout/eslint 1.0.0
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/LICENSE +21 -0
- package/README.md +72 -0
- package/lib/eslint.js +131 -0
- package/lib/get-eslint.mjs +23 -0
- package/lib/simple-import.js +7 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) coderaiser
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# @putout/eslint [![NPM version][NPMIMGURL]][NPMURL]
|
|
2
|
+
|
|
3
|
+
[NPMIMGURL]: https://img.shields.io/npm/v/@putout/eslint.svg?style=flat&longCache=true
|
|
4
|
+
[NPMURL]: https://npmjs.org/package/@putout/eslint "npm"
|
|
5
|
+
|
|
6
|
+
Wrapper that simplifies [**ESLint**](https://eslint.org/) API and makes it compatible with π[**Putout**](https://github.com/coderaiser/putout).
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
npm i @putout/eslint
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## API
|
|
15
|
+
|
|
16
|
+
**ESLint** begins his work as a formatter when π**Putout** done his transformations. That's why it used a lot in different parts of application, for testing purpose and using **API** in a simplest possible way. You can access it with:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
import eslint from '@putout/eslint';
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
To use it simply write:
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
const [source, places] = await eslint({
|
|
26
|
+
name: 'hello.js',
|
|
27
|
+
code: `const t = 'hi'\n`,
|
|
28
|
+
fix: false,
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Isn't it looks similar to π**Putout** way? It definitely is! But... It has a couple differences you should remember:
|
|
33
|
+
|
|
34
|
+
- βοΈ *[π**Putout** returns object with `code` and `places` properties](https://github.com/coderaiser/putout#plugins).*
|
|
35
|
+
- βοΈ ***ESLint** has a `name` property that is used to calculate configuration file.*
|
|
36
|
+
|
|
37
|
+
And you can even override any of **ESLint** βοΈ options with help of `config` property:
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
const [source, places] = await eslint({
|
|
41
|
+
name: 'hello.js',
|
|
42
|
+
code: `const t = 'hi'\n`,
|
|
43
|
+
fix: false,
|
|
44
|
+
config: {
|
|
45
|
+
extends: [
|
|
46
|
+
'plugin:putout/recommended',
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
If you want to apply π**Putout** transformations using `putout/putout` **ESLint** rule, enable π**Putout** with the same called flag lowercased:
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
const [source, places] = await eslint({
|
|
56
|
+
name: 'hello.js',
|
|
57
|
+
code: `const t = 'hi'\n`,
|
|
58
|
+
fix: true,
|
|
59
|
+
putout: true,
|
|
60
|
+
config: {
|
|
61
|
+
extends: [
|
|
62
|
+
'plugin:putout/recommended',
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
It is disabled by default, because **ESLint** always runs after π**Putout** transformations, so there is no need to traverse tree again.
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
MIT
|
package/lib/eslint.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const {simpleImport} = require('./simple-import.js');
|
|
4
|
+
const tryToCatch = require('try-to-catch');
|
|
5
|
+
|
|
6
|
+
const {keys} = Object;
|
|
7
|
+
const eslintId = ' (eslint)';
|
|
8
|
+
const overrideConfigFile = process.env.ESLINT_CONFIG_FILE;
|
|
9
|
+
|
|
10
|
+
const noConfigFound = (config, configError) => {
|
|
11
|
+
if (configError && configError.messageTemplate === 'no-config-found')
|
|
12
|
+
return true;
|
|
13
|
+
|
|
14
|
+
if (configError)
|
|
15
|
+
return false;
|
|
16
|
+
|
|
17
|
+
if (!keys(config.rules).length)
|
|
18
|
+
return true;
|
|
19
|
+
|
|
20
|
+
return false;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const cutNewLine = ({message}) => ({
|
|
24
|
+
message: message.replace(/\n.*/, ''),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
module.exports = async ({name, code, fix, config, putout = false}) => {
|
|
28
|
+
const noChanges = [
|
|
29
|
+
code,
|
|
30
|
+
[],
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const [, ESLint] = await tryToCatch(simpleImport, './get-eslint.mjs');
|
|
34
|
+
|
|
35
|
+
if (!ESLint)
|
|
36
|
+
return noChanges;
|
|
37
|
+
|
|
38
|
+
const {getESLint} = ESLint;
|
|
39
|
+
const [eslintError, eslint] = await tryToCatch(getESLint, {
|
|
40
|
+
fix,
|
|
41
|
+
config,
|
|
42
|
+
overrideConfigFile,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (eslintError)
|
|
46
|
+
return [
|
|
47
|
+
code,
|
|
48
|
+
[convertToPlace(cutNewLine(eslintError))],
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const [configError, finalConfig] = await tryToCatch(eslint.calculateConfigForFile, name);
|
|
52
|
+
|
|
53
|
+
if (noConfigFound(finalConfig, configError))
|
|
54
|
+
return noChanges;
|
|
55
|
+
|
|
56
|
+
if (configError) {
|
|
57
|
+
return [
|
|
58
|
+
code,
|
|
59
|
+
[convertToPlace(parseError(configError))],
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
!putout && disablePutout(finalConfig);
|
|
64
|
+
|
|
65
|
+
// that's right, we disabled "putout" rules in "config"
|
|
66
|
+
// and now it located in eslint's cache
|
|
67
|
+
const results = await eslint.lintText(code, {
|
|
68
|
+
filePath: name,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
if (!results.length)
|
|
72
|
+
return noChanges;
|
|
73
|
+
|
|
74
|
+
const [report] = results;
|
|
75
|
+
const {output} = report;
|
|
76
|
+
const places = report.messages.map(convertToPlace);
|
|
77
|
+
|
|
78
|
+
return [
|
|
79
|
+
output || code,
|
|
80
|
+
places,
|
|
81
|
+
];
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
module.exports._noConfigFound = noConfigFound;
|
|
85
|
+
|
|
86
|
+
const parseRule = (rule) => rule || 'parser';
|
|
87
|
+
|
|
88
|
+
module.exports.convertToPlace = convertToPlace;
|
|
89
|
+
function convertToPlace({ruleId = 'parser', message, line = 0, column = 0}) {
|
|
90
|
+
const rule = `${parseRule(ruleId)}${eslintId}`;
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
rule,
|
|
94
|
+
message: replaceControlChars(message),
|
|
95
|
+
position: {
|
|
96
|
+
line,
|
|
97
|
+
column,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function disablePutout(config) {
|
|
103
|
+
if (!config.rules['putout/putout'])
|
|
104
|
+
return;
|
|
105
|
+
|
|
106
|
+
config.rules['putout/putout'] = 'off';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// when eslint config got errors, table formatter used for reporting
|
|
110
|
+
// can't show control characters and crash
|
|
111
|
+
//
|
|
112
|
+
// https://stackoverflow.com/questions/26741455/how-to-remove-control-characters-from-string
|
|
113
|
+
const replaceControlChars = (a) => a.replace(/[\x00-\x1F]/g, '. ');
|
|
114
|
+
|
|
115
|
+
function parseError(e) {
|
|
116
|
+
const {
|
|
117
|
+
messageTemplate,
|
|
118
|
+
messageData,
|
|
119
|
+
message,
|
|
120
|
+
} = e;
|
|
121
|
+
|
|
122
|
+
if (messageTemplate !== 'plugin-missing')
|
|
123
|
+
return {
|
|
124
|
+
message: replaceControlChars(message),
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
message: `Plugin missing: ${messageData.pluginName}`,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {ESLint} from 'eslint';
|
|
2
|
+
|
|
3
|
+
export const getESLint = ({fix, config, overrideConfigFile, ESLintOverride = ESLint}) => {
|
|
4
|
+
const eslint = new ESLintOverride({
|
|
5
|
+
fix,
|
|
6
|
+
overrideConfig: {
|
|
7
|
+
ignorePatterns: [
|
|
8
|
+
'!.*',
|
|
9
|
+
],
|
|
10
|
+
...config,
|
|
11
|
+
},
|
|
12
|
+
...overrideConfigFile && {
|
|
13
|
+
overrideConfigFile,
|
|
14
|
+
useEslintrc: false,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
calculateConfigForFile: eslint.calculateConfigForFile.bind(eslint),
|
|
20
|
+
lintText: eslint.lintText.bind(eslint),
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@putout/eslint",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "commonjs",
|
|
5
|
+
"author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
|
|
6
|
+
"description": "Wrapper that simplifies ESLint API and makes it compatible with πPutout",
|
|
7
|
+
"homepage": "https://github.com/coderaiser/putout/tree/master/packages/eslint#readme",
|
|
8
|
+
"main": "lib/eslint.js",
|
|
9
|
+
"commitType": "colon",
|
|
10
|
+
"release": false,
|
|
11
|
+
"tag": false,
|
|
12
|
+
"changelog": false,
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git://github.com/coderaiser/putout.git"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"test": "madrun test",
|
|
19
|
+
"watch:test": "madrun watch:test",
|
|
20
|
+
"lint": "madrun lint",
|
|
21
|
+
"fresh:lint": "madrun fresh:lint",
|
|
22
|
+
"lint:fresh": "madrun lint:fresh",
|
|
23
|
+
"fix:lint": "madrun fix:lint",
|
|
24
|
+
"coverage": "madrun coverage",
|
|
25
|
+
"report": "madrun report"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"try-to-catch": "^3.0.1"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"putout",
|
|
32
|
+
"eslint"
|
|
33
|
+
],
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"c8": "^7.5.0",
|
|
36
|
+
"eslint": "^8.0.1",
|
|
37
|
+
"eslint-plugin-n": "^15.2.4",
|
|
38
|
+
"eslint-plugin-putout": "^16.0.0",
|
|
39
|
+
"just-camel-case": "^4.0.2",
|
|
40
|
+
"lerna": "^5.0.0",
|
|
41
|
+
"madrun": "^9.0.0",
|
|
42
|
+
"mock-require": "^3.0.3",
|
|
43
|
+
"montag": "^1.0.0",
|
|
44
|
+
"nodemon": "^2.0.1",
|
|
45
|
+
"putout": "*",
|
|
46
|
+
"supertape": "^7.0.0",
|
|
47
|
+
"try-catch": "^3.0.0"
|
|
48
|
+
},
|
|
49
|
+
"license": "MIT",
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=16"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
}
|
|
56
|
+
}
|