eslint-plugin-wyrm 0.0.4 → 0.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 (37) hide show
  1. package/CHANGELOG.md +7 -12
  2. package/README.md +47 -15
  3. package/dist/configs/index.d.ts +2 -2
  4. package/dist/configs/index.js +6 -7
  5. package/dist/index.d.ts +5 -1
  6. package/dist/plugin.js +0 -2
  7. package/dist/rules/index.d.ts +15 -4
  8. package/dist/rules/index.js +22 -0
  9. package/dist/rules/no-constant-template-expression.d.ts +10 -0
  10. package/dist/rules/no-constant-template-expression.js +82 -0
  11. package/dist/rules/no-else-break.d.ts +7 -0
  12. package/dist/rules/no-else-break.js +51 -0
  13. package/dist/rules/no-else-continue.d.ts +7 -0
  14. package/dist/rules/no-else-continue.js +51 -0
  15. package/dist/rules/no-else-throw.d.ts +7 -0
  16. package/dist/rules/no-else-throw.js +51 -0
  17. package/dist/rules/no-empty-comment.d.ts +9 -0
  18. package/dist/rules/no-empty-comment.js +57 -0
  19. package/dist/rules/no-empty-jsx-expression.d.ts +7 -0
  20. package/dist/rules/no-empty-jsx-expression.js +51 -0
  21. package/dist/rules/no-extra-nested-boolean-cast.d.ts +2 -2
  22. package/dist/rules/no-invalid-date-literal.d.ts +7 -0
  23. package/dist/rules/no-invalid-date-literal.js +68 -0
  24. package/dist/rules/no-jsx-statement.d.ts +2 -2
  25. package/dist/rules/no-suspicious-jsx-semicolon.d.ts +8 -0
  26. package/dist/rules/no-suspicious-jsx-semicolon.js +39 -0
  27. package/dist/rules/no-ternary-return.d.ts +9 -0
  28. package/dist/rules/no-ternary-return.js +51 -0
  29. package/dist/rules/no-useless-iife.d.ts +7 -0
  30. package/dist/rules/no-useless-iife.js +93 -0
  31. package/dist/rules/prefer-repeat.d.ts +7 -0
  32. package/dist/rules/prefer-repeat.js +108 -0
  33. package/dist/utils/option.js +18 -0
  34. package/package.json +3 -1
  35. package/docs/rules/no-extra-nested-boolean-cast.md +0 -110
  36. package/docs/rules/no-jsx-statement.md +0 -36
  37. package/docs/rules/unsafe-asserted-chain.md +0 -68
package/CHANGELOG.md CHANGED
@@ -1,27 +1,22 @@
1
1
  # Changelog
2
2
 
3
- ## [0.0.4](https://github.com/mchevestrier/eslint-plugin-wyrm/compare/eslint-plugin-wyrm-v0.0.3...eslint-plugin-wyrm-v0.0.4) (2025-11-01)
3
+ ## [0.0.6](https://github.com/mchevestrier/eslint-plugin-wyrm/compare/eslint-plugin-wyrm-v0.0.5...eslint-plugin-wyrm-v0.0.6) (2025-11-04)
4
4
 
5
5
 
6
6
  ### Bug Fixes
7
7
 
