@sabzidev/eslint-rules 1.0.4 → 1.0.6

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 +49 -32
  2. package/dist/index.js +74 -71
  3. package/package.json +6 -6
package/README.md CHANGED
@@ -9,7 +9,9 @@ A collection of custom ESLint rules for improving code quality, consistency, and
9
9
  <div align="center">
10
10
  <img src="https://img.shields.io/npm/dm/@sabzidev/eslint-rules?style=flat-square&&color=16A34A&label=DOWNLOADS" alt="DOWNLOADS" />
11
11
  <img src="https://img.shields.io/npm/v/@sabzidev/eslint-rules?style=flat-square&color=16A34A&label=VERSION" alt="VERSION" />
12
+
12
13
  <br />
14
+
13
15
  <img src="./docs/images/logo.webp" alt="SabziDev logo" height="300" width="70%" />
14
16
 
15
17
  [GITHUB](https://github.com/SabziDev/eslint-rules) | [NPM](https://npmjs.com/package/@sabzidev/eslint-rules)
@@ -24,7 +26,7 @@ A collection of custom ESLint rules for improving code quality, consistency, and
24
26
 
25
27
  ---
26
28
 
27
- ## 📦 Installation
29
+ ## 🚀📦 Installation & Usage
28
30
 
29
31
  Install the package as a development dependency:
30
32
 
@@ -32,11 +34,7 @@ Install the package as a development dependency:
32
34
  pnpm i -D @sabzidev/eslint-rules
33
35
  ```
34
36
 
35
- ---
36
-
37
- ## 🚀 Usage
38
-
39
- 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:
40
38
 
41
39
  ### ● Recommended Configuration
42
40
 
@@ -52,7 +50,7 @@ export default defineConfig([
52
50
  ]);
53
51
  ```
54
52
 
55
- 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.
56
54
 
57
55
  ### ● Custom Configuration
58
56
 
@@ -84,11 +82,19 @@ export default defineConfig([
84
82
 
85
83
  ---
86
84
 
87
- ## ⭐ Recommended Tooling Setup
85
+ ## ⭐ Recommended ESLint & Prettier Setup
86
+
87
+ Install the required dependencies:
88
+
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).
88
94
 
89
- 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).
95
+ This setup combines code formatting, code-quality checks, bug detection, maintainability rules, and custom ESLint rules.
90
96
 
91
- This combination brings together code-quality rules, bug detection, maintainability checks, and custom linting rules.
97
+ This setup combines code-quality rules, bug detection, maintainability checks, and custom linting rules.
92
98
 
93
99
  **Configuration for `eslint.config.js`:**
94
100
 
@@ -108,28 +114,39 @@ const baseRules = {
108
114
  eqeqeq: ["error", "always"],
109
115
  "no-console": "warn",
110
116
  };
117
+
111
118
  const plugins = [
112
119
  sabzidev.configs.recommended,
113
120
  sonarjs.configs.recommended,
114
121
  unicorn.configs.recommended,
115
122
  ];
123
+
116
124
  const pluginsRules = {
117
125
  "unicorn/filename-case": "off",
118
- "unicorn/prefer-global-this": "off",
119
- "unicorn/name-replacements": "off",
120
- "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
+ ],
121
143
  "unicorn/no-null": "off",
144
+ "unicorn/prefer-global-this": "off",
122
145
  "unicorn/default-export-style": "off",
123
-
124
- "jsx-a11y/click-events-have-key-events": "off",
125
- "jsx-a11y/no-noninteractive-element-interactions": "off",
126
146
  };
127
147
 
128
148
  const config = defineConfig(
129
- {
130
- tailwind: { entryPoint: "./src/input.css" },
131
- rules: baseRules,
132
- },
149
+ { rules: baseRules, tailwind: { entryPoint: "./src/input.css" } },
133
150
 
134
151
  plugins,
135
152
  { rules: pluginsRules },
@@ -138,23 +155,23 @@ const config = defineConfig(
138
155
  export default config;
139
156
  ```
140
157
 
141
- **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.
142
159
 
143
160
  ---
144
161
 
145
162
  ## 📋 Available Rules
146
163
 
147
- | Rule | Description |
148
- | :--------------------------------------- | :------------------------------------------- |
149
- | `merge-duplicate-id-and-classname-props` | Merges duplicate `id` and `className` props. |
150
- | `merge-exports` | Merges or organizes export declarations. |
151
- | `no-invalid-id-and-classname-value` | Detects invalid `id` and `className` values. |
152
- | `no-useless-empty-type` | Detects unnecessary empty types. |
153
- | `no-useless-template-literal` | Detects unnecessary template literals. |
154
- | `padding-before-jump-statement` | Enforces padding before jump statements. |
155
- | `sort-comments` | Sorts comments. |
156
- | `sort-jsx-props` | Sorts JSX props. |
157
- | `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-object-props` | Sorts object properties. |
158
175
 
159
176
  ---
160
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.4",
20
+ version: "1.0.6",
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.4",
20
+ "version": "1.0.6",
21
21
  "type": "module",
22
22
  "main": "./dist/index.js",
23
23
  "exports": "./dist/index.js",