redlint 1.0.0 → 1.0.2
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/ChangeLog +11 -0
- package/README.md +7 -305
- package/bin/redlint.js +3 -1
- package/lib/redlint.js +18 -29
- package/package.json +3 -19
package/ChangeLog
ADDED
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Redlint [![License][LicenseIMGURL]][LicenseURL] [![NPM version][NPMIMGURL]][NPMURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Coverage Status][CoverageIMGURL]][CoverageURL]
|
|
2
2
|
|
|
3
|
-
[NPMURL]: https://npmjs.org/package
|
|
4
|
-
[NPMIMGURL]: https://img.shields.io/npm/v
|
|
3
|
+
[NPMURL]: https://npmjs.org/package/redlint "npm"
|
|
4
|
+
[NPMIMGURL]: https://img.shields.io/npm/v/redlint.svg?style=flat&longCache=true
|
|
5
5
|
[BuildStatusURL]: https://github.com/putoutjs/printer/actions/workflows/nodejs.yml "Build Status"
|
|
6
6
|
[BuildStatusIMGURL]: https://github.com/putoutjs/printer/actions/workflows/nodejs.yml/badge.svg
|
|
7
7
|
[LicenseURL]: https://tldrlegal.com/license/mit-license "MIT License"
|
|
@@ -9,318 +9,20 @@
|
|
|
9
9
|
[CoverageURL]: https://coveralls.io/github/putoutjs/printer?branch=master
|
|
10
10
|
[CoverageIMGURL]: https://coveralls.io/repos/putoutjs/printer/badge.svg?branch=master&service=github
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- ☝️ Similar to **Recast**, but [twice faster](#speed-comparison), also simpler and easier in maintenance, since it supports only **Babel**.
|
|
15
|
-
- ☝️ As opinionated as **Prettier**, but has more user-friendly output and works directly with **AST**.
|
|
16
|
-
- ☝️ Like **ESLint** but works directly with **Babel AST**.
|
|
17
|
-
- ☝️ Easily extendable with help of [Overrides](#overrides).
|
|
18
|
-
|
|
19
|
-
Supports:
|
|
20
|
-
|
|
21
|
-
- ✅ **ES2023**;
|
|
22
|
-
- ✅ **JSX**;
|
|
23
|
-
- ✅ **TypeScript**;
|
|
24
|
-
- ✅ [**JSON**](https://github.com/coderaiser/putout/tree/master/packages/processor-json#readme);
|
|
12
|
+
Lint Filesystem with 🐊[**Putout**](https://github.com/coderaiser/putout). Creates [`.filesystem.json`](https://github.com/putoutjs/redlint/blob/master/.filesystem.json) file for further lint.
|
|
25
13
|
|
|
26
14
|
## Install
|
|
27
15
|
|
|
28
16
|
```
|
|
29
|
-
npm i
|
|
17
|
+
npm i redlint -g
|
|
30
18
|
```
|
|
31
19
|
|
|
32
|
-
##
|
|
33
|
-
|
|
34
|
-
**Printer** has first class support from 🐊**Putout** with help of [`@putout/plugin-printer`](https://github.com/coderaiser/putout/tree/master/packages/plugin-printer#putoutplugin-printer-). So install:
|
|
20
|
+
## Usage Example
|
|
35
21
|
|
|
36
22
|
```sh
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
And update `.putout.json`:
|
|
41
|
-
|
|
42
|
-
```json
|
|
43
|
-
{
|
|
44
|
-
"printer": "putout",
|
|
45
|
-
"plugins": ["printer"]
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
To benefit from it.
|
|
50
|
-
|
|
51
|
-
## Example
|
|
52
|
-
|
|
53
|
-
```js
|
|
54
|
-
const {print} = require('@putout/printer');
|
|
55
|
-
const {parse} = require('@babel/parser');
|
|
56
|
-
const ast = parse('const a = (b, c) => {const d = 5; return a;}');
|
|
57
|
-
|
|
58
|
-
print(ast);
|
|
59
|
-
// returns
|
|
60
|
-
`
|
|
61
|
-
const a = (b, c) => {
|
|
62
|
-
const d = 5;
|
|
63
|
-
return a;
|
|
64
|
-
};
|
|
65
|
-
`;
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## Overrides
|
|
69
|
-
|
|
70
|
-
When you need to extend syntax of `@putout/printer` just pass a function which receives:
|
|
71
|
-
|
|
72
|
-
- `path`, Babel Path
|
|
73
|
-
- `write`, a function to output result of printing into token array;
|
|
74
|
-
|
|
75
|
-
When `path` contains to dashes `__` and name, it is the same as: `write(path.get('right'))`, and this is
|
|
76
|
-
actually `traverse(path.get('right'))` shortened to simplify read and process.
|
|
77
|
-
|
|
78
|
-
Here is how you can override `AssignmentPattern`:
|
|
79
|
-
|
|
80
|
-
```js
|
|
81
|
-
const ast = parse('const {a = 5} = b');
|
|
82
|
-
|
|
83
|
-
print(ast, {
|
|
84
|
-
format: {
|
|
85
|
-
indent: ' ',
|
|
86
|
-
newline: '\n',
|
|
87
|
-
space: ' ',
|
|
88
|
-
splitter: '\n',
|
|
89
|
-
roundBraceOpen: '(',
|
|
90
|
-
roundBraceClose: ')',
|
|
91
|
-
quote: `'`,
|
|
92
|
-
endOfFile: '\n',
|
|
93
|
-
},
|
|
94
|
-
semantics: {
|
|
95
|
-
comments: true,
|
|
96
|
-
maxSpecifiersInOneLine: 2,
|
|
97
|
-
maxElementsInOneLine: 3,
|
|
98
|
-
maxVariablesInOneLine: 4,
|
|
99
|
-
maxPropertiesInOneLine: 2,
|
|
100
|
-
trailingComma: true,
|
|
101
|
-
},
|
|
102
|
-
visitors: {
|
|
103
|
-
AssignmentPattern(path, {print}) {
|
|
104
|
-
print('/* [hello world] */= ');
|
|
105
|
-
print('__right');
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
// returns
|
|
111
|
-
'const {a/* [hello world] */= 5} = b;\n';
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### `format`
|
|
115
|
-
|
|
116
|
-
Options related to visuals and not related to logic of output can be changed with help of `format`,
|
|
117
|
-
you can override next options:
|
|
118
|
-
|
|
119
|
-
```js
|
|
120
|
-
const overrides = {
|
|
121
|
-
format: {
|
|
122
|
-
indent: ' ',
|
|
123
|
-
newline: '\n',
|
|
124
|
-
space: ' ',
|
|
125
|
-
splitter: '\n',
|
|
126
|
-
roundBraceOpen: '(',
|
|
127
|
-
roundBraceClose: ')',
|
|
128
|
-
endOfFile: '\n',
|
|
129
|
-
},
|
|
130
|
-
};
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
- `indent` - use two spaces, tabs, or anything you want;
|
|
134
|
-
- `newline` - symbol for used for line separation;
|
|
135
|
-
- `space` - default symbol used for space character;
|
|
136
|
-
- `splitter` - mandatory symbol that used inside of statements like this:
|
|
137
|
-
- `roundBraceOpen` and `roundBraceClose` symbols to output braces in a single argument arrow function expressions: `(a) => {}`.
|
|
138
|
-
|
|
139
|
-
Default options produce:
|
|
140
|
-
|
|
141
|
-
```js
|
|
142
|
-
if (a > 3)
|
|
143
|
-
console.log('ok');
|
|
144
|
-
else
|
|
145
|
-
console.log('not ok');
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
But you can override them with:
|
|
149
|
-
|
|
150
|
-
```js
|
|
151
|
-
const overrides = {
|
|
152
|
-
format: {
|
|
153
|
-
indent: '',
|
|
154
|
-
newline: '',
|
|
155
|
-
space: '',
|
|
156
|
-
splitter: ' ',
|
|
157
|
-
},
|
|
158
|
-
};
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
And have minified code:
|
|
162
|
-
|
|
163
|
-
```
|
|
164
|
-
if(a>3)console.log('ok');else console.log('not ok');
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### Semantics
|
|
168
|
-
|
|
169
|
-
Options used to configure logic of output, similar to ESLint rules:
|
|
170
|
-
|
|
171
|
-
- ✅ `maxElementsInOneLine` - count of `ArrayExpression` and `ArrayPattern` elements placed in one line.
|
|
172
|
-
- ✅ `maxVariablesInOneLine` - count of `VariableDeclarators` in one line.
|
|
173
|
-
- ✅ `maxPropertiesInOneLine` - count of `ObjectProperties` in one line.
|
|
174
|
-
|
|
175
|
-
## Visitors API
|
|
176
|
-
|
|
177
|
-
When you want to improve support of existing visitor or extend **Printer** with a new ones, you need next base operations:
|
|
178
|
-
|
|
179
|
-
### override
|
|
180
|
-
|
|
181
|
-
When you need to override behavior of existing visitor use:
|
|
182
|
-
|
|
183
|
-
```js
|
|
184
|
-
import {
|
|
185
|
-
print,
|
|
186
|
-
visitors as v,
|
|
187
|
-
} from '@putout/printer';
|
|
188
|
-
|
|
189
|
-
print(ast, {
|
|
190
|
-
visitors: {
|
|
191
|
-
CallExpression(path, printer, semantics) {
|
|
192
|
-
const {print} = printer;
|
|
193
|
-
|
|
194
|
-
if (!path.node.goldstein)
|
|
195
|
-
return v.CallExpression(path, printer, semantics);
|
|
196
|
-
|
|
197
|
-
print('__goldstein');
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
});
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### `print`
|
|
204
|
-
|
|
205
|
-
Used in previous example `print` can be used for a couple purposes:
|
|
206
|
-
|
|
207
|
-
- to write `string`;
|
|
208
|
-
- to write `node` when `object` passed;
|
|
209
|
-
- to write `node` when `string` started with `__`;
|
|
210
|
-
|
|
211
|
-
```js
|
|
212
|
-
print(ast, {
|
|
213
|
-
visitors: {
|
|
214
|
-
AssignmentPattern(path, {print, maybe}) {
|
|
215
|
-
maybe.write.newline(path.parentPath.isCallExpression());
|
|
216
|
-
print('/* [hello world] */= ');
|
|
217
|
-
print('__right');
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
});
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
### `maybe`
|
|
224
|
-
|
|
225
|
-
When you need some condition use `maybe`. For example, to add newline only when parent node is `CallExpression` you
|
|
226
|
-
can use `maybe.write.newline(condition)`:
|
|
227
|
-
|
|
228
|
-
```js
|
|
229
|
-
print(ast, {
|
|
230
|
-
visitors: {
|
|
231
|
-
AssignmentPattern(path, {write, maybe}) {
|
|
232
|
-
maybe.write.newline(path.parentPath.isCallExpression());
|
|
233
|
-
write(' /* [hello world] */= ');
|
|
234
|
-
write('__right');
|
|
235
|
-
},
|
|
236
|
-
},
|
|
237
|
-
});
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
### `write`
|
|
241
|
-
|
|
242
|
-
When you going to output string you can use low-level function `write`:
|
|
243
|
-
|
|
244
|
-
```js
|
|
245
|
-
print(ast, {
|
|
246
|
-
visitors: {
|
|
247
|
-
BlockStatement(path, {write}) {
|
|
248
|
-
write('hello');
|
|
249
|
-
},
|
|
250
|
-
},
|
|
251
|
-
});
|
|
23
|
+
redlint
|
|
252
24
|
```
|
|
253
25
|
|
|
254
|
-
### `indent`
|
|
255
|
-
|
|
256
|
-
When you need to add indentation use `indent`, for example when you output body,
|
|
257
|
-
you need to increment indentation, and then decrement it back:
|
|
258
|
-
|
|
259
|
-
```js
|
|
260
|
-
print(ast, {
|
|
261
|
-
visitors: {
|
|
262
|
-
BlockStatement(path, {write, indent}) {
|
|
263
|
-
write('{');
|
|
264
|
-
indent.inc();
|
|
265
|
-
indent();
|
|
266
|
-
write('some;');
|
|
267
|
-
indent.dec();
|
|
268
|
-
write('{');
|
|
269
|
-
},
|
|
270
|
-
},
|
|
271
|
-
});
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### `traverse`
|
|
275
|
-
|
|
276
|
-
When you need to traverse node path, you can use `traverse`:
|
|
277
|
-
|
|
278
|
-
```js
|
|
279
|
-
print(ast, {
|
|
280
|
-
visitors: {
|
|
281
|
-
AssignmentExpression(path, {traverse}) {
|
|
282
|
-
traverse(path.get('left'));
|
|
283
|
-
},
|
|
284
|
-
},
|
|
285
|
-
});
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
This is the same as `print('__left')` but more low-level, and supports only objects.
|
|
289
|
-
|
|
290
|
-
## Speed Comparison
|
|
291
|
-
|
|
292
|
-
About speed, for file `speed.js`:
|
|
293
|
-
|
|
294
|
-
```js
|
|
295
|
-
const {readFileSync} = require('fs');
|
|
296
|
-
|
|
297
|
-
const putout = require('putout');
|
|
298
|
-
const parser = require('@babel/parser');
|
|
299
|
-
|
|
300
|
-
const code = readFileSync('./lib/tokenize/tokenize.js', 'utf8');
|
|
301
|
-
const ast = parser.parse(code);
|
|
302
|
-
|
|
303
|
-
speed('recast');
|
|
304
|
-
speed('putout');
|
|
305
|
-
|
|
306
|
-
function speed(printer) {
|
|
307
|
-
console.time(printer);
|
|
308
|
-
|
|
309
|
-
for (let i = 0; i < 1000; i++) {
|
|
310
|
-
putout(code, {
|
|
311
|
-
printer,
|
|
312
|
-
plugins: ['remove-unused-variables'],
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
console.timeEnd(printer);
|
|
317
|
-
}
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
With contents of [`tokenize.js`](https://github.com/putoutjs/printer/blob/v1.69.1/lib/tokenize/tokenize.js), we have:
|
|
321
|
-
|
|
322
|
-

|
|
323
|
-
|
|
324
26
|
## License
|
|
325
27
|
|
|
326
28
|
MIT
|
package/bin/redlint.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import {writeFile} from 'node:fs/promises';
|
|
3
3
|
import {buildTree} from '../lib/redlint.js';
|
|
4
|
+
import {lintJSON} from 'putout/lint/json';
|
|
4
5
|
|
|
6
|
+
const {stringify} = JSON;
|
|
5
7
|
const result = await buildTree(process.cwd());
|
|
6
|
-
const filesystem =
|
|
8
|
+
const filesystem = lintJSON(stringify(result));
|
|
7
9
|
|
|
8
10
|
await writeFile('.filesystem.json', filesystem);
|
package/lib/redlint.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import fastGlob from 'fast-glob';
|
|
1
|
+
import ignore from 'ignore';
|
|
2
|
+
import {opendir} from 'node:fs/promises';
|
|
4
3
|
|
|
5
|
-
const
|
|
4
|
+
const resolveName = (name, cwd) => name.replace(`${cwd}/`, '');
|
|
5
|
+
|
|
6
|
+
const ignoreList = [
|
|
6
7
|
'node_modules',
|
|
7
8
|
'coverage',
|
|
8
9
|
'.git',
|
|
@@ -10,31 +11,28 @@ const ignore = [
|
|
|
10
11
|
'fixture',
|
|
11
12
|
];
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
type: 'directory',
|
|
16
|
-
filename,
|
|
17
|
-
files: await walk(filename)
|
|
18
|
-
};
|
|
19
|
-
};
|
|
14
|
+
const ig = ignore().add(ignoreList);
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
export const buildTree = async (cwd) => ({
|
|
17
|
+
type: 'directory',
|
|
18
|
+
filename: cwd,
|
|
19
|
+
files: await walk(cwd, cwd),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
async function walk(cwd, dir, files = []) {
|
|
23
|
+
for await (const dirent of await opendir(dir)) {
|
|
25
24
|
const {path, name} = dirent;
|
|
25
|
+
const filename = `${path}/${name}`;
|
|
26
|
+
const resolved = resolveName(filename, cwd);
|
|
26
27
|
|
|
27
|
-
if (
|
|
28
|
+
if (resolved && ig.ignores(resolved))
|
|
28
29
|
continue;
|
|
29
30
|
|
|
30
|
-
const filename = `${path}/${name}`;
|
|
31
|
-
|
|
32
31
|
if (dirent.isDirectory()) {
|
|
33
|
-
debugger;
|
|
34
32
|
files.push({
|
|
35
33
|
type: 'directory',
|
|
36
34
|
filename,
|
|
37
|
-
files: await walk(filename),
|
|
35
|
+
files: await walk(cwd, filename),
|
|
38
36
|
});
|
|
39
37
|
continue;
|
|
40
38
|
}
|
|
@@ -47,12 +45,3 @@ async function walk(cwd, files = []) {
|
|
|
47
45
|
|
|
48
46
|
return files;
|
|
49
47
|
}
|
|
50
|
-
|
|
51
|
-
function isIgnored(name) {
|
|
52
|
-
for (const current of ignore) {
|
|
53
|
-
if (RegExp(current).test(name))
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return false;
|
|
58
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redlint",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
|
|
6
6
|
"description": "Lint Filesystem with 🐊Putout",
|
|
@@ -27,14 +27,8 @@
|
|
|
27
27
|
"report": "madrun report"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"@putout/operate": "^11.0.0",
|
|
33
|
-
"@putout/processor-json": "^7.0.0",
|
|
34
|
-
"fullstore": "^3.0.0",
|
|
35
|
-
"just-snake-case": "^3.2.0",
|
|
36
|
-
"parse-import-specifiers": "^1.0.1",
|
|
37
|
-
"rendy": "^4.0.0"
|
|
30
|
+
"ignore": "^5.2.4",
|
|
31
|
+
"putout": "^32.15.1"
|
|
38
32
|
},
|
|
39
33
|
"keywords": [
|
|
40
34
|
"putout",
|
|
@@ -46,16 +40,7 @@
|
|
|
46
40
|
"generate"
|
|
47
41
|
],
|
|
48
42
|
"devDependencies": {
|
|
49
|
-
"@babel/plugin-codemod-object-assign-to-object-spread": "^7.10.4",
|
|
50
|
-
"@putout/plugin-minify": "^5.0.0",
|
|
51
|
-
"@putout/plugin-redlint": "^3.0.0",
|
|
52
|
-
"@putout/plugin-promises": "^13.0.0",
|
|
53
|
-
"@putout/plugin-react-hook-form": "^4.0.0",
|
|
54
|
-
"@putout/plugin-react-hooks": "^5.0.0",
|
|
55
|
-
"acorn": "^8.8.2",
|
|
56
43
|
"c8": "^8.0.0",
|
|
57
|
-
"check-dts": "^0.7.2",
|
|
58
|
-
"escover": "^3.0.0",
|
|
59
44
|
"eslint": "^8.0.1",
|
|
60
45
|
"eslint-plugin-n": "^16.0.0",
|
|
61
46
|
"eslint-plugin-putout": "^21.0.1",
|
|
@@ -65,7 +50,6 @@
|
|
|
65
50
|
"mock-require": "^3.0.3",
|
|
66
51
|
"montag": "^1.0.0",
|
|
67
52
|
"nodemon": "^3.0.1",
|
|
68
|
-
"putout": "^32.0.4",
|
|
69
53
|
"supertape": "^8.0.0",
|
|
70
54
|
"try-catch": "^3.0.0"
|
|
71
55
|
},
|