@sabzidev/eslint-rules 1.0.5 → 1.0.7

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.
Files changed (3) hide show
  1. package/README.md +47 -32
  2. package/dist/index.js +74 -71
  3. package/package.json +6 -6
package/README.md CHANGED
@@ -26,7 +26,7 @@ A collection of custom ESLint rules for improving code quality, consistency, and
26
26
 
27
27
  ---
28
28
 
29
- ## 📦 Installation
29
+ ## 🚀📦 Installation & Usage
30
30
 
31
31
  Install the package as a development dependency:
32
32
 
@@ -34,11 +34,7 @@ Install the package as a development dependency:
34
34
  pnpm i -D @sabzidev/eslint-rules
35
35
  ```
36
36
 
37
- ---
38
-
39
- ## 🚀 Usage
40
-
41
- Choose **one** of the following configuration methods for your existing `eslint.config.js` file:
37
+ Choose **one** of the following configuration methods for your `eslint.config.js` file:
42
38
 
43
39
  ### ● Recommended Configuration
44
40
 
@@ -54,7 +50,7 @@ export default defineConfig([
54
50
  ]);
55
51
  ```
56
52
 
57
- This enables all rules included in the recommended configuration with their predefined severity levels.
53
+ This enables all recommended rules with their predefined severity levels.
58
54
 
59
55
  ### ● Custom Configuration
60
56
 
