eslint-plugin-th-rules 1.4.0
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/.eslintrc.js +19 -0
- package/.github/dependabot.yml +15 -0
- package/.github/workflows/codecov.yml +26 -0
- package/.github/workflows/codeql.yml +82 -0
- package/.github/workflows/dependency-review.yml +20 -0
- package/.github/workflows/main.yml +43 -0
- package/.github/workflows/scorecard.yml +72 -0
- package/.github/workflows/snyk-security.yml +67 -0
- package/.releaserc +13 -0
- package/.vscode/settings.json +1 -0
- package/.yarn/releases/yarn-4.1.0.cjs +893 -0
- package/.yarnrc.yml +3 -0
- package/CHANGELOG.md +131 -0
- package/README.md +84 -0
- package/SECURITY.md +48 -0
- package/bun.lockb +0 -0
- package/lib/index.js +27 -0
- package/lib/rules/no-destruction.js +94 -0
- package/lib/rules/no-unamed-default-export.js +65 -0
- package/package.json +49 -0
- package/renovate.json +3 -0
- package/tests/lib/rules/no-destruction.js +51 -0
- package/tests/lib/rules/no-unamed-default-export.js +56 -0
- package/tsconfig.json +22 -0
package/.yarnrc.yml
ADDED
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# [1.4.0](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v1.3.2...v1.4.0) (2024-02-23)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* Update package name and plugin references ([2fd90bd](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/2fd90bd5873e541ea0e4ce05c7872732636753ec))
|
|
7
|
+
|
|
8
|
+
## [1.3.1](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v1.3.0...v1.3.1) (2024-02-23)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* fixed package name ([4e006ab](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/4e006ab95cb8daa4310c43adbdd24c3be82b34b4))
|
|
14
|
+
|
|
15
|
+
# [1.3.0](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v1.2.0...v1.3.0) (2024-02-23)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* renamed recommended configuration to all ([f11d297](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/f11d297861da5b9234ddebf18c1ea4f52099b7b6))
|
|
21
|
+
* Update plugin and rule names in configs ([476b081](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/476b0813aaecfe717291ac44fdd9c661a4356693))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Features
|
|
25
|
+
|
|
26
|
+
* updated readme ([3903d35](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/3903d354c2d4ba367258aa0cd80501db080cf595))
|
|
27
|
+
|
|
28
|
+
# [1.2.0](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v1.1.4...v1.2.0) (2024-02-23)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
### Features
|
|
32
|
+
|
|
33
|
+
* :sparkles: Created a recommended configuration ([4c81e02](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/4c81e027ef00ab06a4c69ef32857093fcb06fb3b))
|
|
34
|
+
|
|
35
|
+
## [1.1.4](https://github.com/tomerh2001/eslint-plugin-no-destruction/compare/v1.1.3...v1.1.4) (2024-02-23)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
### Bug Fixes
|
|
39
|
+
|
|
40
|
+
* Update lib/index.js to import all rules in lib/rules ([d4f3183](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/d4f3183de27b530a7f62fc1670055915641d7533))
|
|
41
|
+
|
|
42
|
+
## [1.1.3](https://github.com/tomerh2001/eslint-plugin-no-destruction/compare/v1.1.2...v1.1.3) (2024-02-23)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
### Bug Fixes
|
|
46
|
+
|
|
47
|
+
* Remove "type" field from package.json ([aadbbb0](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/aadbbb090a256e20e8437b5d9c7bf57cbfd0daf5))
|
|
48
|
+
|
|
49
|
+
## [1.1.2](https://github.com/tomerh2001/eslint-plugin-no-destruction/compare/v1.1.1...v1.1.2) (2024-02-23)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
### Bug Fixes
|
|
53
|
+
|
|
54
|
+
* changed back to CommonJS ([07174fc](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/07174fce92e3a0b660fe76b4baa862fd0d33ee72))
|
|
55
|
+
|
|
56
|
+
## [1.1.1](https://github.com/tomerh2001/eslint-plugin-no-destruction/compare/v1.1.0...v1.1.1) (2024-02-23)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
### Bug Fixes
|
|
60
|
+
|
|
61
|
+
* changed index.js to ES ([d55351e](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/d55351ed380ceeb2c15d89f4b9db7e85c5250937))
|
|
62
|
+
|
|
63
|
+
# [1.1.0](https://github.com/tomerh2001/eslint-plugin-no-destruction/compare/v1.0.7...v1.1.0) (2024-02-23)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
### Bug Fixes
|
|
67
|
+
|
|
68
|
+
* Remove redundant Docker configuration ([2b1be8f](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/2b1be8f41a1036c8237f689d2addf29beedaedea))
|
|
69
|
+
* Remove Dockerfile and update eslint rule ([63d6d03](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/63d6d033a3614be9a0e132e25ff5eb94b7448505))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
### Features
|
|
73
|
+
|
|
74
|
+
* Added a rule to convert unnamed default exports to named default exports based on the file name ([cfda4c1](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/cfda4c16bbba11b281a45deca8ca8742ecab23e9))
|
|
75
|
+
|
|
76
|
+
## [1.0.7](https://github.com/tomerh2001/eslint-plugin-no-destruction/compare/v1.0.6...v1.0.7) (2024-02-22)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
### Bug Fixes
|
|
80
|
+
|
|
81
|
+
* test ([99d8a4f](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/99d8a4f325faaa425bc0ea0842567562441dcf2e))
|
|
82
|
+
|
|
83
|
+
## [1.0.6](https://github.com/tomerh2001/eslint-plugin-no-destruction/compare/v1.0.5...v1.0.6) (2024-02-22)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
### Bug Fixes
|
|
87
|
+
|
|
88
|
+
* 7 ([f397bee](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/f397bee5676832b8b11e95dc52e0b8e83c5e5940))
|
|
89
|
+
|
|
90
|
+
## [1.0.5](https://github.com/tomerh2001/eslint-plugin-no-destruction/compare/v1.0.4...v1.0.5) (2024-02-22)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
### Bug Fixes
|
|
94
|
+
|
|
95
|
+
* 6 ([e4b80fd](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/e4b80fdea4d224b880c114e8ac5c433131f46e58))
|
|
96
|
+
|
|
97
|
+
## [1.0.4](https://github.com/tomerh2001/eslint-plugin-no-destruction/compare/v1.0.3...v1.0.4) (2024-02-22)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
### Bug Fixes
|
|
101
|
+
|
|
102
|
+
* 3 ([de1546e](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/de1546eff2921718c6cfd6d6c4e8d6f82b178847))
|
|
103
|
+
* 5 ([8d1b80d](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/8d1b80d22129d1a5baaa7330f76645ef6e9f2cc9))
|
|
104
|
+
|
|
105
|
+
## [1.0.3](https://github.com/tomerh2001/eslint-plugin-no-destruction/compare/v1.0.2...v1.0.3) (2024-02-22)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
### Bug Fixes
|
|
109
|
+
|
|
110
|
+
* number 3 ([ac78e66](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/ac78e6685fcda4551a18f93afc0e05ecb232185c))
|
|
111
|
+
|
|
112
|
+
## [1.0.2](https://github.com/tomerh2001/eslint-plugin-no-destruction/compare/v1.0.1...v1.0.2) (2024-02-22)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
### Bug Fixes
|
|
116
|
+
|
|
117
|
+
* Update package.json version to 1.0.6 ([1c5409c](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/1c5409ce77ccc5fc4e35a975ffa328f59766c1d7))
|
|
118
|
+
|
|
119
|
+
## [1.0.1](https://github.com/tomerh2001/eslint-plugin-no-destruction/compare/v1.0.0...v1.0.1) (2024-02-22)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
### Bug Fixes
|
|
123
|
+
|
|
124
|
+
* semantic ([1e08f3d](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/1e08f3ddb5f1432307ce7a1e50863c9325ddbbfc))
|
|
125
|
+
|
|
126
|
+
# 1.0.0 (2024-02-22)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
### Bug Fixes
|
|
130
|
+
|
|
131
|
+
* Add ESLint configuration and rules ([0197c62](https://github.com/tomerh2001/eslint-plugin-no-destruction/commit/0197c62d8d4be2f8fd5ae67ad4c3a83370d5d678))
|
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# eslint-plugin-th-rules
|
|
2
|
+
[](https://github.com/semantic-release/semantic-release)
|
|
3
|
+
[](https://github.com/xojs/xo)
|
|
4
|
+
[](../../actions/workflows/snyk-security.yml)
|
|
5
|
+
[](../../actions/workflows/codeql.yml)
|
|
6
|
+
[](https://securityscorecards.dev/viewer/?uri=github.com/tomerh2001/eslint-plugin-th-rules)
|
|
7
|
+
|
|
8
|
+
This repository contains custom ESLint rules to enhance code quality and consistency across projects.
|
|
9
|
+
|
|
10
|
+
# Custom ESLint Rules
|
|
11
|
+
|
|
12
|
+
This repository contains custom ESLint rules to enhance code quality and consistency across projects, created by Tomer Horowitz.
|
|
13
|
+
|
|
14
|
+
## Configurations
|
|
15
|
+
|
|
16
|
+
To add all of the rules into your project, add the following configuration into your ESLint configuration file:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"extends": ["plugin:eslint-plugin-th-rules/all"]
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Rules
|
|
25
|
+
|
|
26
|
+
### 1. No-Destruction Rule
|
|
27
|
+
|
|
28
|
+
**Rule ID:** `eslint-plugin-th-rules/no-destructuring`
|
|
29
|
+
|
|
30
|
+
#### Description
|
|
31
|
+
|
|
32
|
+
This rule disallows destructuring that does not meet certain conditions, aiming to prevent overly complex destructuring patterns and ensure code readability.
|
|
33
|
+
|
|
34
|
+
#### Rule Details
|
|
35
|
+
|
|
36
|
+
This rule checks for:
|
|
37
|
+
|
|
38
|
+
- Destructuring at a nesting level above 3.
|
|
39
|
+
- Destructuring of more than the specified maximum number of variables (default is 2).
|
|
40
|
+
- Destructuring on a line exceeding the specified maximum line length (default is 100 characters).
|
|
41
|
+
|
|
42
|
+
#### Configuration
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"rules": {
|
|
47
|
+
"eslint-plugin-th-rules/no-destructuring": ["error", { "maximumDestructuredVariables": 2, "maximumLineLength": 100 }]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Name-Export Rule
|
|
53
|
+
|
|
54
|
+
**Rule ID:** `eslint-plugin-th-rules/no-unamed-default-export`
|
|
55
|
+
|
|
56
|
+
#### Description
|
|
57
|
+
|
|
58
|
+
Converts unnamed default exports to named default exports based on the file name. This rule helps maintain consistency in export names and facilitates easier identification of components or modules.
|
|
59
|
+
|
|
60
|
+
#### Rule Details
|
|
61
|
+
|
|
62
|
+
This rule targets unnamed default exports and automatically generates a named export based on the file name.
|
|
63
|
+
|
|
64
|
+
#### Configuration
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"rules": {
|
|
68
|
+
"eslint-plugin-th-rules/no-unamed-default-export": "error"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Installation
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"plugins": [
|
|
77
|
+
"eslint-plugin-th-rules"
|
|
78
|
+
],
|
|
79
|
+
"rules": {
|
|
80
|
+
"eslint-plugin-th-rules/no-destructuring": "error",
|
|
81
|
+
"eslint-plugin-th-rules/no-unamed-default-export": "error"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## 1. Purpose
|
|
4
|
+
|
|
5
|
+
This document provides guidelines and procedures for maintaining the security and integrity of the repository.
|
|
6
|
+
|
|
7
|
+
## 2. Scope
|
|
8
|
+
|
|
9
|
+
This policy applies to all contributors, maintainers, and users of the repository.
|
|
10
|
+
|
|
11
|
+
## 3. Repository Security
|
|
12
|
+
|
|
13
|
+
### 3.1. Access Control
|
|
14
|
+
|
|
15
|
+
- Access to the repository is restricted to authorized personnel only. All contributors must have a valid and active GitHub account.
|
|
16
|
+
- External collaborators should be granted access on a need-to-know basis and should be reviewed periodically.
|
|
17
|
+
|
|
18
|
+
### 3.2. Encryption
|
|
19
|
+
|
|
20
|
+
- All sensitive data stored in this repo must be encrypted using `git-crypt`.
|
|
21
|
+
- Authorized users will be provided with decryption keys. These keys must not be shared, stored publicly, or embedded in code.
|
|
22
|
+
|
|
23
|
+
### 3.3. Code Review
|
|
24
|
+
|
|
25
|
+
- All pull requests (PRs) must undergo a code review by at least one other member before being merged.
|
|
26
|
+
- PRs with changes to cryptographic routines or handling of encrypted data must be reviewed by a security expert.
|
|
27
|
+
|
|
28
|
+
## 4. Reporting Security Issues
|
|
29
|
+
|
|
30
|
+
- If you discover a vulnerability or security issue, please create an issue on the GitHub repository. Label it as `security` for easy identification.
|
|
31
|
+
- Do not disclose details of the vulnerability in public forums, chats, or other public channels.
|
|
32
|
+
|
|
33
|
+
## 5. Patch Management
|
|
34
|
+
|
|
35
|
+
- All contributors are encouraged to regularly fetch updates from the main branch and ensure their local copy is updated to benefit from security patches.
|
|
36
|
+
|
|
37
|
+
## 6. Compliance
|
|
38
|
+
|
|
39
|
+
- Contributors found to be in violation of this policy may have their access revoked.
|
|
40
|
+
- Users and maintainers are encouraged to report any non-compliance to this policy.
|
|
41
|
+
|
|
42
|
+
## 7. Review and Updates
|
|
43
|
+
|
|
44
|
+
This policy will be reviewed annually or after any significant incident.
|
|
45
|
+
|
|
46
|
+
## 8. Contact
|
|
47
|
+
|
|
48
|
+
For any queries or concerns regarding this security policy, eat a biscuit. (tomerh2001@gmail.com)
|
package/bun.lockb
ADDED
|
Binary file
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview A List of custom ESLint rules created by Tomer Horowitz
|
|
3
|
+
* @author Tomer Horowitz
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
//------------------------------------------------------------------------------
|
|
8
|
+
// Requirements
|
|
9
|
+
//------------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
const requireIndex = require('requireindex');
|
|
12
|
+
|
|
13
|
+
//------------------------------------------------------------------------------
|
|
14
|
+
// Plugin Definition
|
|
15
|
+
//------------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
// import all rules in lib/rules
|
|
18
|
+
module.exports.rules = requireIndex(__dirname + '/rules');
|
|
19
|
+
module.exports.configs = {
|
|
20
|
+
all: {
|
|
21
|
+
plugins: ['eslint-plugin-th-rules'],
|
|
22
|
+
rules: {
|
|
23
|
+
'eslint-plugin-th-rules/no-destructuring': 'error',
|
|
24
|
+
'eslint-plugin-th-rules/no-unamed-default-export': 'error',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const MAX_TAB_COUNT = 3;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents the metadata for the "no-destruction" ESLint rule.
|
|
5
|
+
*
|
|
6
|
+
* @type {Object}
|
|
7
|
+
* @property {string} type - The type of the rule.
|
|
8
|
+
* @property {Object} docs - The documentation for the rule.
|
|
9
|
+
* @property {string} docs.description - The description of the rule.
|
|
10
|
+
* @property {string} docs.category - The category of the rule.
|
|
11
|
+
* @property {boolean} docs.recommended - Indicates if the rule is recommended.
|
|
12
|
+
* @property {Object[]} schema - The schema for the rule options.
|
|
13
|
+
* @property {Object} schema[].properties - The properties of the rule options.
|
|
14
|
+
* @property {number} schema[].properties.maximumDestructuredVariables - The maximum number of destructured variables allowed.
|
|
15
|
+
* @property {number} schema[].properties.maximumLineLength - The maximum line length allowed.
|
|
16
|
+
*/
|
|
17
|
+
const meta = {
|
|
18
|
+
type: 'problem',
|
|
19
|
+
docs: {
|
|
20
|
+
description: 'Disallow destructuring that does not meet certain conditions',
|
|
21
|
+
category: 'Possible Errors',
|
|
22
|
+
recommended: true,
|
|
23
|
+
},
|
|
24
|
+
schema: [
|
|
25
|
+
{
|
|
26
|
+
type: 'object',
|
|
27
|
+
properties: {
|
|
28
|
+
maximumDestructuredVariables: {
|
|
29
|
+
type: 'integer',
|
|
30
|
+
minimum: 0,
|
|
31
|
+
},
|
|
32
|
+
maximumLineLength: {
|
|
33
|
+
type: 'integer',
|
|
34
|
+
minimum: 0,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
additionalProperties: false,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Creates an ESLint rule that checks for excessive destructuring in variable declarations.
|
|
44
|
+
* @param {Object} context - The ESLint rule context.
|
|
45
|
+
* @returns {Object} - The ESLint rule object.
|
|
46
|
+
*/
|
|
47
|
+
function create(context) {
|
|
48
|
+
const MAX_VARIABLES = context?.options[0]?.maximumDestructuredVariables || 2;
|
|
49
|
+
const MAX_LINE_LENGTH = context?.options[0]?.maximumLineLength || 100;
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
VariableDeclarator(node) {
|
|
53
|
+
const sourceCode = context.getSourceCode();
|
|
54
|
+
const line = sourceCode.lines[node.loc.start.line - 1];
|
|
55
|
+
const lineLength = line.length;
|
|
56
|
+
const tabCount = line.search(/\S|$/);
|
|
57
|
+
|
|
58
|
+
if (node?.id?.type !== 'ObjectPattern') {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Check for the number of destructured variables and the nesting level
|
|
63
|
+
if (tabCount > MAX_TAB_COUNT) {
|
|
64
|
+
context.report({
|
|
65
|
+
node,
|
|
66
|
+
message: `Destruction at a nesting level above ${MAX_TAB_COUNT} is not allowed, instead saw ${tabCount} levels of nesting`,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Check for the number of destructured variables
|
|
71
|
+
if (node?.id?.properties?.length > MAX_VARIABLES) {
|
|
72
|
+
context.report({
|
|
73
|
+
node,
|
|
74
|
+
message: `Destruction of more than ${MAX_VARIABLES} variables is not allowed`,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Check for the line length
|
|
79
|
+
if (lineLength > MAX_LINE_LENGTH) {
|
|
80
|
+
context.report({
|
|
81
|
+
node,
|
|
82
|
+
message: `Destruction on a line exceeding ${MAX_LINE_LENGTH} characters is not allowed`,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const rule = {
|
|
90
|
+
meta,
|
|
91
|
+
create,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
module.exports = rule;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const path = require('node:path');
|
|
2
|
+
|
|
3
|
+
const meta = {
|
|
4
|
+
type: 'suggestion',
|
|
5
|
+
docs: {
|
|
6
|
+
description: 'Convert unnamed default exports to named default exports based on the file name.',
|
|
7
|
+
},
|
|
8
|
+
fixable: 'code',
|
|
9
|
+
schema: [],
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function create(context) {
|
|
13
|
+
function generateExportNameFromFileName(fileName) {
|
|
14
|
+
return fileName.replaceAll(/^\w|[A-Z]|\b\w|\s+/g, (match, index) => {
|
|
15
|
+
if (match === ' ') {
|
|
16
|
+
return '';
|
|
17
|
+
} // Remove spaces
|
|
18
|
+
|
|
19
|
+
if (index === 0) {
|
|
20
|
+
return match.toLowerCase();
|
|
21
|
+
} // Lowercase the first character
|
|
22
|
+
|
|
23
|
+
return match.toUpperCase();
|
|
24
|
+
})
|
|
25
|
+
.replaceAll(/[-_]/g, '')
|
|
26
|
+
.replaceAll('<', '')
|
|
27
|
+
.replaceAll('>', '');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
ExportDefaultDeclaration(node) {
|
|
32
|
+
// If the export declaration is an identifier (e.g., a variable name), it's considered named.
|
|
33
|
+
if (node.declaration.type === 'Identifier') {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Existing check for function or class declarations that are named
|
|
38
|
+
if (node.declaration.id) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const fileName = context.getFilename();
|
|
43
|
+
const exportName = generateExportNameFromFileName(path.basename(fileName, path.extname(fileName)));
|
|
44
|
+
|
|
45
|
+
context.report({
|
|
46
|
+
node,
|
|
47
|
+
message: 'Unnamed default export should be named based on the file name.',
|
|
48
|
+
fix(fixer) {
|
|
49
|
+
const sourceCode = context.getSourceCode();
|
|
50
|
+
const declarationText = sourceCode.getText(node.declaration);
|
|
51
|
+
const fixedCode = `const ${exportName} = ${declarationText};\nexport default ${exportName};`;
|
|
52
|
+
|
|
53
|
+
return fixer.replaceText(node, fixedCode);
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const rule = {
|
|
61
|
+
meta,
|
|
62
|
+
create,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
module.exports = rule;
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eslint-plugin-th-rules",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "A List of custom ESLint rules created by Tomer Horowitz",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"eslint",
|
|
7
|
+
"eslintplugin",
|
|
8
|
+
"eslint-plugin"
|
|
9
|
+
],
|
|
10
|
+
"author": "Tomer Horowitz",
|
|
11
|
+
"main": "./lib/index.js",
|
|
12
|
+
"exports": "./lib/index.js",
|
|
13
|
+
"scripts": {
|
|
14
|
+
"lint": "npm-run-all \"lint:*\"",
|
|
15
|
+
"lint:eslint-docs": "npm-run-all \"update:eslint-docs -- --check\"",
|
|
16
|
+
"lint:js": "eslint .",
|
|
17
|
+
"test": "xo && mocha tests --recursive",
|
|
18
|
+
"update:eslint-docs": "eslint-doc-generator"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"requireindex": "^1.2.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@codedependant/semantic-release-docker": "^4.4.0",
|
|
25
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
26
|
+
"@semantic-release/commit-analyzer": "^11.0.0",
|
|
27
|
+
"@semantic-release/git": "^10.0.1",
|
|
28
|
+
"@semantic-release/github": "^9.2.1",
|
|
29
|
+
"@semantic-release/npm": "^11.0.0",
|
|
30
|
+
"@semantic-release/release-notes-generator": "^12.0.0",
|
|
31
|
+
"bun-types": "latest",
|
|
32
|
+
"eslint": "^8.19.0",
|
|
33
|
+
"eslint-doc-generator": "^1.0.0",
|
|
34
|
+
"eslint-plugin-eslint-plugin": "^5.0.0",
|
|
35
|
+
"eslint-plugin-node": "^11.1.0",
|
|
36
|
+
"mocha": "^10.0.0",
|
|
37
|
+
"npm-run-all": "^4.1.5",
|
|
38
|
+
"xo": "^0.57.0"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">= 20.11.0"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"eslint": ">=7",
|
|
45
|
+
"typescript": "^5.0.0"
|
|
46
|
+
},
|
|
47
|
+
"license": "ISC",
|
|
48
|
+
"packageManager": "yarn@4.1.0"
|
|
49
|
+
}
|
package/renovate.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const {RuleTester} = require('eslint');
|
|
2
|
+
const rule = require('../../../lib/rules/no-destruction.js');
|
|
3
|
+
|
|
4
|
+
const ruleTester = new RuleTester({
|
|
5
|
+
parserOptions: {
|
|
6
|
+
ecmaVersion: 2020, // ES6 syntax
|
|
7
|
+
sourceType: 'module', // Allows the use of imports
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
ruleTester.run('no-destruction', rule, {
|
|
12
|
+
valid: [
|
|
13
|
+
{
|
|
14
|
+
code: 'const { a, b } = obj;',
|
|
15
|
+
options: [{maximumDestructuredVariables: 3, maximumLineLength: 80}],
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
code: 'const { a } = obj;',
|
|
19
|
+
options: [{maximumDestructuredVariables: 2, maximumLineLength: 80}],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
code: 'const { a, b, c } = obj;',
|
|
23
|
+
options: [{maximumDestructuredVariables: 3, maximumLineLength: 30}],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
code: 'function foo() {\n\tconst { a, b } = obj;\n}',
|
|
27
|
+
options: [{maximumDestructuredVariables: 3, maximumLineLength: 80}],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
code: '\tconst { a, b } = obj;',
|
|
31
|
+
options: [{maximumDestructuredVariables: 3, maximumLineLength: 80}],
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
invalid: [
|
|
35
|
+
{
|
|
36
|
+
code: 'const { a, b, c } = obj;',
|
|
37
|
+
options: [{maximumDestructuredVariables: 2, maximumLineLength: 80}],
|
|
38
|
+
errors: [{message: 'Destruction of more than 2 variables is not allowed'}],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
code: 'const { a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z } = obj;',
|
|
42
|
+
options: [{maximumDestructuredVariables: 3, maximumLineLength: 80}],
|
|
43
|
+
errors: [{message: 'Destruction of more than 3 variables is not allowed'}, {message: 'Destruction on a line exceeding 80 characters is not allowed'}],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
code: 'function foo() {\n\t\t\t\t\t\t\tconst { a, b } = obj;\n}',
|
|
47
|
+
options: [{maximumDestructuredVariables: 3, maximumLineLength: 80}],
|
|
48
|
+
errors: [{message: 'Destruction at a nesting level above 3 is not allowed, instead saw 7 levels of nesting'}],
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const {RuleTester} = require('eslint');
|
|
2
|
+
const rule = require('../../../lib/rules/no-unamed-default-export.js');
|
|
3
|
+
|
|
4
|
+
const ruleTester = new RuleTester({
|
|
5
|
+
parserOptions: {
|
|
6
|
+
ecmaVersion: 2020,
|
|
7
|
+
sourceType: 'module',
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
ruleTester.run('no-unamed-default-export', rule, {
|
|
12
|
+
valid: [
|
|
13
|
+
// Already named exports should pass
|
|
14
|
+
'const a = 1; export default a;',
|
|
15
|
+
'export default function foo() {}',
|
|
16
|
+
'export default class Foo {}',
|
|
17
|
+
],
|
|
18
|
+
invalid: [
|
|
19
|
+
// Function exports without a name
|
|
20
|
+
{
|
|
21
|
+
code: 'export default function () {}',
|
|
22
|
+
output: 'const Input = function () {};\nexport default Input;',
|
|
23
|
+
errors: [{message: 'Unnamed default export should be named based on the file name.'}],
|
|
24
|
+
},
|
|
25
|
+
// Class exports without a name
|
|
26
|
+
{
|
|
27
|
+
code: 'export default class {}',
|
|
28
|
+
output: 'const Input = class {};\nexport default Input;',
|
|
29
|
+
errors: [{message: 'Unnamed default export should be named based on the file name.'}],
|
|
30
|
+
},
|
|
31
|
+
// Object literal exports
|
|
32
|
+
{
|
|
33
|
+
code: 'export default {}',
|
|
34
|
+
output: 'const Input = {};\nexport default Input;',
|
|
35
|
+
errors: [{message: 'Unnamed default export should be named based on the file name.'}],
|
|
36
|
+
},
|
|
37
|
+
// Primitive value exports
|
|
38
|
+
{
|
|
39
|
+
code: 'export default 42',
|
|
40
|
+
output: 'const Input = 42;\nexport default Input;',
|
|
41
|
+
errors: [{message: 'Unnamed default export should be named based on the file name.'}],
|
|
42
|
+
},
|
|
43
|
+
// Null exports
|
|
44
|
+
{
|
|
45
|
+
code: 'export default null',
|
|
46
|
+
output: 'const Input = null;\nexport default Input;',
|
|
47
|
+
errors: [{message: 'Unnamed default export should be named based on the file name.'}],
|
|
48
|
+
},
|
|
49
|
+
// Arrow function exports
|
|
50
|
+
{
|
|
51
|
+
code: 'export default () => {}',
|
|
52
|
+
output: 'const Input = () => {};\nexport default Input;',
|
|
53
|
+
errors: [{message: 'Unnamed default export should be named based on the file name.'}],
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"lib": ["ESNext"],
|
|
4
|
+
"module": "esnext",
|
|
5
|
+
"target": "esnext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"allowImportingTsExtensions": true,
|
|
9
|
+
"noEmit": true,
|
|
10
|
+
"composite": true,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"downlevelIteration": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"jsx": "react-jsx",
|
|
15
|
+
"allowSyntheticDefaultImports": true,
|
|
16
|
+
"forceConsistentCasingInFileNames": true,
|
|
17
|
+
"allowJs": true,
|
|
18
|
+
"types": [
|
|
19
|
+
"bun-types" // add Bun global
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
}
|