eslint-plugin-th-rules 1.14.1 → 1.15.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/.yarnrc.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  nodeLinker: node-modules
2
2
 
3
- yarnPath: .yarn/releases/yarn-4.4.0.cjs
3
+ yarnPath: .yarn/releases/yarn-4.6.0.cjs
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [1.15.0](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v1.14.1...v1.15.0) (2024-12-30)
2
+
3
+
4
+ ### Features
5
+
6
+ * add top-level functions rule and update ESLint configuration ([49e5ebb](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/49e5ebbf597615e508a8b0067d8ca263d73f0469))
7
+
1
8
  ## [1.14.1](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v1.14.0...v1.14.1) (2024-12-30)
2
9
 
3
10
 
package/README.md CHANGED
@@ -18,11 +18,12 @@ This repository contains custom ESLint rules to enhance code quality and consist
18
18
  ✅ Set in the `recommended` configuration.\
19
19
  🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).
20
20
 
21
- | Name              | Description | 💼 | 🔧 |
22
- | :--------------------------------------------------- | :------------------------------------------------------------------------------- | :--------------------------------------------------------------- | :- |
23
- | [no-comments](docs/rules/no-comments.md) | Disallow comments except for specified allowed patterns. | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | 🔧 |
24
- | [no-default-export](docs/rules/no-default-export.md) | Convert unnamed default exports to named default exports based on the file name. | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | 🔧 |
25
- | [no-destructuring](docs/rules/no-destructuring.md) | Disallow destructuring that does not meet certain conditions | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | |
21
+ | Name                | Description | 💼 | 🔧 |
22
+ | :------------------------------------------------------- | :------------------------------------------------------------------------------- | :--------------------------------------------------------------- | :- |
23
+ | [no-comments](docs/rules/no-comments.md) | Disallow comments except for specified allowed patterns. | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | 🔧 |
24
+ | [no-default-export](docs/rules/no-default-export.md) | Convert unnamed default exports to named default exports based on the file name. | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | 🔧 |
25
+ | [no-destructuring](docs/rules/no-destructuring.md) | Disallow destructuring that does not meet certain conditions | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | |
26
+ | [top-level-functions](docs/rules/top-level-functions.md) | Require all top-level functions to be named/regular functions. | | 🔧 |
26
27
 
27
28
  <!-- end auto-generated rules list -->
28
29
 