8
- * improve no-extra-nested-boolean-cast ([333d0f3](https://github.com/mchevestrier/eslint-plugin-wyrm/commit/333d0f3bcc3aa73a329bb9ff60189490f96813cd))
8
+ * add no-else-break and no-else-continue ([eb2647f](https://github.com/mchevestrier/eslint-plugin-wyrm/commit/eb2647feb3a5d04782a86db8324259afb70a5369))
9
+ * add no-else-throw ([cedc18e](https://github.com/mchevestrier/eslint-plugin-wyrm/commit/cedc18efd6952c3c3195d378dbd59a8772b7613d))
9
10
 
10
- ## [0.0.3](https://github.com/mchevestrier/eslint-plugin-wyrm/compare/eslint-plugin-wyrm-v0.0.2...eslint-plugin-wyrm-v0.0.3) (2025-10-26)
11
+ ## [0.0.5](https://github.com/mchevestrier/eslint-plugin-wyrm/compare/eslint-plugin-wyrm-v0.0.4...eslint-plugin-wyrm-v0.0.5) (2025-11-02)
11
12
 
12
13
 
13
14
  ### Bug Fixes
14
15
 
15
- * ignore CHANGELOG.md formatting ([f6a923c](https://github.com/mchevestrier/eslint-plugin-wyrm/commit/f6a923c348be8c2976635ae64a45c75932faba60))
16
-
17
- ## 0.0.2 (2025-10-26)
16
+ * add no-ternary-return ([4e029be](https://github.com/mchevestrier/eslint-plugin-wyrm/commit/4e029be3f157601bbbb5b9cb854a526ad88b2c1e))
18
17
 
18
+ ## [0.0.4](https://github.com/mchevestrier/eslint-plugin-wyrm/compare/eslint-plugin-wyrm-v0.0.3...eslint-plugin-wyrm-v0.0.4) (2025-11-01)
19
19
 
20
20
  ### Bug Fixes
21
21
 
22
- * rule doc url ([1ae7be1](https://github.com/mchevestrier/eslint-plugin-wyrm/commit/1ae7be12ffa2811f22909b36b415061ddf890a2b))
23
-
24
-
25
- ### Miscellaneous Chores
26
-
27
- * Merge npm-publish.yml with release.yml ([fba85e8](https://github.com/mchevestrier/eslint-plugin-wyrm/commit/fba85e8ff67e5274aedb63db60756a5a41ab010f))
22
+ - improve no-extra-nested-boolean-cast ([333d0f3](https://github.com/mchevestrier/eslint-plugin-wyrm/commit/333d0f3bcc3aa73a329bb9ff60189490f96813cd))
package/README.md CHANGED
@@ -4,16 +4,35 @@
4
4
  [![GitHub release](https://img.shields.io/github/v/release/mchevestrier/eslint-plugin-wyrm?color=7f52af&labelColor=26272b)](https://github.com/mchevestrier/eslint-plugin-wyrm/releases/latest)
5
5
  [![GitHub License](https://img.shields.io/badge/license-MIT-232428.svg?color=7f52af&labelColor=26272b)](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/main/LICENSE.md)
6
6
 
7
+ ## Installation
8
+
9
+ ```shell
10
+ npm install --save-dev eslint eslint-plugin-wyrm
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```ts
16
+ import { defineConfig } from 'eslint/config';
17
+ import wyrm from 'eslint-plugin-wyrm';
18
+
19
+ export default defineConfig([
20
+ // ...
21
+
22
+ wyrm.configs.recommended,
23
+ ]);
24
+ ```
25
+
7
26
  ## Configs
8
27
 
9
28
  <!-- begin auto-generated configs list -->
10
29
 
11
- | | Name |
12
- | :-- | :---------------------------- |
13
- | | `wyrm/recommended` |
14
- | ☑️ | `wyrm/recommendedTypeChecked` |
15
- | 🟢 | `wyrm/strict` |
16
- | 🟣 | `wyrm/strictTypeChecked` |
30
+ | | Name |
31
+ | :-- | :----------------------- |
32
+ | 🟩 | `recommended` |
33
+ | | `recommendedTypeChecked` |
34
+ | 🟪 | `strict` |
35
+ | ☑️ | `strictTypeChecked` |
17
36
 
18
37
  <!-- end auto-generated configs list -->
19
38
 
@@ -22,16 +41,29 @@
22
41
  <!-- begin auto-generated rules list -->
23
42
 
24
43
  💼 Configurations enabled in.\
25
- Set in the `wyrm/recommended` configuration.\
26
- ☑️ Set in the `wyrm/recommendedTypeChecked` configuration.\
27
- 🟢 Set in the `wyrm/strict` configuration.\
28
- 🟣 Set in the `wyrm/strictTypeChecked` configuration.\
44
+ 🟩 Set in the `recommended` configuration.\
45
+ Set in the `recommendedTypeChecked` configuration.\
46
+ 🟪 Set in the `strict` configuration.\
47
+ ☑️ Set in the `strictTypeChecked` configuration.\
48
+ 🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
49
+ 💡 Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).\
29
50
  💭 Requires [type information](https://typescript-eslint.io/linting/typed-linting).
30
51
 
31
- | Name                         | Description | 💼 | 💭 |
32
- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------- | :---------- | :-- |
33
- | [no-extra-nested-boolean-cast](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-extra-nested-boolean-cast.md) | Forbid extra boolean casts in conditions and predicates | 🟢 🟣 | |
34
- | [no-jsx-statement](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-jsx-statement.md) | Forbid JSX expression statements | ✅ ☑️ 🟢 🟣 | |
35
- | [unsafe-asserted-chain](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/unsafe-asserted-chain.md) | Disallow unsafe type assertions on optional chained expressions | 🟣 | 💭 |
52
+ | Name                            | Description | 💼 | 🔧 | 💡 | 💭 |
53
+ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------- | :---------- | :-- | :-- | :-- |
54
+ | [no-constant-template-expression](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-constant-template-expression.md) | Disallow constant string expressions in template literals | ☑️ | | 💡 | 💭 |
55
+ | [no-else-break](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-else-break.md) | Forbid unnecessary `else` block after a `break` statement | 🟩 🟪 ☑️ | 🔧 | | |
56
+ | [no-else-continue](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-else-continue.md) | Forbid unnecessary `else` block after a `continue` statement | 🟩 ✅ 🟪 ☑️ | 🔧 | | |
57
+ | [no-else-throw](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-else-throw.md) | Forbid unnecessary `else` block after a `throw` statement | 🟩 ✅ 🟪 ☑️ | 🔧 | | |
58
+ | [no-empty-comment](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-empty-comment.md) | Forbid empty comments | 🟪 ☑️ | | | |
59
+ | [no-empty-jsx-expression](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-empty-jsx-expression.md) | Forbid empty JSX expression containers | 🟩 ✅ 🟪 ☑️ | | | |
60
+ | [no-extra-nested-boolean-cast](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-extra-nested-boolean-cast.md) | Forbid extra boolean casts in conditions and predicates | 🟪 ☑️ | | | |
61
+ | [no-invalid-date-literal](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-invalid-date-literal.md) | Disallow invalid date literals | 🟩 ✅ 🟪 ☑️ | | | |
62
+ | [no-jsx-statement](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-jsx-statement.md) | Forbid JSX expression statements | 🟩 ✅ 🟪 ☑️ | | | |
63
+ | [no-suspicious-jsx-semicolon](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-suspicious-jsx-semicolon.md) | Forbid suspicious semicolons in JSX | 🟩 ✅ 🟪 ☑️ | | | |
64
+ | [no-ternary-return](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-ternary-return.md) | Disallow ternary conditions in return statements | 🟪 ☑️ | 🔧 | | |
65
+ | [no-useless-iife](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/no-useless-iife.md) | Forbid useless IIFEs | 🟩 ✅ 🟪 ☑️ | | 💡 | |
66
+ | [prefer-repeat](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/prefer-repeat.md) | Enforce usage of `String.prototype.repeat` | 🟩 ✅ 🟪 ☑️ | | 💡 | |
67
+ | [unsafe-asserted-chain](https://github.com/mchevestrier/eslint-plugin-wyrm/blob/master/packages/eslint-plugin-wyrm/docs/rules/unsafe-asserted-chain.md) | Disallow unsafe type assertions on optional chained expressions | ☑️ | | | 💭 |
36
68
 
37
69
  <!-- end auto-generated rules list -->
@@ -1,10 +1,10 @@
1
- import { Linter } from "eslint";
1
+ import { FlatConfig } from "@typescript-eslint/utils/ts-eslint";
2
2
 
3
3
  //#region lib/configs/index.d.ts
4
4
  declare namespace index_d_exports {
5
5
  export { all, recommended, recommendedTypeChecked, recommendedTypeCheckedOnly, strict, strictOnly, strictTypeChecked, strictTypeCheckedOnly };
6
6
  }
7
- type Config = Linter.Config;
7
+ type Config = FlatConfig.Config;
8
8
  declare const all: Config;
9
9
  declare const recommended: Config;
10
10
  declare const strictOnly: Config;
@@ -1,7 +1,6 @@
1
1
  import { __export } from "../_virtual/rolldown_runtime.js";
2
2
  import { rules_exports } from "../rules/index.js";
3
3
  import { plugin } from "../plugin.js";
4
- import { Linter } from "eslint";
5
4
 
6
5
  //#region lib/configs/index.ts
7
6
  var configs_exports = /* @__PURE__ */ __export({
@@ -17,12 +16,12 @@ var configs_exports = /* @__PURE__ */ __export({
17
16
  const baseConfig = { plugins: { get wyrm() {
18
17
  return plugin;
19
18
  } } };
20
- function createConfigWithRules(initialRules, name, pred) {
21
- const filteredRules = Object.entries(initialRules).filter(([, rule]) => pred(rule)).map(([name$1]) => [`wyrm/${name$1}`, "error"]);
19
+ function createConfigWithRules(initialRules, configName, pred) {
20
+ const filteredRules = Object.entries(initialRules).filter(([, rule]) => pred(rule)).map(([ruleName]) => [`wyrm/${ruleName}`, "error"]);
22
21
  const rules = Object.fromEntries(filteredRules);
23
22
  return {
24
23
  ...baseConfig,
25
- name: `wyrm/${name}`,
24
+ name: `wyrm/${configName}`,
26
25
  rules
27
26
  };
28
27
  }
@@ -39,7 +38,7 @@ const strictOnly = createConfigWithRules(rules_exports, "strictOnly", (rule) =>
39
38
  });
40
39
  const strict = {
41
40
  ...baseConfig,
42
- name: `wyrm/strict`,
41
+ name: "wyrm/strict",
43
42
  rules: {
44
43
  ...recommended.rules,
45
44
  ...strictOnly.rules
@@ -52,7 +51,7 @@ const recommendedTypeCheckedOnly = createConfigWithRules(rules_exports, "recomme
52
51
  });
53
52
  const recommendedTypeChecked = {
54
53
  ...baseConfig,
55
- name: `wyrm/recommendedTypeChecked`,
54
+ name: "wyrm/recommendedTypeChecked",
56
55
  rules: {
57
56
  ...recommended.rules,
58
57
  ...recommendedTypeCheckedOnly.rules
@@ -65,7 +64,7 @@ const strictTypeCheckedOnly = createConfigWithRules(rules_exports, "strictTypeCh
65
64
  });
66
65
  const strictTypeChecked = {
67
66
  ...baseConfig,
68
- name: `wyrm/strictTypeChecked`,
67
+ name: "wyrm/strictTypeChecked",
69
68
  rules: {
70
69
  ...recommendedTypeChecked.rules,
71
70
  ...strictOnly.rules,
package/dist/index.d.ts CHANGED
@@ -2,9 +2,13 @@ import { index_d_exports } from "./configs/index.js";
2
2
  import { index_d_exports as index_d_exports$1 } from "./rules/index.js";
3
3
 
4
4
  //#region lib/index.d.ts
5
+ interface CompatibleConfig {
6
+ name?: string;
7
+ rules?: object;
8
+ }
5
9
  declare const plugin: {
6
10
  rules: typeof index_d_exports$1;
7
- configs: typeof index_d_exports;
11
+ configs: Record<keyof typeof index_d_exports, CompatibleConfig>;
8
12
  };
9
13
  //#endregion
10
14
  export { plugin as default };
package/dist/plugin.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { rules_exports } from "./rules/index.js";
2
- import { configs_exports } from "./configs/index.js";
3
2
  import { createRequire } from "node:module";
4
3
 
5
4
  //#region lib/plugin.ts
@@ -9,7 +8,6 @@ const plugin = {
9
8
  name,
10
9
  version
11
10
  },
12
- configs: configs_exports,
13
11
  rules: rules_exports
14
12
  };
15
13
 
@@ -1,10 +1,21 @@
1
- import { _default } from "./no-extra-nested-boolean-cast.js";
2
- import { _default as _default$1 } from "./no-jsx-statement.js";
3
- import { _default as _default$2 } from "./unsafe-asserted-chain.js";
1
+ import { _default } from "./no-constant-template-expression.js";
2
+ import { _default as _default$1 } from "./no-else-break.js";
3
+ import { _default as _default$2 } from "./no-else-continue.js";
4
+ import { _default as _default$3 } from "./no-else-throw.js";
5
+ import { _default as _default$4 } from "./no-empty-comment.js";
6
+ import { _default as _default$5 } from "./no-empty-jsx-expression.js";
7
+ import { _default as _default$6 } from "./no-extra-nested-boolean-cast.js";
8
+ import { _default as _default$7 } from "./no-invalid-date-literal.js";
9
+ import { _default as _default$8 } from "./no-jsx-statement.js";
10
+ import { _default as _default$9 } from "./no-suspicious-jsx-semicolon.js";
11
+ import { _default as _default$10 } from "./no-ternary-return.js";
12
+ import { _default as _default$11 } from "./no-useless-iife.js";
13
+ import { _default as _default$12 } from "./prefer-repeat.js";
14
+ import { _default as _default$13 } from "./unsafe-asserted-chain.js";
4
15
 
5
16
  //#region lib/rules/index.d.ts
6
17
  declare namespace index_d_exports {
7
- export { _default as "no-extra-nested-boolean-cast", _default$1 as "no-jsx-statement", _default$2 as "unsafe-asserted-chain" };
18
+ export { _default as "no-constant-template-expression", _default$1 as "no-else-break", _default$2 as "no-else-continue", _default$3 as "no-else-throw", _default$4 as "no-empty-comment", _default$5 as "no-empty-jsx-expression", _default$6 as "no-extra-nested-boolean-cast", _default$7 as "no-invalid-date-literal", _default$8 as "no-jsx-statement", _default$9 as "no-suspicious-jsx-semicolon", _default$10 as "no-ternary-return", _default$11 as "no-useless-iife", _default$12 as "prefer-repeat", _default$13 as "unsafe-asserted-chain" };
8
19
  }
9
20
  //#endregion
10
21
  export { index_d_exports };
@@ -1,12 +1,34 @@
1
1
  import { __export } from "../_virtual/rolldown_runtime.js";
2
+ import no_constant_template_expression_default from "./no-constant-template-expression.js";
3
+ import no_else_break_default from "./no-else-break.js";
4
+ import no_else_continue_default from "./no-else-continue.js";
5
+ import no_else_throw_default from "./no-else-throw.js";
6
+ import no_empty_comment_default from "./no-empty-comment.js";
7
+ import no_empty_jsx_expression_default from "./no-empty-jsx-expression.js";
2
8
  import no_extra_nested_boolean_cast_default from "./no-extra-nested-boolean-cast.js";
9
+ import no_invalid_date_literal_default from "./no-invalid-date-literal.js";
3
10
  import no_jsx_statement_default from "./no-jsx-statement.js";
11
+ import no_suspicious_jsx_semicolon_default from "./no-suspicious-jsx-semicolon.js";
12
+ import no_ternary_return_default from "./no-ternary-return.js";
13
+ import no_useless_iife_default from "./no-useless-iife.js";
14
+ import prefer_repeat_default from "./prefer-repeat.js";
4
15
  import unsafe_asserted_chain_default from "./unsafe-asserted-chain.js";
5
16
 
6
17
  //#region lib/rules/index.ts
7
18
  var rules_exports = /* @__PURE__ */ __export({
19
+ "no-constant-template-expression": () => no_constant_template_expression_default,
20
+ "no-else-break": () => no_else_break_default,
21
+ "no-else-continue": () => no_else_continue_default,
22
+ "no-else-throw": () => no_else_throw_default,
23
+ "no-empty-comment": () => no_empty_comment_default,
24
+ "no-empty-jsx-expression": () => no_empty_jsx_expression_default,
8
25
  "no-extra-nested-boolean-cast": () => no_extra_nested_boolean_cast_default,
26
+ "no-invalid-date-literal": () => no_invalid_date_literal_default,
9
27
  "no-jsx-statement": () => no_jsx_statement_default,
28
+ "no-suspicious-jsx-semicolon": () => no_suspicious_jsx_semicolon_default,
29
+ "no-ternary-return": () => no_ternary_return_default,
30
+ "no-useless-iife": () => no_useless_iife_default,
31
+ "prefer-repeat": () => prefer_repeat_default,
10
32
  "unsafe-asserted-chain": () => unsafe_asserted_chain_default
11
33
  });
12
34
 
@@ -0,0 +1,10 @@
1
+ import { WyrmPluginDocs } from "../utils/createRule.js";
2
+ import { ESLintUtils } from "@typescript-eslint/utils";
3
+
4
+ //#region lib/rules/no-constant-template-expression.d.ts
5
+
6
+ declare const _default: ESLintUtils.RuleModule<"noConstantTemplateExpression" | "replaceByString", [{
7
+ minAllowedLength: number;
8
+ }], WyrmPluginDocs, ESLintUtils.RuleListener>;
9
+ //#endregion
10
+ export { _default };
@@ -0,0 +1,82 @@
1
+ import { createRule } from "../utils/createRule.js";
2
+ import path from "node:path";
3
+ import { ASTUtils, AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
4
+
5
+ //#region lib/rules/no-constant-template-expression.ts
6
+ const { name } = path.parse(import.meta.filename);
7
+ const DEFAULT_MIN_ALLOWED_LENGTH = 10;
8
+ var no_constant_template_expression_default = createRule({
9
+ name,
10
+ meta: {
11
+ type: "problem",
12
+ docs: {
13
+ description: "Disallow constant string expressions in template literals",
14
+ requiresTypeChecking: true,
15
+ strict: true
16
+ },
17
+ hasSuggestions: true,
18
+ schema: [{
19
+ type: "object",
20
+ properties: { minAllowedLength: {
21
+ type: "number",
22
+ description: `Minimum string length allowed for constant expressions. Default: ${DEFAULT_MIN_ALLOWED_LENGTH}`
23
+ } }
24
+ }],
25
+ messages: {
26
+ noConstantTemplateExpression: "Replace this constant template expression by its value as a string ('{{value}}')",
27
+ replaceByString: "Replace by '{{value}}'"
28
+ }
29
+ },
30
+ defaultOptions: [{ minAllowedLength: DEFAULT_MIN_ALLOWED_LENGTH }],
31
+ create(context, [options]) {
32
+ return { TemplateLiteral(node) {
33
+ const services = ESLintUtils.getParserServices(context);
34
+ const checker = services.program.getTypeChecker();
35
+ const { expressions, quasis } = node;
36
+ if (quasis.some((quasi) => quasi.value.cooked.includes(" "))) return;
37
+ const scope = context.sourceCode.getScope(node);
38
+ for (const expr of expressions) {
39
+ if (expr.type === AST_NODE_TYPES.Identifier) {
40
+ const variable = ASTUtils.findVariable(scope, expr);
41
+ if (variable) {
42
+ const { references, defs } = variable;
43
+ if (references.length > 2) continue;
44
+ const def = defs.at(-1);
45
+ if (def?.parent?.type === AST_NODE_TYPES.VariableDeclaration && (def.parent.parent.type === AST_NODE_TYPES.ExportNamedDeclaration || def.parent.parent.type === AST_NODE_TYPES.ExportDefaultDeclaration)) continue;
46
+ }
47
+ }
48
+ const value = getLiteralValue(services.getTypeAtLocation(expr), checker);
49
+ if (value === null) continue;
50
+ if (value.length >= options.minAllowedLength) return;
51
+ context.report({
52
+ node: expr,
53
+ messageId: "noConstantTemplateExpression",
54
+ data: { value },
55
+ suggest: [{
56
+ messageId: "replaceByString",
57
+ data: { value },
58
+ fix(fixer) {
59
+ const [identStart, identEnd] = expr.range;
60
+ const previousQuasi = quasis.toReversed().find((quasi) => quasi.range[1] <= identStart);
61
+ const nextQuasi = quasis.find((quasi) => quasi.range[0] >= identEnd);
62
+ const start = previousQuasi?.range[1] ?? node.range[0];
63
+ const end = nextQuasi?.range[0] ?? node.range[1];
64
+ const range = [start - 2, end + 1];
65
+ return fixer.replaceTextRange(range, value);
66
+ }
67
+ }]
68
+ });
69
+ }
70
+ } };
71
+ }
72
+ });
73
+ function getLiteralValue(type, checker) {
74
+ if (type.isStringLiteral()) return type.value;
75
+ if (type.isNumberLiteral()) return type.value.toString();
76
+ if (type === checker.getTrueType()) return "true";
77
+ if (type === checker.getFalseType()) return "false";
78
+ return null;
79
+ }
80
+
81
+ //#endregion
82
+ export { no_constant_template_expression_default as default };
@@ -0,0 +1,7 @@
1
+ import { WyrmPluginDocs } from "../utils/createRule.js";
2
+ import * as _typescript_eslint_utils_ts_eslint0 from "@typescript-eslint/utils/ts-eslint";
3
+
4
+ //#region lib/rules/no-else-break.d.ts
5
+ declare const _default: _typescript_eslint_utils_ts_eslint0.RuleModule<"noElseBreak", [], WyrmPluginDocs, _typescript_eslint_utils_ts_eslint0.RuleListener>;
6
+ //#endregion
7
+ export { _default };
@@ -0,0 +1,51 @@
1
+ import { createRule } from "../utils/createRule.js";
2
+ import path from "node:path";
3
+ import { AST_NODE_TYPES } from "@typescript-eslint/utils";
4
+
5
+ //#region lib/rules/no-else-break.ts
6
+ const { name } = path.parse(import.meta.filename);
7
+ var no_else_break_default = createRule({
8
+ name,
9
+ meta: {
10
+ type: "suggestion",
11
+ docs: {
12
+ description: "Forbid unnecessary `else` block after a `break` statement",
13
+ recommended: true
14
+ },
15
+ fixable: "code",
16
+ schema: [],
17
+ messages: { noElseBreak: "Remove this unnecessary else" }
18
+ },
19
+ defaultOptions: [],
20
+ create(context) {
21
+ return { IfStatement(node) {
22
+ const { alternate } = node;
23
+ if (!alternate) return;
24
+ const lastConsequentStatement = getLastStatement(node.consequent);
25
+ if (!lastConsequentStatement) return;
26
+ if (lastConsequentStatement.type === AST_NODE_TYPES.BreakStatement) context.report({
27
+ node: alternate,
28
+ messageId: "noElseBreak",
29
+ *fix(fixer) {
30
+ const firstToken = context.sourceCode.getTokenBefore(alternate);
31
+ if (firstToken) yield fixer.remove(firstToken);
32
+ yield fixer.remove(alternate);
33
+ if (alternate.type === AST_NODE_TYPES.BlockStatement) {
34
+ const bodyText$1 = alternate.body.map((stmt) => context.sourceCode.getText(stmt)).join("\n");
35
+ yield fixer.insertTextAfter(node, bodyText$1);
36
+ return;
37
+ }
38
+ const bodyText = context.sourceCode.getText(alternate);
39
+ yield fixer.insertTextAfter(node, bodyText);
40
+ }
41
+ });
42
+ } };
43
+ }
44
+ });
45
+ function getLastStatement(stmt) {
46
+ if (stmt.type === AST_NODE_TYPES.BlockStatement) return stmt.body.at(-1);
47
+ return stmt;
48
+ }
49
+
50
+ //#endregion
51
+ export { no_else_break_default as default };
@@ -0,0 +1,7 @@
1
+ import { WyrmPluginDocs } from "../utils/createRule.js";
2
+ import * as _typescript_eslint_utils_ts_eslint1 from "@typescript-eslint/utils/ts-eslint";
3
+
4
+ //#region lib/rules/no-else-continue.d.ts
5
+ declare const _default: _typescript_eslint_utils_ts_eslint1.RuleModule<"noElseContinue", [], WyrmPluginDocs, _typescript_eslint_utils_ts_eslint1.RuleListener>;
6
+ //#endregion
7
+ export { _default };
@@ -0,0 +1,51 @@
1
+ import { createRule } from "../utils/createRule.js";
2
+ import path from "node:path";
3
+ import { AST_NODE_TYPES } from "@typescript-eslint/utils";
4
+
5
+ //#region lib/rules/no-else-continue.ts
6
+ const { name } = path.parse(import.meta.filename);
7
+ var no_else_continue_default = createRule({
8
+ name,
9
+ meta: {
10
+ type: "suggestion",
11
+ docs: {
12
+ description: "Forbid unnecessary `else` block after a `continue` statement",
13
+ recommended: true
14
+ },
15
+ fixable: "code",
16
+ schema: [],
17
+ messages: { noElseContinue: "Remove this unnecessary else" }
18
+ },
19
+ defaultOptions: [],
20
+ create(context) {
21
+ return { IfStatement(node) {
22
+ const { alternate } = node;
23
+ if (!alternate) return;
24
+ const lastConsequentStatement = getLastStatement(node.consequent);
25
+ if (!lastConsequentStatement) return;
26
+ if (lastConsequentStatement.type === AST_NODE_TYPES.ContinueStatement) context.report({
27
+ node: alternate,
28
+ messageId: "noElseContinue",
29
+ *fix(fixer) {
30
+ const firstToken = context.sourceCode.getTokenBefore(alternate);
31
+ if (firstToken) yield fixer.remove(firstToken);
32
+ yield fixer.remove(alternate);
33
+ if (alternate.type === AST_NODE_TYPES.BlockStatement) {
34
+ const bodyText$1 = alternate.body.map((stmt) => context.sourceCode.getText(stmt)).join("\n");
35
+ yield fixer.insertTextAfter(node, bodyText$1);
36
+ return;
37
+ }
38
+ const bodyText = context.sourceCode.getText(alternate);
39
+ yield fixer.insertTextAfter(node, bodyText);
40
+ }
41
+ });
42
+ } };
43
+ }
44
+ });
45
+ function getLastStatement(stmt) {
46
+ if (stmt.type === AST_NODE_TYPES.BlockStatement) return stmt.body.at(-1);
47
+ return stmt;
48
+ }
49
+
50
+ //#endregion
51
+ export { no_else_continue_default as default };
@@ -0,0 +1,7 @@
1
+ import { WyrmPluginDocs } from "../utils/createRule.js";
2
+ import * as _typescript_eslint_utils_ts_eslint3 from "@typescript-eslint/utils/ts-eslint";
3
+
4
+ //#region lib/rules/no-else-throw.d.ts
5
+ declare const _default: _typescript_eslint_utils_ts_eslint3.RuleModule<"noElseThrow", [], WyrmPluginDocs, _typescript_eslint_utils_ts_eslint3.RuleListener>;
6
+ //#endregion
7
+ export { _default };
@@ -0,0 +1,51 @@
1
+ import { createRule } from "../utils/createRule.js";
2
+ import path from "node:path";
3
+ import { AST_NODE_TYPES } from "@typescript-eslint/utils";
4
+
5
+ //#region lib/rules/no-else-throw.ts
6
+ const { name } = path.parse(import.meta.filename);
7
+ var no_else_throw_default = createRule({
8
+ name,
9
+ meta: {
10
+ type: "suggestion",
11
+ docs: {
12
+ description: "Forbid unnecessary `else` block after a `throw` statement",
13
+ recommended: true
14
+ },
15
+ fixable: "code",
16
+ schema: [],
17
+ messages: { noElseThrow: "Remove this unnecessary else" }
18
+ },
19
+ defaultOptions: [],
20
+ create(context) {
21
+ return { IfStatement(node) {
22
+ const { alternate } = node;
23
+ if (!alternate) return;
24
+ const lastConsequentStatement = getLastStatement(node.consequent);
25
+ if (!lastConsequentStatement) return;
26
+ if (lastConsequentStatement.type === AST_NODE_TYPES.ThrowStatement) context.report({
27
+ node: alternate,
28
+ messageId: "noElseThrow",
29
+ *fix(fixer) {
30
+ const firstToken = context.sourceCode.getTokenBefore(alternate);
31
+ if (firstToken) yield fixer.remove(firstToken);
32
+ yield fixer.remove(alternate);
33
+ if (alternate.type === AST_NODE_TYPES.BlockStatement) {
34
+ const bodyText$1 = alternate.body.map((stmt) => context.sourceCode.getText(stmt)).join("\n");
35
+ yield fixer.insertTextAfter(node, bodyText$1);
36
+ return;
37
+ }
38
+ const bodyText = context.sourceCode.getText(alternate);
39
+ yield fixer.insertTextAfter(node, bodyText);
40
+ }
41
+ });
42
+ } };
43
+ }
44
+ });
45
+ function getLastStatement(stmt) {
46
+ if (stmt.type === AST_NODE_TYPES.BlockStatement) return stmt.body.at(-1);
47
+ return stmt;
48
+ }
49
+
50
+ //#endregion
51
+ export { no_else_throw_default as default };
@@ -0,0 +1,9 @@
1
+ import { WyrmPluginDocs } from "../utils/createRule.js";
2
+ import * as _typescript_eslint_utils_ts_eslint5 from "@typescript-eslint/utils/ts-eslint";
3
+
4
+ //#region lib/rules/no-empty-comment.d.ts
5
+ declare const _default: _typescript_eslint_utils_ts_eslint5.RuleModule<"noEmptyComment", [{
6
+ allowStacked: boolean;
7
+ }], WyrmPluginDocs, _typescript_eslint_utils_ts_eslint5.RuleListener>;
8
+ //#endregion
9
+ export { _default };
@@ -0,0 +1,57 @@
1
+ import { createRule } from "../utils/createRule.js";
2
+ import path from "node:path";
3
+ import { AST_TOKEN_TYPES } from "@typescript-eslint/utils";
4
+
5
+ //#region lib/rules/no-empty-comment.ts
6
+ const { name } = path.parse(import.meta.filename);
7
+ const DEFAULT_ALLOW_STACKED = false;
8
+ var no_empty_comment_default = createRule({
9
+ name,
10
+ meta: {
11
+ type: "suggestion",
12
+ docs: {
13
+ description: "Forbid empty comments",
14
+ strict: true
15
+ },
16
+ schema: [{
17
+ type: "object",
18
+ additionalProperties: false,
19
+ properties: { allowStacked: {
20
+ type: "boolean",
21
+ description: `Whether to allow empty comments stacked next to non-empty comments. Default: \`${DEFAULT_ALLOW_STACKED}\``
22
+ } }
23
+ }],
24
+ messages: { noEmptyComment: "Remove this empty comment" }
25
+ },
26
+ defaultOptions: [{ allowStacked: DEFAULT_ALLOW_STACKED }],
27
+ create(context, [options]) {
28
+ if (typeof context.sourceCode.getAllComments === "undefined") return {};
29
+ const comments = context.sourceCode.getAllComments();
30
+ for (const comment of comments) {
31
+ if (!isEmptyComment(comment)) continue;
32
+ if (options.allowStacked && isStackedComment(comment, comments)) continue;
33
+ context.report({
34
+ node: comment,
35
+ messageId: "noEmptyComment"
36
+ });
37
+ }
38
+ return {};
39
+ }
40
+ });
41
+ function isEmptyComment(comment) {
42
+ return !comment.value.replace(/^\*/u, "").replaceAll("*\n", "").trim();
43
+ }
44
+ function isStackedComment(comment, comments) {
45
+ if (comment.type !== AST_TOKEN_TYPES.Line) return false;
46
+ return comments.some((otherComment) => {
47
+ if (otherComment === comment) return false;
48
+ if (otherComment.type !== AST_TOKEN_TYPES.Line) return false;
49
+ if (isEmptyComment(otherComment)) return false;
50
+ if (otherComment.loc.start.line === comment.loc.start.line - 1) return true;
51
+ if (otherComment.loc.start.line === comment.loc.start.line + 1) return true;
52
+ return false;
53
+ });
54
+ }
55
+
56
+ //#endregion
57
+ export { no_empty_comment_default as default };
@@ -0,0 +1,7 @@
1
+ import { WyrmPluginDocs } from "../utils/createRule.js";
2
+ import * as _typescript_eslint_utils_ts_eslint7 from "@typescript-eslint/utils/ts-eslint";
3
+
4
+ //#region lib/rules/no-empty-jsx-expression.d.ts
5
+ declare const _default: _typescript_eslint_utils_ts_eslint7.RuleModule<"noEmptyJsxExpression", [], WyrmPluginDocs, _typescript_eslint_utils_ts_eslint7.RuleListener>;
6
+ //#endregion
7
+ export { _default };