@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 CHANGED
@@ -37,9 +37,9 @@ export default [
37
37
 
38
38
  ## Rules
39
39
 
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 new thoughts | yes |
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: "0.1.0";
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 statements that continue the same paragraph.",
63
- missing: "Expected a blank line between statements that start new paragraphs."
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 p = unwrapExport(prev);
197
- const n = unwrapExport(next);
198
- if (p.type !== AST_NODE_TYPES.VariableDeclaration || n.type !== AST_NODE_TYPES.VariableDeclaration) return false;
199
- if (!isConstOrLet(p) || !isConstOrLet(n)) return false;
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 (p.declarations.length !== 1 || n.declarations.length !== 1) return false;
202
- if (!initsMatchByShape(p.declarations[0].init, n.declarations[0].init)) return false;
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 p = unwrapExport(prev);
207
- const n = unwrapExport(next);
208
- if (p.type !== AST_NODE_TYPES.TSTypeAliasDeclaration || n.type !== AST_NODE_TYPES.TSTypeAliasDeclaration) return false;
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) return Boolean(node.alternate) && blockAlwaysTerminates(node.consequent) && blockAlwaysTerminates(node.alternate);
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 p = parentOf(thisNode);
337
- while (p) {
338
- if (p.type === AST_NODE_TYPES.FunctionDeclaration || p.type === AST_NODE_TYPES.FunctionExpression) return !isInSubtree(p, root);
339
- p = parentOf(p);
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 p = parentOf(cur);
375
- while (p) {
376
- if (FN_DECL_TYPES.has(p.type) && "params" in p && Array.isArray(p.params) && p.params.includes(cur)) return true;
377
- if (p.type === AST_NODE_TYPES.ObjectPattern || p.type === AST_NODE_TYPES.ArrayPattern) return true;
378
- if (p.type === AST_NODE_TYPES.Property) {
379
- if (p.computed && p.key === cur) return false;
380
- if (!p.shorthand && p.value !== cur) return false;
381
- cur = p;
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 (p.type === AST_NODE_TYPES.AssignmentPattern) {
386
- if (p.right === cur) return false;
387
- cur = p;
388
- p = parentOf(p);
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 (p.type === AST_NODE_TYPES.RestElement) {
392
- cur = p;
393
- p = parentOf(p);
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 obj = node;
430
- for (const key of Object.keys(obj)) {
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 = obj[key];
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: "0.1.0"
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.0",
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
+ }