package/bun.lockb CHANGED
Binary file
@@ -0,0 +1,47 @@
1
+ # Require all top-level functions to be named/regular functions (`th-rules/top-level-functions`)
2
+
3
+ 🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ ## Description
8
+
9
+ This rule requires all top-level functions to be named/regular functions, preventing the use of arrow functions at the top level. This rule aims to improve code readability and maintainability by enforcing consistent function declaration styles.
10
+
11
+ ## Rule Details
12
+
13
+ This rule checks for arrow functions at the top level and reports them as errors.
14
+
15
+ Examples of **incorrect** code for this rule:
16
+
17
+ ```js
18
+ const myFunction = () => {
19
+ // Function body
20
+ };
21
+ ```
22
+
23
+ Examples of **correct** code for this rule:
24
+
25
+ ```js
26
+ function myFunction() {
27
+ // Function body
28
+ }
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ```json
34
+ {
35
+ "rules": {
36
+ "th-rules/top-level-functions": "error"
37
+ }
38
+ }
39
+ ```
40
+
41
+ ## Options
42
+
43
+ This rule has no options.
44
+
45
+ ## When Not To Use It
46
+
47
+ If you do not want to enforce consistent function declaration styles, you can disable this rule.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-th-rules",
3
- "version": "1.14.1",
3
+ "version": "1.15.0",
4
4
  "description": "A List of custom ESLint rules created by Tomer Horowitz",
5
5
  "keywords": [
6
6
  "eslint",
@@ -49,6 +49,7 @@
49
49
  "eslint-plugin-eslint-plugin": "^6.4.0",
50
50
  "eslint-plugin-node": "^11.1.0",
51
51
  "eslint-plugin-sonarjs": "^3.0.1",
52
+ "eslint-plugin-th-rules": "1.14.1",
52
53
  "eslint-plugin-unicorn": "^56.0.1",
53
54
  "mocha": "^11.0.1",
54
55
  "npm-run-all": "^4.1.5",
@@ -61,5 +62,5 @@
61
62
  "typescript": "^5.7.2"
62
63
  },
63
64
  "license": "ISC",
64
- "packageManager": "yarn@4.4.0"
65
+ "packageManager": "yarn@4.6.0"
65
66
  }
@@ -5,7 +5,7 @@ const allowedPatterns = [
5
5
  /warning/i, // Allow WARNING (case-insensitive)
6
6
  /error/i, // Allow ERROR (case-insensitive)
7
7
  /info/i, // Allow INFO (case-insensitive)
8
- /^\s*eslint-(disable|enable|env|globals|ignore|directive)/, // Allow ESLint directives
8
+ /^\s*eslint-(disable|enable|env|globals|ignore|directive)/,
9
9
  ];
10
10
 
11
11
  const meta = {
@@ -47,26 +47,23 @@ function create(context) {
47
47
  function isCommentAllowed(comment) {
48
48
  const text = comment.value.trim();
49
49
 
50
- // Check if the comment is a valid JSDoc comment
51
50
  if (comment.type === 'Block' && comment.value.startsWith('*')) {
52
- return true; // Allow any JSDoc-style block comment (/** ... */)
51
+ return true;
53
52
  }
54
53
 
55
- // Check if the comment matches any allowed pattern
56
54
  for (const pattern of [...allowedPatterns, ...userAllowedPatterns]) {
57
55
  if (pattern.test(text)) {
58
56
  return true;
59
57
  }
60
58
  }
61
59
 
62
- // Check if the comment matches any disallowed pattern
63
60
  for (const pattern of userDisallowedPatterns) {
64
61
  if (pattern.test(text)) {
65
62
  return false;
66
63
  }
67
64
  }
68
65
 
69
- return false; // Disallow by default if no match
66
+ return false;
70
67
  }
71
68
 
72
69
  return {
@@ -17,11 +17,11 @@ function create(context) {
17
17
  return fileName.replaceAll(/^\w|[A-Z]|\b\w|\s+/g, (match, index) => {
18
18
  if (match === ' ') {
19
19
  return '';
20
- } // Remove spaces
20
+ }
21
21
 
22
22
  if (index === 0) {
23
23
  return match.toLowerCase();
24
- } // Lowercase the first character
24
+ }
25
25
 
26
26
  return match.toUpperCase();
27
27
  })
@@ -30,12 +30,10 @@ function create(context) {
30
30
 
31
31
  return {
32
32
  ExportDefaultDeclaration(node) {
33
- // If the export declaration is an identifier (e.g., a variable name), it's considered named.
34
33
  if (node.declaration.type === 'Identifier') {
35
34
  return;
36
35
  }
37
36
 
38
- // Existing check for function or class declarations that are named
39
37
  if (node.declaration.id) {
40
38
  return;
41
39
  }
@@ -60,7 +60,6 @@ function create(context) {
60
60
  return;
61
61
  }
62
62
 
63
- // Check for the number of destructured variables and the nesting level
64
63
  if (tabCount > MAX_TAB_COUNT) {
65
64
  context.report({
66
65
  node,
@@ -68,7 +67,6 @@ function create(context) {
68
67
  });
69
68
  }
70
69
 
71
- // Check for the number of destructured variables
72
70
  if (node?.id?.properties?.length > MAX_VARIABLES) {
73
71
  context.report({
74
72
  node,
@@ -76,7 +74,6 @@ function create(context) {
76
74
  });
77
75
  }
78
76
 
79
- // Check for the line length
80
77
  if (lineLength > MAX_LINE_LENGTH) {
81
78
  context.report({
82
79
  node,
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @type {Object}
3
+ * @property {string} type - The type of the rule, in this case 'suggestion'.
4
+ * @property {Object} docs - Documentation related to the rule.
5
+ * @property {string} docs.description - A brief description of the rule.
6
+ * @property {string} docs.category - The category of the rule, here 'Stylistic Issues'.
7
+ * @property {boolean} docs.recommended - Indicates whether the rule is recommended.
8
+ * @property {string} docs.url - The URL to the documentation of the rule.
9
+ * @property {string} fixable - Indicates if the rule is fixable, in this case 'code'.
10
+ * @property {Array} schema - The schema for the rule options.
11
+ */
12
+ const meta = {
13
+ type: 'suggestion',
14
+ docs: {
15
+ description: 'Require all top-level functions to be named/regular functions.',
16
+ category: 'Stylistic Issues',
17
+ recommended: false,
18
+ url: 'https://github.com/tomerh2001/eslint-plugin-th-rules/blob/main/docs/rules/top-level-functions.md',
19
+ },
20
+ fixable: 'code',
21
+ schema: [],
22
+ };
23
+
24
+ /**
25
+ * ESLint rule to enforce naming of top-level functions.
26
+ *
27
+ * @param {Object} context - The ESLint rule context.
28
+ * @returns {Object} An object containing the rule's visitor methods.
29
+ */
30
+ function create(context) {
31
+ return {
32
+
33
+ VariableDeclaration(node) {
34
+ if (node.parent.type !== 'Program') {
35
+ return;
36
+ }
37
+
38
+ for (const declaration of node.declarations) {
39
+ if (
40
+ declaration.init
41
+ && (declaration.init.type === 'ArrowFunctionExpression'
42
+ || declaration.init.type === 'FunctionExpression')
43
+ ) {
44
+ context.report({
45
+ node: declaration,
46
+ message: 'Top-level functions must be named/regular functions.',
47
+ fix(fixer) {
48
+ const sourceCode = context.getSourceCode();
49
+ const functionText = sourceCode.getText(declaration.init);
50
+ const functionName = declaration.id.name;
51
+ const fixedCode = `function ${functionName}${functionText.slice(functionText.indexOf('('))}`;
52
+ return fixer.replaceText(declaration, fixedCode);
53
+ },
54
+ });
55
+ }
56
+ }
57
+ },
58
+
59
+ FunctionDeclaration(node) {
60
+ if (node.id) {
61
+ return;
62
+ }
63
+
64
+ if (node.parent.type === 'Program') {
65
+ context.report({
66
+ node,
67
+ message: 'Top-level functions must be named.',
68
+ fix(fixer) {
69
+ const sourceCode = context.getSourceCode();
70
+ const functionName = 'defaultFunction';
71
+ const functionText = sourceCode.getText(node);
72
+
73
+ const fixedCode = functionText.replace('function (', `function ${functionName}(`);
74
+
75
+ return fixer.replaceText(node, fixedCode);
76
+ },
77
+ });
78
+ }
79
+ },
80
+ };
81
+ }
82
+
83
+ const rule = {
84
+ meta,
85
+ create,
86
+ };
87
+
88
+ module.exports = rule;
package/.eslintrc.js DELETED
@@ -1,19 +0,0 @@
1
- "use strict";
2
-
3
- module.exports = {
4
- root: true,
5
- extends: [
6
- "eslint:recommended",
7
- "plugin:eslint-plugin/recommended",
8
- "plugin:node/recommended",
9
- ],
10
- env: {
11
- node: true,
12
- },
13
- overrides: [
14
- {
15
- files: ["tests/**/*.js"],
16
- env: { mocha: true },
17
- },
18
- ],
19
- };