@utilfirst/eslint-plugin 0.1.0 → 0.1.1
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/README.md +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +46 -41
- package/package.json +17 -17
package/README.md
CHANGED
|
@@ -37,9 +37,9 @@ export default [
|
|
|
37
37
|
|
|
38
38
|
## Rules
|
|
39
39
|
|
|
40
|
-
| Rule | Description
|
|
41
|
-
| ------------------------------------------------------------------ |
|
|
42
|
-
| [`consistent-blank-lines`](./docs/rules/consistent-blank-lines.md) | Insert blank lines between statement-list and JSXChild items that start new
|
|
40
|
+
| Rule | Description | Fixable |
|
|
41
|
+
| ------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | ------- |
|
|
42
|
+
| [`consistent-blank-lines`](./docs/rules/consistent-blank-lines.md) | Insert blank lines between statement-list and JSXChild items that start a new thought | yes |
|
|
43
43
|
|
|
44
44
|
## Develop
|
|
45
45
|
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { TSESLint } from "@typescript-eslint/utils";
|
|
|
4
4
|
declare const plugin: {
|
|
5
5
|
meta: {
|
|
6
6
|
readonly name: "@utilfirst/eslint-plugin";
|
|
7
|
-
readonly version:
|
|
7
|
+
readonly version: string;
|
|
8
8
|
};
|
|
9
9
|
rules: {
|
|
10
10
|
"consistent-blank-lines": TSESLint.RuleModule<"extra" | "missing", [], unknown, TSESLint.RuleListener>;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
2
|
|
|
3
|
+
//#region package.json
|
|
4
|
+
var version = "0.1.1";
|
|
5
|
+
|
|
6
|
+
//#endregion
|
|
3
7
|
//#region src/rules/consistent-blank-lines.ts
|
|
4
8
|
const SKIP_KEYS = new Set([
|
|
5
9
|
"parent",
|
|
@@ -59,8 +63,8 @@ const consistentBlankLines = {
|
|
|
59
63
|
fixable: "whitespace",
|
|
60
64
|
schema: [],
|
|
61
65
|
messages: {
|
|
62
|
-
extra: "Unexpected blank line between
|
|
63
|
-
missing: "Expected a blank line between
|
|
66
|
+
extra: "Unexpected blank line between items that continue the same paragraph.",
|
|
67
|
+
missing: "Expected a blank line between items that start a new paragraph."
|
|
64
68
|
}
|
|
65
69
|
},
|
|
66
70
|
defaultOptions: [],
|
|
@@ -70,7 +74,7 @@ const consistentBlankLines = {
|
|
|
70
74
|
for (let i = 0; i < statements.length - 1; i++) {
|
|
71
75
|
const prev = statements[i];
|
|
72
76
|
const next = statements[i + 1];
|
|
73
|
-
if (prev && next) checkPair(prev, next, sourceCode.getCommentsBefore(next)[0] ?? next, () => sameParagraph(prev, next, sourceCode), () => isImportPair(prev, next) || isReExport(prev) && isReExport(next));
|
|
77
|
+
if (prev && next) checkPair(prev, next, sourceCode.getCommentsBefore(next)[0] ?? next, () => sameParagraph(prev, next, sourceCode), () => isImportPair(prev, next) || isReExport(prev) && isReExport(next) || isExpressionStatementPair(prev, next));
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
80
|
function checkJsxChildren(children) {
|
|
@@ -189,23 +193,26 @@ function sameShape(prev, next) {
|
|
|
189
193
|
function isImportPair(prev, next) {
|
|
190
194
|
return prev.type === AST_NODE_TYPES.ImportDeclaration && next.type === AST_NODE_TYPES.ImportDeclaration;
|
|
191
195
|
}
|
|
196
|
+
function isExpressionStatementPair(prev, next) {
|
|
197
|
+
return prev.type === AST_NODE_TYPES.ExpressionStatement && next.type === AST_NODE_TYPES.ExpressionStatement;
|
|
198
|
+
}
|
|
192
199
|
function isReExport(stmt) {
|
|
193
200
|
return stmt.type === AST_NODE_TYPES.ExportNamedDeclaration && stmt.source !== null || stmt.type === AST_NODE_TYPES.ExportAllDeclaration;
|
|
194
201
|
}
|
|
195
202
|
function isMatchingVarDeclPair(prev, next) {
|
|
196
|
-
const
|
|
197
|
-
const
|
|
198
|
-
if (
|
|
199
|
-
if (!isConstOrLet(
|
|
203
|
+
const previousDeclaration = unwrapExport(prev);
|
|
204
|
+
const nextDeclaration = unwrapExport(next);
|
|
205
|
+
if (previousDeclaration.type !== AST_NODE_TYPES.VariableDeclaration || nextDeclaration.type !== AST_NODE_TYPES.VariableDeclaration) return false;
|
|
206
|
+
if (!isConstOrLet(previousDeclaration) || !isConstOrLet(nextDeclaration)) return false;
|
|
200
207
|
if (isMultiLine(prev) || isMultiLine(next)) return false;
|
|
201
|
-
if (
|
|
202
|
-
if (!initsMatchByShape(
|
|
208
|
+
if (previousDeclaration.declarations.length !== 1 || nextDeclaration.declarations.length !== 1) return false;
|
|
209
|
+
if (!initsMatchByShape(previousDeclaration.declarations[0].init, nextDeclaration.declarations[0].init)) return false;
|
|
203
210
|
return prev.type === AST_NODE_TYPES.ExportNamedDeclaration === (next.type === AST_NODE_TYPES.ExportNamedDeclaration);
|
|
204
211
|
}
|
|
205
212
|
function isMatchingTypeAliasPair(prev, next) {
|
|
206
|
-
const
|
|
207
|
-
const
|
|
208
|
-
if (
|
|
213
|
+
const previousDeclaration = unwrapExport(prev);
|
|
214
|
+
const nextDeclaration = unwrapExport(next);
|
|
215
|
+
if (previousDeclaration.type !== AST_NODE_TYPES.TSTypeAliasDeclaration || nextDeclaration.type !== AST_NODE_TYPES.TSTypeAliasDeclaration) return false;
|
|
209
216
|
if (isMultiLine(prev) || isMultiLine(next)) return false;
|
|
210
217
|
return prev.type === AST_NODE_TYPES.ExportNamedDeclaration === (next.type === AST_NODE_TYPES.ExportNamedDeclaration);
|
|
211
218
|
}
|
|
@@ -248,13 +255,15 @@ function isGuardIf(stmt) {
|
|
|
248
255
|
return stmt.type === AST_NODE_TYPES.IfStatement && blockAlwaysTerminates(stmt.consequent);
|
|
249
256
|
}
|
|
250
257
|
function blockAlwaysTerminates(node) {
|
|
251
|
-
if (!node) return false;
|
|
252
258
|
if (TERMINATING_STATEMENT_TYPES.has(node.type)) return true;
|
|
253
259
|
if (node.type === AST_NODE_TYPES.BlockStatement) {
|
|
254
260
|
const last = node.body[node.body.length - 1];
|
|
255
261
|
return last ? blockAlwaysTerminates(last) : false;
|
|
256
262
|
}
|
|
257
|
-
if (node.type === AST_NODE_TYPES.IfStatement)
|
|
263
|
+
if (node.type === AST_NODE_TYPES.IfStatement) {
|
|
264
|
+
if (!node.alternate) return false;
|
|
265
|
+
return blockAlwaysTerminates(node.consequent) && blockAlwaysTerminates(node.alternate);
|
|
266
|
+
}
|
|
258
267
|
if (node.type === AST_NODE_TYPES.TryStatement) {
|
|
259
268
|
if (node.finalizer && blockAlwaysTerminates(node.finalizer)) return true;
|
|
260
269
|
if (!blockAlwaysTerminates(node.block)) return false;
|
|
@@ -278,7 +287,6 @@ function collectIntroducedOrAssignedNames(stmt) {
|
|
|
278
287
|
return set;
|
|
279
288
|
}
|
|
280
289
|
function collectBindingNames(node, set) {
|
|
281
|
-
if (!node) return;
|
|
282
290
|
switch (node.type) {
|
|
283
291
|
case AST_NODE_TYPES.Identifier:
|
|
284
292
|
set.add(node.name);
|
|
@@ -333,10 +341,10 @@ function resolvesOutsideRoot(idNode, root, sourceCode) {
|
|
|
333
341
|
return true;
|
|
334
342
|
}
|
|
335
343
|
function thisResolvesOutsideRoot(thisNode, root) {
|
|
336
|
-
let
|
|
337
|
-
while (
|
|
338
|
-
if (
|
|
339
|
-
|
|
344
|
+
let parent = parentOf(thisNode);
|
|
345
|
+
while (parent) {
|
|
346
|
+
if (parent.type === AST_NODE_TYPES.FunctionDeclaration || parent.type === AST_NODE_TYPES.FunctionExpression) return !isInSubtree(parent, root);
|
|
347
|
+
parent = parentOf(parent);
|
|
340
348
|
}
|
|
341
349
|
return true;
|
|
342
350
|
}
|
|
@@ -362,8 +370,6 @@ function isDeclarationOrPropertyKey(idNode) {
|
|
|
362
370
|
if (FN_DECL_TYPES.has(parent.type) && "id" in parent && parent.id === idNode) return true;
|
|
363
371
|
if ((parent.type === AST_NODE_TYPES.ClassDeclaration || parent.type === AST_NODE_TYPES.ClassExpression) && parent.id === idNode) return true;
|
|
364
372
|
if (parent.type === AST_NODE_TYPES.MemberExpression && parent.property === idNode && !parent.computed) return true;
|
|
365
|
-
if (parent.type === AST_NODE_TYPES.MethodDefinition && parent.key === idNode && !parent.computed) return true;
|
|
366
|
-
if (parent.type === AST_NODE_TYPES.PropertyDefinition && parent.key === idNode && !parent.computed) return true;
|
|
367
373
|
if (IMPORT_SPECIFIER_TYPES.has(parent.type) && "local" in parent && parent.local === idNode) return true;
|
|
368
374
|
if (parent.type === AST_NODE_TYPES.Property && parent.key === idNode && !parent.computed && !parent.shorthand) return true;
|
|
369
375
|
if (isInBindingPosition(idNode)) return true;
|
|
@@ -371,26 +377,25 @@ function isDeclarationOrPropertyKey(idNode) {
|
|
|
371
377
|
}
|
|
372
378
|
function isInBindingPosition(idNode) {
|
|
373
379
|
let cur = idNode;
|
|
374
|
-
let
|
|
375
|
-
while (
|
|
376
|
-
if (FN_DECL_TYPES.has(
|
|
377
|
-
if (
|
|
378
|
-
if (
|
|
379
|
-
if (
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
p = parentOf(p);
|
|
380
|
+
let parent = parentOf(cur);
|
|
381
|
+
while (parent) {
|
|
382
|
+
if (FN_DECL_TYPES.has(parent.type) && "params" in parent && Array.isArray(parent.params) && parent.params.includes(cur)) return true;
|
|
383
|
+
if (parent.type === AST_NODE_TYPES.ObjectPattern || parent.type === AST_NODE_TYPES.ArrayPattern) return true;
|
|
384
|
+
if (parent.type === AST_NODE_TYPES.Property) {
|
|
385
|
+
if (parent.computed && parent.key === cur) return false;
|
|
386
|
+
cur = parent;
|
|
387
|
+
parent = parentOf(parent);
|
|
383
388
|
continue;
|
|
384
389
|
}
|
|
385
|
-
if (
|
|
386
|
-
if (
|
|
387
|
-
cur =
|
|
388
|
-
|
|
390
|
+
if (parent.type === AST_NODE_TYPES.AssignmentPattern) {
|
|
391
|
+
if (parent.right === cur) return false;
|
|
392
|
+
cur = parent;
|
|
393
|
+
parent = parentOf(parent);
|
|
389
394
|
continue;
|
|
390
395
|
}
|
|
391
|
-
if (
|
|
392
|
-
cur =
|
|
393
|
-
|
|
396
|
+
if (parent.type === AST_NODE_TYPES.RestElement) {
|
|
397
|
+
cur = parent;
|
|
398
|
+
parent = parentOf(parent);
|
|
394
399
|
continue;
|
|
395
400
|
}
|
|
396
401
|
return false;
|
|
@@ -426,11 +431,11 @@ function expressionYieldsStringLiteral(expr) {
|
|
|
426
431
|
function walk(node, fn) {
|
|
427
432
|
if (!node || typeof node !== "object" || typeof node.type !== "string") return;
|
|
428
433
|
fn(node);
|
|
429
|
-
const
|
|
430
|
-
for (const key of Object.keys(
|
|
434
|
+
const nodeFields = node;
|
|
435
|
+
for (const key of Object.keys(nodeFields)) {
|
|
431
436
|
if (SKIP_KEYS.has(key)) continue;
|
|
432
437
|
if (key === "body" && OPAQUE_BODY_TYPES.has(node.type)) continue;
|
|
433
|
-
const child =
|
|
438
|
+
const child = nodeFields[key];
|
|
434
439
|
if (Array.isArray(child)) for (const c of child) walk(c, fn);
|
|
435
440
|
else walk(child, fn);
|
|
436
441
|
}
|
|
@@ -451,7 +456,7 @@ function hasMultiLineLeadingComment(node, sourceCode) {
|
|
|
451
456
|
const plugin = {
|
|
452
457
|
meta: {
|
|
453
458
|
name: "@utilfirst/eslint-plugin",
|
|
454
|
-
version
|
|
459
|
+
version
|
|
455
460
|
},
|
|
456
461
|
rules: { "consistent-blank-lines": consistentBlankLines },
|
|
457
462
|
configs: {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@utilfirst/eslint-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Shared ESLint rules for utilfirst projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -28,20 +28,6 @@
|
|
|
28
28
|
"files": [
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
|
-
"scripts": {
|
|
32
|
-
"build": "tsdown",
|
|
33
|
-
"fix": "pnpm run --sequential '/^fix:[^:]+$/'",
|
|
34
|
-
"fix:eslint": "pnpm run lint:eslint --fix",
|
|
35
|
-
"fix:prettier": "pnpm run lint:prettier --write",
|
|
36
|
-
"lint": "pnpm run --sequential '/^lint:[^:]+$/'",
|
|
37
|
-
"lint:eslint": "eslint .",
|
|
38
|
-
"lint:prettier": "prettier --check .",
|
|
39
|
-
"lint:publint": "publint",
|
|
40
|
-
"lint:typecheck": "tsc --pretty --noEmit",
|
|
41
|
-
"prepack": "pnpm run build",
|
|
42
|
-
"setup-hooks": "simple-git-hooks",
|
|
43
|
-
"test": "vitest run"
|
|
44
|
-
},
|
|
45
31
|
"simple-git-hooks": {
|
|
46
32
|
"pre-commit": "pnpm exec lint-staged && pnpm run lint:typecheck"
|
|
47
33
|
},
|
|
@@ -56,6 +42,8 @@
|
|
|
56
42
|
"@eslint/js": "^10.0.1",
|
|
57
43
|
"@types/node": "^25.9.1",
|
|
58
44
|
"@typescript-eslint/rule-tester": "^8.59.3",
|
|
45
|
+
"@utilfirst/prettier-plugin": "^0.1.0",
|
|
46
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
59
47
|
"eslint": "^10.3.0",
|
|
60
48
|
"lint-staged": "^17.0.4",
|
|
61
49
|
"prettier": "^3.8.3",
|
|
@@ -73,12 +61,24 @@
|
|
|
73
61
|
"peerDependencies": {
|
|
74
62
|
"eslint": "^9.0.0 || ^10.0.0"
|
|
75
63
|
},
|
|
76
|
-
"packageManager": "pnpm@11.0.9",
|
|
77
64
|
"engines": {
|
|
78
65
|
"node": ">=20.19.0"
|
|
79
66
|
},
|
|
80
67
|
"publishConfig": {
|
|
81
68
|
"access": "public",
|
|
82
69
|
"provenance": true
|
|
70
|
+
},
|
|
71
|
+
"scripts": {
|
|
72
|
+
"build": "tsdown",
|
|
73
|
+
"fix": "pnpm run --sequential '/^fix:[^:]+$/'",
|
|
74
|
+
"fix:eslint": "pnpm run lint:eslint --fix",
|
|
75
|
+
"fix:prettier": "pnpm run lint:prettier --write",
|
|
76
|
+
"lint": "pnpm run --sequential '/^lint:[^:]+$/'",
|
|
77
|
+
"lint:eslint": "eslint .",
|
|
78
|
+
"lint:prettier": "prettier --check .",
|
|
79
|
+
"lint:publint": "publint",
|
|
80
|
+
"lint:typecheck": "tsc --pretty --noEmit",
|
|
81
|
+
"setup-hooks": "simple-git-hooks",
|
|
82
|
+
"test": "vitest run"
|
|
83
83
|
}
|
|
84
|
-
}
|
|
84
|
+
}
|