@@ -86,11 +82,19 @@ export default defineConfig([
86
82
 
87
83
  ---
88
84
 
89
- ## ⭐ Recommended Tooling Setup
85
+ ## ⭐ Recommended ESLint & Prettier Setup
90
86
 
91
- For a more comprehensive linting setup, combine `@sabzidev/eslint-rules` with [`@fullstacksjs/eslint-config`](https://www.npmjs.com/package/@fullstacksjs/eslint-config), [`eslint-plugin-sonarjs`](https://www.npmjs.com/package/eslint-plugin-sonarjs), and [`eslint-plugin-unicorn`](https://www.npmjs.com/package/eslint-plugin-unicorn).
87
+ Install the required dependencies:
92
88
 
93
- This combination brings together code-quality rules, bug detection, maintainability checks, and custom linting rules.
89
+ ```bash
90
+ pnpm i -D eslint prettier @fullstacksjs/eslint-config @sabzidev/eslint-rules eslint-plugin-sonarjs eslint-plugin-unicorn
91
+ ```
92
+
93
+ For a comprehensive code-quality setup, combine `ESLint`, `Prettier`, [`@fullstacksjs/eslint-config`](https://npmjs.com/package/@fullstacksjs/eslint-config), [`@sabzidev/eslint-rules`](https://npmjs.com/package/@sabzidev/eslint-rules), [`eslint-plugin-sonarjs`](https://npmjs.com/package/eslint-plugin-sonarjs), and [`eslint-plugin-unicorn`](https://npmjs.com/package/eslint-plugin-unicorn).
94
+
95
+ This setup combines code formatting, code-quality checks, bug detection, maintainability rules, and custom ESLint rules.
96
+
97
+ This setup combines code-quality rules, bug detection, maintainability checks, and custom linting rules.
94
98
 
95
99
  **Configuration for `eslint.config.js`:**
96
100
 
@@ -110,28 +114,39 @@ const baseRules = {
110
114
  eqeqeq: ["error", "always"],
111
115
  "no-console": "warn",
112
116
  };
117
+
113
118
  const plugins = [
114
119
  sabzidev.configs.recommended,
115
120
  sonarjs.configs.recommended,
116
121
  unicorn.configs.recommended,
117
122
  ];
123
+
118
124
  const pluginsRules = {
119
125
  "unicorn/filename-case": "off",
120
- "unicorn/prefer-global-this": "off",
121
- "unicorn/name-replacements": "off",
122
- "unicorn/no-array-sort": "off",
126
+ "unicorn/name-replacements": [
127
+ "error",
128
+ {
129
+ replacements: {
130
+ prop: false,
131
+ props: false,
132
+ param: false,
133
+ params: false,
134
+ ref: false,
135
+ refs: false,
136
+ prev: false,
137
+ e: false,
138
+ res: false,
139
+ err: false,
140
+ },
141
+ },
142
+ ],
123
143
  "unicorn/no-null": "off",
144
+ "unicorn/prefer-global-this": "off",
124
145
  "unicorn/default-export-style": "off",
125
-
126
- "jsx-a11y/click-events-have-key-events": "off",
127
- "jsx-a11y/no-noninteractive-element-interactions": "off",
128
146
  };
129
147
 
130
148
  const config = defineConfig(
131
- {
132
- tailwind: { entryPoint: "./src/input.css" },
133
- rules: baseRules,
134
- },
149
+ { rules: baseRules, tailwind: { entryPoint: "./src/input.css" } },
135
150
 
136
151
  plugins,
137
152
  { rules: pluginsRules },
@@ -140,23 +155,23 @@ const config = defineConfig(
140
155
  export default config;
141
156
  ```
142
157
 
143
- **Note:** Customize the rules to match your project's requirements and verify compatibility with your installed plugin versions.
158
+ **Note:** Adjust the rules to suit your project and ensure compatibility with your installed plugin versions.
144
159
 
145
160
  ---
146
161
 
147
162
  ## 📋 Available Rules
148
163
 
149
- | Rule | Description |
150
- | :--------------------------------------- | :------------------------------------------- |
151
- | `merge-duplicate-id-and-classname-props` | Merges duplicate `id` and `className` props. |
152
- | `merge-exports` | Merges or organizes export declarations. |
153
- | `no-invalid-id-and-classname-value` | Detects invalid `id` and `className` values. |
154
- | `no-useless-empty-type` | Detects unnecessary empty types. |
155
- | `no-useless-template-literal` | Detects unnecessary template literals. |
156
- | `padding-before-jump-statement` | Enforces padding before jump statements. |
157
- | `sort-comments` | Sorts comments. |
158
- | `sort-jsx-props` | Sorts JSX props. |
159
- | `sort-object-props` | Sorts object properties. |
164
+ | Rule | Description |
165
+ | :--------------------------------------- | :------------------------------------------------------------------------- |
166
+ | `merge-duplicate-id-and-classname-props` | Merges duplicate id and className props. |
167
+ | `merge-exports` | Merges or organizes export declarations. |
168
+ | `no-invalid-id-and-classname-value` | Detects invalid id and className values. |
169
+ | `no-useless-empty-type` | Detects unnecessary empty types. |
170
+ | `no-useless-template-literal` | Detects unnecessary template literals. |
171
+ | `padding-before-jump-statement` | Enforces padding before jump statements. |
172
+ | `sort-comments` | Sorts comments. |
173
+ | `sort-jsx-props` | Sorts JSX props. |
174
+ | `sort-props` | Sorts object properties, function parameters, and TypeScript type members. |
160
175
 
161
176
  ---
162
177
 
package/dist/index.js CHANGED
@@ -1,11 +1,6 @@
1
1
  var e = {
2
2
  name: "@sabzidev/eslint-rules",
3
3
  description: "A collection of ESLint rules for better code quality, consistency, and maintainability.",
4
- repository: {
5
- type: "git",
6
- url: "https://github.com/SabziDev/eslint-rules"
7
- },
8
- license: "MIT",
9
4
  keywords: [
10
5
  "SabziDev",
11
6
  "eslint",
@@ -16,8 +11,13 @@ var e = {
16
11
  "linting",
17
12
  "developer-tools"
18
13
  ],
14
+ repository: {
15
+ type: "git",
16
+ url: "https://github.com/SabziDev/eslint-rules"
17
+ },
18
+ license: "MIT",
19
19
  author: "Abolfazl Sabzmohammadi <SabziDev@gmail.com> (https://Sabzi.Dev)",
20
- version: "1.0.5",
20
+ version: "1.0.7",
21
21
  type: "module",
22
22
  main: "./dist/index.js",
23
23
  exports: "./dist/index.js",
@@ -356,10 +356,11 @@ var e = {
356
356
  });
357
357
  } };
358
358
  }
359
- }, l = /* @__PURE__ */ "children.key.id.ref.data.title.desc.htmlFor.type.inputMode.name.value.placeholder.autoComplete.min.max.minLength.maxLength.src.alt.loading.poster.preload.controls.href.target.rel.to.replace.viewTransition".split("."), u = [
359
+ }, l = /* @__PURE__ */ "prop.props.children.param.params.key.id.ref.data.title.desc.htmlFor.type.inputMode.name.value.placeholder.autoComplete.min.max.minLength.maxLength.src.alt.loading.poster.preload.controls.href.target.rel.to.replace.viewTransition".split("."), u = [
360
360
  "onClick",
361
361
  "onChange",
362
- "onKeyUp"
362
+ "onKeyUp",
363
+ "onKeyDown"
363
364
  ], d = {
364
365
  "merge-duplicate-id-and-classname-props": t,
365
366
  "merge-exports": n,
@@ -412,7 +413,7 @@ var e = {
412
413
  } };
413
414
  }
414
415
  },
415
- "sort-object-props": {
416
+ "sort-props": {
416
417
  meta: {
417
418
  type: "suggestion",
418
419
  fixable: "code",
@@ -432,16 +433,10 @@ var e = {
432
433
  let t = l.flatMap((t) => e.filter((e) => a(e) === t)), o = e.filter((e) => {
433
434
  let t = a(e);
434
435
  return !n.has(t) && !r(t) && !["className", "style"].includes(t);
435
- }), s = e.filter((e) => {
436
- let t = a(e);
437
- return r(t);
438
- }).sort((e, t) => {
436
+ }), s = e.filter((e) => r(a(e))).sort((e, t) => {
439
437
  let n = i(a(e)), r = i(a(t));
440
438
  return n === 999 && r === 999 ? 0 : n - r;
441
- }), c = e.filter((e) => {
442
- let t = a(e);
443
- return ["className", "style"].includes(t);
444
- }).sort((e, t) => {
439
+ }), c = e.filter((e) => ["className", "style"].includes(a(e))).sort((e, t) => {
445
440
  let n = a(e), r = a(t);
446
441
  return n === "className" && r === "style" ? -1 : +(n === "style" && r === "className");
447
442
  });
@@ -453,57 +448,68 @@ var e = {
453
448
  ];
454
449
  }, d = (e) => {
455
450
  let t = [], n = [];
456
- for (let r of e) if (o(r)) {
457
- if (n.length > 0) {
458
- let e = c(n);
459
- t.push(...e), n = [];
460
- }
461
- t.push(r);
462
- } else n.push(r);
463
- if (n.length > 0) {
464
- let e = c(n);
465
- t.push(...e);
466
- }
467
- return t;
451
+ for (let r of e) o(r) ? (n.length > 0 && (t.push(...c(n)), n = []), t.push(r)) : n.push(r);
452
+ return n.length > 0 && t.push(...c(n)), t;
468
453
  }, f = (e) => {
469
454
  if (e.length <= 1) return e;
470
455
  let t = e.filter((e) => !o(e) && s(e)), n = e.filter((e) => !t.includes(e));
471
456
  return [...c(t), ...n];
472
- }, p = (e, t) => {
473
- if (e.length !== t.length) return !0;
474
- for (let [n, r] of e.entries()) if (r !== t[n]) return !0;
475
- return !1;
476
- }, m = (e) => `{ ${e.map((e) => t.getText(e)).join(", ")} }`, h = (e) => e.map((e) => t.getText(e)).join("\n"), g = (n, r) => {
477
- let { properties: i } = n;
478
- if (!i || i.length <= 1) return;
479
- let a = d(i);
480
- if (!p(i, a)) return;
481
- let o = i[0], s = i.at(-1), c = o.range[0], l = s.range[1];
457
+ }, p = (e, t) => e.length !== t.length || e.some((e, n) => e !== t[n]), m = (e) => `{ ${e.map((e) => t.getText(e)).join(", ")} }`, h = (e) => e.map((e) => t.getText(e)).join("\n"), g = (t, n, r, i, a) => {
458
+ if (!p(n, r)) return;
459
+ let o = n[0], s = n.at(-1);
482
460
  e.report({
483
- node: n,
484
- messageId: r,
461
+ node: t,
462
+ messageId: i,
485
463
  fix(e) {
486
- let n = a.map((e) => t.getText(e)).join(", ");
487
- return e.replaceTextRange([c, l], n);
464
+ let t = a(r);
465
+ return e.replaceTextRange([o.range[0], s.range[1]], t);
488
466
  }
489
467
  });
490
- }, _ = (e) => {
491
- let { params: t } = e;
492
- if (t && t.length !== 0) for (let e of t) e.type === "ObjectPattern" && g(e, "wrongParams");
493
- }, v = (t) => {
494
- let n = t.body ?? t.members;
495
- if (!n || n.length <= 1) return;
496
- let r = f(n);
497
- if (!p(n, r)) return;
498
- let i = n[0], a = n.at(-1), o = i.range[0], s = a.range[1];
468
+ }, _ = (e, n) => {
469
+ let { properties: r } = e;
470
+ if (!r || r.length <= 1) return;
471
+ let i = d(r);
472
+ g(e, r, i, n, (e) => e.map((e) => t.getText(e)).join(", "));
473
+ }, v = (n) => {
474
+ let { params: a } = n;
475
+ if (!a || a.length === 0) return;
476
+ for (let e of a) e.type === "ObjectPattern" && _(e, "wrongParams");
477
+ if (a.length <= 1 || a.some((e) => e.type !== "Identifier")) return;
478
+ let o = (e) => {
479
+ let t = l.indexOf(e);
480
+ return t === -1 ? r(e) ? {
481
+ category: 2,
482
+ priority: i(e)
483
+ } : e === "className" ? {
484
+ category: 3,
485
+ priority: 0
486
+ } : {
487
+ category: e === "style" ? 4 : 1,
488
+ priority: 0
489
+ } : {
490
+ category: 0,
491
+ priority: t
492
+ };
493
+ }, s = a.map((e, t) => ({
494
+ param: e,
495
+ index: t,
496
+ ...o(e.name)
497
+ })).sort((e, t) => e.category === t.category ? e.priority === t.priority ? e.index - t.index : e.priority - t.priority : e.category - t.category).map(({ param: e }) => e);
498
+ if (!p(a, s)) return;
499
+ let c = a[0], u = a.at(-1);
499
500
  e.report({
500
- node: t,
501
- messageId: "wrongTypeProperties",
501
+ node: n,
502
+ messageId: "wrongParams",
502
503
  fix(e) {
503
- let t = h(r);
504
- return e.replaceTextRange([o, s], t);
504
+ let n = s.map((e) => t.getText(e)).join(", ");
505
+ return e.replaceTextRange([c.range[0], u.range[1]], n);
505
506
  }
506
507
  });
508
+ }, y = (e) => {
509
+ let t = e.body ?? e.members;
510
+ if (!t || t.length <= 1) return;
511
+ let n = f(t);
512
+ g(e, t, n, "wrongTypeProperties", h);
507
513
  };
508
514
  return {
509
515
  ObjectExpression(t) {
@@ -514,26 +520,23 @@ var e = {
514
520
  node: t,
515
521
  messageId: "wrongOrder",
516
522
  fix(e) {
517
- let n = m(r);
518
- return e.replaceText(t, n);
523
+ return e.replaceText(t, m(r));
519
524
  }
520
525
  });
521
526
  },
522
527
  ObjectPattern(e) {
523
- g(e, "wrongDestructure");
524
- },
525
- TSTypeLiteral(e) {
526
- v(e);
527
- },
528
- TSInterfaceBody(e) {
529
- v(e);
530
- },
531
- TSTypeAliasDeclaration(e) {
532
- e.typeAnnotation?.type === "TSTypeLiteral" && v(e.typeAnnotation);
528
+ _(e, "wrongDestructure");
533
529
  },
534
- FunctionDeclaration: _,
535
- FunctionExpression: _,
536
- ArrowFunctionExpression: _
530
+ TSTypeLiteral: y,
531
+ TSInterfaceBody: y,
532
+ FunctionDeclaration: v,
533
+ FunctionExpression: v,
534
+ ArrowFunctionExpression: v,
535
+ TSDeclareFunction: v,
536
+ TSFunctionType: v,
537
+ TSCallSignatureDeclaration: v,
538
+ TSConstructSignatureDeclaration: v,
539
+ TSMethodSignature: v
537
540
  };
538
541
  }
539
542
  }
package/package.json CHANGED
@@ -1,11 +1,6 @@
1
1
  {
2
2
  "name": "@sabzidev/eslint-rules",
3
3
  "description": "A collection of ESLint rules for better code quality, consistency, and maintainability.",
4
- "repository": {
5
- "type": "git",
6
- "url": "https://github.com/SabziDev/eslint-rules"
7
- },
8
- "license": "MIT",
9
4
  "keywords": [
10
5
  "SabziDev",
11
6
  "eslint",
@@ -16,8 +11,13 @@
16
11
  "linting",
17
12
  "developer-tools"
18
13
  ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/SabziDev/eslint-rules"
17
+ },
18
+ "license": "MIT",
19
19
  "author": "Abolfazl Sabzmohammadi <SabziDev@gmail.com> (https://Sabzi.Dev)",
20
- "version": "1.0.5",
20
+ "version": "1.0.7",
21
21
  "type": "module",
22
22
  "main": "./dist/index.js",
23
23
  "exports": "./dist/index.js",