@xaliksss/eslint-config 4.0.4 → 5.0.1

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.
@@ -0,0 +1,28 @@
1
+ export interface XaliksConfigOptions {
2
+ /**
3
+ * Файлы, которые не должны быть обработаны плагином.
4
+ * @default ["**\/dist/**", "**\/node_modules/**"]
5
+ */
6
+ ignores?: string[];
7
+ /**
8
+ * Файлы, которые должны быть обработаны плагином только для JS.
9
+ * @default ["**\/*.js", "**\/*.mjs", "**\/*.cjs", "**\/*.jsx"]
10
+ */
11
+ jsFiles?: string[];
12
+ /**
13
+ * Файлы, которые должны быть обработаны плагином только для TS.
14
+ * @default ["**\/*.ts", "**\/*.mts", "**\/*.cts", "**\/*.tsx"]
15
+ */
16
+ tsFiles?: string[];
17
+ /**
18
+ * Максимальная длина строки.
19
+ * @default 120
20
+ */
21
+ maxCodeLength?: number;
22
+ }
23
+ export declare const DEFAULT_CONFIG: {
24
+ ignores: string[];
25
+ jsFiles: string[];
26
+ tsFiles: string[];
27
+ maxCodeLength: number;
28
+ };
package/dist/config.js ADDED
@@ -0,0 +1,9 @@
1
+ export const DEFAULT_CONFIG = {
2
+ ignores: [
3
+ "**/dist/**",
4
+ "**/node_modules/**",
5
+ ],
6
+ jsFiles: ["**/*.js", "**/*.mjs", "**/*.cjs", "**/*.jsx"],
7
+ tsFiles: ["**/*.ts", "**/*.mts", "**/*.cts", "**/*.tsx"],
8
+ maxCodeLength: 120,
9
+ };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- declare const _default: import("eslint/config").ConfigObject[];
2
- export default _default;
1
+ import type { XaliksConfigOptions } from "./config.js";
2
+ export default function createConfig(_options?: XaliksConfigOptions): import("eslint/config").ConfigObject[];
package/dist/index.js CHANGED
@@ -1,65 +1,95 @@
1
- import { defineConfig } from 'eslint/config';
2
- import globals from "globals";
3
- import tseslint from "typescript-eslint";
4
1
  import stylisticPlugin from "@stylistic/eslint-plugin";
5
- import importPlugin from "eslint-plugin-import-x";
2
+ import { defineConfig } from "eslint/config";
3
+ import importPlugin, { createNodeResolver } from "eslint-plugin-import-x";
6
4
  import nPlugin from "eslint-plugin-n";
5
+ import globals from "globals";
6
+ import tseslint from "typescript-eslint";
7
+ import { DEFAULT_CONFIG } from "./config.js";
7
8
  import { eslintRules } from "./rules/eslint.js";
8
- import { stylisticRules } from "./rules/stylistic.js";
9
9
  import { importRules } from "./rules/import-x.js";
10
+ import { nRules } from "./rules/n.js";
11
+ import { stylisticRules } from "./rules/stylistic.js";
10
12
  import { typescriptRules, typescriptTypeAwareRules } from "./rules/typescript.js";
11
- const IGNORES = [
12
- "**/dist/**",
13
- "**/node_modules/**",
14
- ];
15
- const JS_FILES = ["**/*.js", "**/*.mjs", "**/*.cjs", "**/*.jsx"];
16
- const TS_FILES = ["**/*.ts", "**/*.mts", "**/*.cts", "**/*.tsx"];
17
- export default defineConfig({
18
- ignores: IGNORES,
19
- },
20
- // Общие правила для JS и TS
21
- {
22
- files: [...JS_FILES, ...TS_FILES],
23
- languageOptions: {
24
- ecmaVersion: "latest",
25
- sourceType: "module",
26
- globals: {
27
- ...globals.node,
28
- NodeJS: "off",
13
+ const extensions = {
14
+ js: [".js", ".mjs", ".cjs", ".jsx"],
15
+ ts: [".ts", ".mts", ".cts", ".tsx"],
16
+ };
17
+ export default function createConfig(_options = {}) {
18
+ const options = {
19
+ ...DEFAULT_CONFIG,
20
+ ..._options,
21
+ };
22
+ const cjsFiles = options.jsFiles.filter((pattern) => pattern.endsWith(".cjs"));
23
+ return defineConfig({
24
+ ignores: options.ignores,
25
+ },
26
+ // Общие правила для JS и TS
27
+ {
28
+ files: [...options.jsFiles, ...options.tsFiles],
29
+ languageOptions: {
30
+ ecmaVersion: "latest",
31
+ sourceType: "module",
32
+ globals: {
33
+ ...globals.node,
34
+ NodeJS: "off",
35
+ },
36
+ },
37
+ plugins: {
38
+ "@stylistic": stylisticPlugin,
39
+ "import-x": importPlugin,
40
+ n: nPlugin,
41
+ },
42
+ settings: {
43
+ // Без этого import-x не парсит .ts файлы: no-cycle, named и т.д. молча не работают
44
+ "import-x/extensions": [...extensions.js, ...extensions.ts],
45
+ "import-x/parsers": {
46
+ "@typescript-eslint/parser": extensions.ts,
47
+ },
48
+ // import "./a.js" -> a.ts
49
+ "import-x/resolver-next": [
50
+ createNodeResolver({
51
+ extensions: [...extensions.ts, ...extensions.js, ".json", ".node"],
52
+ extensionAlias: {
53
+ ".js": [".ts", ".tsx", ".js", ".jsx"],
54
+ ".mjs": [".mts", ".mjs"],
55
+ ".cjs": [".cts", ".cjs"],
56
+ },
57
+ }),
58
+ ],
59
+ },
60
+ rules: {
61
+ ...eslintRules,
62
+ ...stylisticRules(options),
63
+ ...importRules,
64
+ ...nRules,
65
+ },
66
+ },
67
+ // CommonJS
68
+ ...cjsFiles.length ? [{
69
+ files: cjsFiles,
70
+ languageOptions: {
71
+ sourceType: "commonjs",
72
+ },
73
+ rules: {
74
+ "import-x/no-commonjs": "off",
75
+ "import-x/unambiguous": "off",
76
+ },
77
+ }] : [],
78
+ // overrides для TS
79
+ {
80
+ files: options.tsFiles,
81
+ languageOptions: {
82
+ parser: tseslint.parser,
83
+ parserOptions: {
84
+ projectService: true,
85
+ },
86
+ },
87
+ plugins: {
88
+ "@typescript-eslint": tseslint.plugin,
89
+ },
90
+ rules: {
91
+ ...typescriptRules,
92
+ ...typescriptTypeAwareRules,
29
93
  },
30
- },
31
- plugins: {
32
- "@stylistic": stylisticPlugin,
33
- "import-x": importPlugin,
34
- n: nPlugin,
35
- },
36
- rules: {
37
- ...eslintRules,
38
- ...stylisticRules,
39
- ...importRules,
40
- },
41
- },
42
- // overrides для TS
43
- {
44
- files: TS_FILES,
45
- languageOptions: {
46
- parser: tseslint.parser,
47
- parserOptions: { project: false },
48
- },
49
- plugins: {
50
- "@typescript-eslint": tseslint.plugin,
51
- },
52
- rules: typescriptRules,
53
- },
54
- // type-aware правила
55
- {
56
- files: TS_FILES,
57
- languageOptions: {
58
- parser: tseslint.parser,
59
- parserOptions: { project: true },
60
- },
61
- plugins: {
62
- "@typescript-eslint": tseslint.plugin,
63
- },
64
- rules: typescriptTypeAwareRules,
65
- });
94
+ });
95
+ }
@@ -19,7 +19,7 @@ export const eslintRules = {
19
19
  "no-dupe-else-if": "error",
20
20
  "no-dupe-keys": "error", // [TS]
21
21
  "no-duplicate-case": "error",
22
- "no-duplicate-imports": ["error", { allowSeparateTypeImports: true }],
22
+ "no-duplicate-imports": "off", // есть import-x/no-duplicates
23
23
  "no-empty-character-class": "error",
24
24
  "no-empty-pattern": "error",
25
25
  "no-ex-assign": "error",
@@ -35,6 +35,7 @@ export const eslintRules = {
35
35
  "no-obj-calls": "error", // [TS]
36
36
  "no-promise-executor-return": "error",
37
37
  "no-prototype-builtins": "error",
38
+ "no-restricted-syntax": "off",
38
39
  "no-self-assign": "error",
39
40
  "no-self-compare": "error",
40
41
  "no-setter-return": "error", // [TS]
@@ -51,7 +52,11 @@ export const eslintRules = {
51
52
  "no-unsafe-negation": "error", // [TS]
52
53
  "no-unsafe-optional-chaining": "error",
53
54
  "no-unused-private-class-members": "error",
54
- "no-unused-vars": "error",
55
+ "no-unused-vars": ["error", {
56
+ ignoreRestSiblings: true,
57
+ ignoreClassWithStaticInitBlock: true,
58
+ argsIgnorePattern: "^_",
59
+ }],
55
60
  "no-use-before-define": ["error", {
56
61
  functions: false,
57
62
  classes: false,
@@ -102,33 +107,33 @@ export const eslintRules = {
102
107
  "prefer-spread": "error",
103
108
  "prefer-template": "error",
104
109
  "preserve-caught-error": "off", // Нужно указывать cause в new Error
105
- "radix": "off",
110
+ radix: "off",
106
111
  "require-await": "error",
107
112
  "require-unicode-regexp": "off", // Обязательно указывать /u или /v в regex
108
113
  "require-yield": "error",
109
114
  "sort-imports": "off", // установлен другой плагин import
110
115
  "sort-keys": "off",
111
- "sort-vars": "error",
112
- "strict": "off",
116
+ "sort-vars": "off", // не нужен при one-var: never
117
+ strict: "off",
113
118
  "symbol-description": "error",
114
- "vars-on-top": "error",
115
- "yoda": "error",
119
+ "vars-on-top": "off", // не нужен при no-var
120
+ yoda: "error",
116
121
  "unicode-bom": "error",
117
122
  "accessor-pairs": "error", // Спорно, возможно удалится
118
123
  "arrow-body-style": "off",
119
- "block-scoped-var": "error",
120
- "camelcase": "off", // есть naming-convention с более детальной настройкой
124
+ "block-scoped-var": "off", // не нужен при no-var
125
+ camelcase: "off", // есть naming-convention с более детальной настройкой
121
126
  "capitalized-comments": "off",
122
127
  "class-methods-use-this": "off",
123
- "complexity": "off",
128
+ complexity: "off",
124
129
  "consistent-return": "off",
125
130
  "consistent-this": "off",
126
- "curly": ["error", "multi-line"],
131
+ curly: ["error", "multi-line"],
127
132
  "default-case": "off",
128
133
  "default-case-last": "error",
129
134
  "default-param-last": "error",
130
135
  "dot-notation": "error",
131
- "eqeqeq": "error",
136
+ eqeqeq: "error",
132
137
  "func-name-matching": "error",
133
138
  "func-names": "off",
134
139
  "func-style": ["error", "declaration", { allowArrowFunctions: true }],
@@ -1,2 +1,2 @@
1
- import { Linter } from "eslint";
1
+ import type { Linter } from "eslint";
2
2
  export declare const importRules: Linter.RulesRecord;
@@ -1,7 +1,6 @@
1
- import { Linter } from "eslint";
2
1
  export const importRules = {
3
2
  "import-x/consistent-type-specifier-style": ["error", "prefer-top-level"],
4
- "import-x/default": "error",
3
+ "import-x/default": "error", // [TS]
5
4
  "import-x/dynamic-import-chunkname": "off",
6
5
  "import-x/export": "error",
7
6
  "import-x/exports-last": "off",
@@ -9,8 +8,8 @@ export const importRules = {
9
8
  "import-x/first": "error",
10
9
  "import-x/group-exports": "off",
11
10
  "import-x/max-dependencies": "off",
12
- "import-x/named": "error",
13
- "import-x/namespace": "error",
11
+ "import-x/named": "error", // [TS]
12
+ "import-x/namespace": "error", // [TS]
14
13
  "import-x/newline-after-import": ["error", { count: 1 }],
15
14
  "import-x/no-absolute-path": "error",
16
15
  "import-x/no-amd": "error",
@@ -19,11 +18,11 @@ export const importRules = {
19
18
  "import-x/no-cycle": ["error", {
20
19
  maxDepth: 4, // Возможно придется обновить на 1
21
20
  ignoreExternal: true,
22
- allowUnsafeDynamicCyclicDependency: false
21
+ allowUnsafeDynamicCyclicDependency: false,
23
22
  }],
24
23
  "import-x/no-default-export": "off",
25
24
  "import-x/no-deprecated": "off", // С этим лучше справляется @typescript-eslint/no-deprecated
26
- "import-x/no-duplicates": "off", // уже используем extensions
25
+ "import-x/no-duplicates": "error", // type и value импорты считаются отдельно (prefer-inline: false)
27
26
  "import-x/no-dynamic-require": "error",
28
27
  "import-x/no-empty-named-blocks": "error",
29
28
  "import-x/no-extraneous-dependencies": "error",
@@ -38,7 +37,7 @@ export const importRules = {
38
37
  "import-x/no-nodejs-modules": "off",
39
38
  "import-x/no-relative-packages": "off",
40
39
  "import-x/no-relative-parent-imports": "off",
41
- "import-x/no-rename-default": "error",
40
+ "import-x/no-rename-default": "off",
42
41
  "import-x/no-restricted-paths": "off", // в связке с no-restricted-imports от Eslint
43
42
  "import-x/no-self-import": "error",
44
43
  "import-x/no-unassigned-import": "off",
@@ -46,14 +45,12 @@ export const importRules = {
46
45
  "import-x/no-unused-modules": "off", // с eslint v10 no-op, есть no-unused-vars
47
46
  "import-x/no-useless-path-segments": "error",
48
47
  "import-x/no-webpack-loader-syntax": "error",
49
- "import-x/order": ["error",
50
- {
48
+ "import-x/order": ["error", {
51
49
  groups: ["builtin", "external", "type", "internal", "parent", "sibling", "index", "object"],
52
50
  "newlines-between": "always",
53
51
  alphabetize: { order: "asc" },
54
52
  named: true,
55
- },
56
- ],
53
+ }],
57
54
  "import-x/prefer-default-export": "off",
58
55
  "import-x/prefer-namespace-import": "off",
59
56
  "import-x/unambiguous": "error",
package/dist/rules/n.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { Linter } from "eslint";
1
+ import type { Linter } from "eslint";
2
2
  export declare const nRules: Linter.RulesRecord;
package/dist/rules/n.js CHANGED
@@ -1,4 +1,3 @@
1
- import { Linter } from "eslint";
2
1
  export const nRules = {
3
2
  "n/callback-return": "error",
4
3
  "n/exports-style": ["error", "exports"],
@@ -1,2 +1,3 @@
1
+ import type { XaliksConfigOptions } from "../config.js";
1
2
  import type { Linter } from "eslint";
2
- export declare const stylisticRules: Linter.RulesRecord;
3
+ export declare const stylisticRules: (options: XaliksConfigOptions) => Linter.RulesRecord;
@@ -1,149 +1,176 @@
1
- export const stylisticRules = {
2
- "@stylistic/array-bracket-newline": ["error", "consistent"],
3
- "@stylistic/array-bracket-spacing": "error",
4
- "@stylistic/array-element-newline": ["error", "consistent"],
5
- "@stylistic/arrow-parens": "error",
6
- "@stylistic/arrow-spacing": "error",
7
- "@stylistic/block-spacing": "error",
8
- "@stylistic/brace-style": "error",
9
- "@stylistic/comma-dangle": ["error", "always-multiline"],
10
- "@stylistic/comma-spacing": "error",
11
- "@stylistic/comma-style": "error",
12
- "@stylistic/computed-property-spacing": "error",
13
- "@stylistic/curly-newline": ["error", { consistent: true }],
14
- "@stylistic/dot-location": ["error", "property"],
15
- "@stylistic/eol-last": "error",
16
- "@stylistic/function-call-argument-newline": ["error", "consistent"],
17
- "@stylistic/function-call-spacing": "error",
18
- "@stylistic/function-paren-newline": ["error", "consistent"],
19
- "@stylistic/generator-star-spacing": "error",
20
- "@stylistic/implicit-arrow-linebreak": "error",
21
- "@stylistic/indent": ["error", "tab"],
22
- "@stylistic/indent-binary-ops": ["error", 1],
23
- // JSX пока игнорирую. потом сделаю
24
- "@stylistic/jsx-child-element-spacing": "off",
25
- "@stylistic/jsx-closing-bracket-location": "off",
26
- "@stylistic/jsx-closing-tag-location": "off",
27
- "@stylistic/jsx-curly-brace-presence": "off",
28
- "@stylistic/jsx-curly-newline": "off",
29
- "@stylistic/jsx-curly-spacing": "off",
30
- "@stylistic/jsx-equals-spacing": "off",
31
- "@stylistic/jsx-first-prop-new-line": "off",
32
- "@stylistic/jsx-function-call-newline": "off",
33
- "@stylistic/jsx-indent-props": "off",
34
- "@stylistic/jsx-max-props-per-line": "off",
35
- "@stylistic/jsx-newline": "off",
36
- "@stylistic/jsx-one-expression-per-line": "off",
37
- "@stylistic/jsx-pascal-case": "off",
38
- "@stylistic/jsx-props-style": "off",
39
- "@stylistic/jsx-quotes": "off",
40
- "@stylistic/jsx-self-closing-comp": "off",
41
- "@stylistic/jsx-shorthand-boolean": "off",
42
- "@stylistic/jsx-shorthand-fragment": "off",
43
- "@stylistic/jsx-tag-spacing": "off",
44
- "@stylistic/jsx-wrap-multilines": "off",
45
- "@stylistic/key-spacing": "error",
46
- "@stylistic/keyword-spacing": "error",
47
- "@stylistic/line-comment-position": "off", // Без разницы где ставить комментарий
48
- "@stylistic/linebreak-style": ["error", "unix"],
49
- "@stylistic/lines-around-comment": "off", // Без разницы где ставить комментарий
50
- "@stylistic/lines-between-class-members": ["error",
51
- {
52
- enforce: [
53
- { blankLine: "always", prev: "method", next: "method" },
54
- { blankLine: "always", prev: "field", next: "method" },
55
- { blankLine: "always", prev: "method", next: "field" },
56
- ],
57
- },
58
- { exceptAfterOverload: true }
59
- ],
60
- "@stylistic/max-len": ["error", {
61
- code: 120,
62
- tabWidth: 1,
63
- ignoreComments: true,
64
- ignoreTrailingComments: true,
65
- ignoreUrls: true,
66
- ignoreStrings: true,
67
- ignoreTemplateLiterals: true,
68
- ignoreRegExpLiterals: true
69
- }],
70
- "@stylistic/max-statements-per-line": ["error", { max: 1 }],
71
- "@stylistic/member-delimiter-style": ["error", {
72
- multiline: {
73
- delimiter: "semi",
74
- requireLast: true,
75
- },
76
- singleline: {
77
- delimiter: "semi",
78
- requireLast: false,
79
- },
80
- }],
81
- "@stylistic/multiline-comment-style": "off",
82
- "@stylistic/multiline-ternary": "off",
83
- "@stylistic/new-parens": "error",
84
- "@stylistic/newline-per-chained-call": "off",
85
- "@stylistic/no-confusing-arrow": "off",
86
- "@stylistic/no-extra-parens": ["error", "all", {
87
- returnAssign: false, // return (a = b)
88
- nestedBinaryExpressions: false, // (a || b) && c
89
- ternaryOperandBinaryExpressions: false, // (a && b) ? foo : bar;
90
- nestedConditionalExpressions: false, // (a ? b : c) ? d : e
91
- ignoredNodes: [
92
- "ArrowFunctionExpression[body.type=ConditionalExpression]", // x => (a ? b : c)
93
- "SpreadElement[argument.type=ConditionalExpression]", // ...(a ? [1, 2, 3] : []),
94
- "SpreadElement[argument.type=LogicalExpression]", // ...(isSummer && { watermelon: 30 }),
95
- "SpreadElement[argument.type=AwaitExpression]", // ...(await promiseArray)
96
- ],
97
- }],
98
- "@stylistic/no-extra-semi": "error",
99
- "@stylistic/no-floating-decimal": "error",
100
- "@stylistic/no-mixed-operators": ["error", {
101
- groups: [["&&", "||", "?:"]],
102
- allowSamePrecedence: true,
103
- }],
104
- "@stylistic/no-mixed-spaces-and-tabs": "off", // разобраться
105
- "@stylistic/no-multi-spaces": "error",
106
- "@stylistic/no-multiple-empty-lines": ["error", { max: 1, maxBOF: 0, maxEOF: 1 }],
107
- "@stylistic/no-tabs": "off",
108
- "@stylistic/no-trailing-spaces": ["error", { ignoreComments: true }],
109
- "@stylistic/no-whitespace-before-property": "error",
110
- "@stylistic/nonblock-statement-body-position": "error",
111
- "@stylistic/object-curly-newline": "error",
112
- "@stylistic/object-curly-spacing": ["error", "always"],
113
- "@stylistic/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
114
- "@stylistic/one-var-declaration-per-line": "off",
115
- "@stylistic/operator-linebreak": ["error", "after", {
116
- overrides: {
117
- "?": "before",
118
- ":": "before",
119
- "|": "before",
120
- },
121
- }],
122
- "@stylistic/padded-blocks": ["error", "never"],
123
- "@stylistic/padding-line-between-statements": "off", // Вообще шикарное правило, нужно долго настраивать, но мне лень
124
- "@stylistic/quote-props": ["error", "as-needed"],
125
- "@stylistic/quotes": ["error", "double"],
126
- "@stylistic/rest-spread-spacing": ["error", "never"],
127
- "@stylistic/semi": "error",
128
- "@stylistic/semi-spacing": "error",
129
- "@stylistic/semi-style": "error",
130
- "@stylistic/space-before-blocks": "error",
131
- "@stylistic/space-before-function-paren": ["error", {
132
- anonymous: "always", // function () {}
133
- named: "never", // function foo() {}
134
- asyncArrow: "always", // async () => {}
135
- }],
136
- "@stylistic/space-in-parens": ["error", "never"],
137
- "@stylistic/space-infix-ops": "error",
138
- "@stylistic/space-unary-ops": "error",
139
- "@stylistic/spaced-comment": "error",
140
- "@stylistic/switch-colon-spacing": "error",
141
- "@stylistic/template-curly-spacing": "error",
142
- "@stylistic/template-tag-spacing": ["error", "never"],
143
- "@stylistic/type-annotation-spacing": "error",
144
- "@stylistic/type-generic-spacing": "error",
145
- "@stylistic/type-named-tuple-spacing": "error",
146
- "@stylistic/wrap-iife": ["error", "inside"],
147
- "@stylistic/wrap-regex": "off",
148
- "@stylistic/yield-star-spacing": "error",
1
+ export const stylisticRules = (options) => {
2
+ return {
3
+ "@stylistic/arrow-parens": "error",
4
+ "@stylistic/arrow-spacing": "error",
5
+ "@stylistic/block-spacing": "error",
6
+ "@stylistic/brace-style": "error",
7
+ "@stylistic/comma-dangle": ["error", "always-multiline"],
8
+ "@stylistic/comma-spacing": "error",
9
+ "@stylistic/comma-style": "error",
10
+ "@stylistic/computed-property-spacing": "error",
11
+ "@stylistic/curly-newline": ["error", { consistent: true }],
12
+ "@stylistic/dot-location": ["error", "property"],
13
+ "@stylistic/eol-last": ["error", "always"],
14
+ "@stylistic/function-call-spacing": "error",
15
+ "@stylistic/generator-star-spacing": "error",
16
+ "@stylistic/implicit-arrow-linebreak": "error",
17
+ "@stylistic/indent": ["error", "tab"],
18
+ "@stylistic/indent-binary-ops": ["error", "tab"],
19
+ // JSX пока игнорирую. потом сделаю
20
+ "@stylistic/jsx-child-element-spacing": "off",
21
+ "@stylistic/jsx-closing-bracket-location": "off",
22
+ "@stylistic/jsx-closing-tag-location": "off",
23
+ "@stylistic/jsx-curly-brace-presence": "off",
24
+ "@stylistic/jsx-curly-newline": "off",
25
+ "@stylistic/jsx-curly-spacing": "off",
26
+ "@stylistic/jsx-equals-spacing": "off",
27
+ "@stylistic/jsx-first-prop-new-line": "off",
28
+ "@stylistic/jsx-function-call-newline": "off",
29
+ "@stylistic/jsx-indent-props": "off",
30
+ "@stylistic/jsx-max-props-per-line": "off",
31
+ "@stylistic/jsx-newline": "off",
32
+ "@stylistic/jsx-one-expression-per-line": "off",
33
+ "@stylistic/jsx-pascal-case": "off",
34
+ "@stylistic/exp-jsx-props-style": "off", // experimental
35
+ "@stylistic/jsx-quotes": "off",
36
+ "@stylistic/jsx-self-closing-comp": "off",
37
+ "@stylistic/jsx-shorthand-boolean": "off",
38
+ "@stylistic/jsx-shorthand-fragment": "off",
39
+ "@stylistic/jsx-tag-spacing": "off",
40
+ "@stylistic/jsx-wrap-multilines": "off",
41
+ "@stylistic/key-spacing": "error",
42
+ "@stylistic/keyword-spacing": "error",
43
+ "@stylistic/line-comment-position": "off", // Без разницы где ставить комментарий
44
+ "@stylistic/linebreak-style": ["error", "unix"],
45
+ "@stylistic/lines-around-comment": "off", // Без разницы где ставить комментарий
46
+ "@stylistic/lines-between-class-members": ["error", {
47
+ enforce: [
48
+ { blankLine: "always", prev: "method", next: "method" },
49
+ { blankLine: "always", prev: "field", next: "method" },
50
+ { blankLine: "always", prev: "method", next: "field" },
51
+ ],
52
+ }, { exceptAfterOverload: true }],
53
+ "@stylistic/list-style": ["error", {
54
+ empty: "never",
55
+ overrides: {
56
+ // Сбрасываем defaults
57
+ "{}": "off",
58
+ "[]": "off",
59
+ "()": "off",
60
+ "<>": "off",
61
+ ArrayExpression: {}, // Создание массива a = [1, 2, 3] | function([1, 2, 3]),
62
+ ArrayPattern: {}, // Извлечение из массива [a, b] = c | function([a, b]) => a + b,
63
+ ArrowFunctionExpression: {}, // Параметры стрелоч. функции (a, b) => a + b
64
+ CallExpression: {}, // Вызов функции через () a(b, c)
65
+ FunctionDeclaration: {}, // Создание именованной функции function a(b, c)
66
+ FunctionExpression: {}, // Создание анонимной функции a = function(b, c)
67
+ IfStatement: {}, // Условие в if if (a)
68
+ NewExpression: {}, // Создание через new new a(b, c)
69
+ TSDeclareFunction: {}, // Оверлоад функции
70
+ TSFunctionType: {}, // Тип стрелочной нотации (a: B, c: D) => void
71
+ TSTupleType: {}, // Тип кортежа. Массив фикс. длины [a: B, c: D]
72
+ TSTypeParameterDeclaration: {}, // Типов объявлений функций type C<A, B>
73
+ TSTypeParameterInstantiation: {}, // Типы параметров a: Map<A, B>
74
+ JSONArrayExpression: {}, // "a": ["b", "c"]
75
+ ExportNamedDeclaration: { singleLine: { spacing: "always" } }, // export { a, b, c }
76
+ ImportDeclaration: { singleLine: { spacing: "always" } }, // import { a, b, c }
77
+ ImportAttributes: { singleLine: { spacing: "always" } }, // import ... with { a, b, c }
78
+ ObjectExpression: { singleLine: { spacing: "always" } }, // a = { a, b, c }
79
+ ObjectPattern: { singleLine: { spacing: "always" } }, // { a, b, c } = d
80
+ // [TODO]: ждем beta 7. multiline -> multiLine
81
+ TSInterfaceBody: { singleLine: { spacing: "always", maxItems: 1 } }, // interface A { a } | interface A { a,\n b }
82
+ // [TODO]: ждем beta 7. multiline -> multiLine
83
+ TSEnumBody: { singleLine: { maxItems: 0 } }, // enum {\n a,\n b }
84
+ TSTypeLiteral: { singleLine: { spacing: "always" } }, // a: { b: B, c: D }
85
+ JSONObjectExpression: { singleLine: { spacing: "always" } }, // "a": { "b": "c" }
86
+ },
87
+ }],
88
+ "@stylistic/max-len": ["error", {
89
+ code: options.maxCodeLength,
90
+ tabWidth: 1,
91
+ ignoreComments: true,
92
+ ignoreTrailingComments: true,
93
+ ignoreUrls: true,
94
+ ignoreStrings: true,
95
+ ignoreTemplateLiterals: true,
96
+ ignoreRegExpLiterals: true,
97
+ }],
98
+ "@stylistic/max-statements-per-line": ["error", { max: 1 }],
99
+ "@stylistic/member-delimiter-style": ["error", {
100
+ multiline: {
101
+ delimiter: "semi",
102
+ requireLast: true,
103
+ },
104
+ singleline: {
105
+ delimiter: "semi",
106
+ requireLast: false,
107
+ },
108
+ }],
109
+ "@stylistic/multiline-comment-style": "off",
110
+ "@stylistic/multiline-ternary": "off",
111
+ "@stylistic/new-parens": "error",
112
+ "@stylistic/newline-per-chained-call": "off",
113
+ "@stylistic/no-confusing-arrow": "off",
114
+ "@stylistic/no-extra-parens": ["error", "all", {
115
+ returnAssign: false, // return (a = b)
116
+ nestedBinaryExpressions: false, // (a || b) && c
117
+ ternaryOperandBinaryExpressions: false, // (a && b) ? foo : bar;
118
+ nestedConditionalExpressions: false, // (a ? b : c) ? d : e
119
+ ignoredNodes: [
120
+ "ArrowFunctionExpression[body.type=ConditionalExpression]", // x => (a ? b : c)
121
+ "SpreadElement[argument.type=ConditionalExpression]", // ...(a ? [1, 2, 3] : []),
122
+ "SpreadElement[argument.type=LogicalExpression]", // ...(isSummer && { watermelon: 30 }),
123
+ "SpreadElement[argument.type=AwaitExpression]", // ...(await promiseArray)
124
+ ],
125
+ }],
126
+ "@stylistic/no-extra-semi": "error",
127
+ "@stylistic/no-floating-decimal": "error",
128
+ "@stylistic/no-mixed-operators": ["error", {
129
+ groups: [["&&", "||", "?:"]],
130
+ allowSamePrecedence: true,
131
+ }],
132
+ "@stylistic/no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
133
+ "@stylistic/no-multi-spaces": "error", // Для некоторых проектов можно разрешать const a = '' для красоты
134
+ "@stylistic/no-multiple-empty-lines": ["error", { max: 1, maxBOF: 0, maxEOF: 1 }],
135
+ "@stylistic/no-tabs": "off",
136
+ "@stylistic/no-trailing-spaces": ["error", { ignoreComments: true }],
137
+ "@stylistic/no-whitespace-before-property": "error",
138
+ "@stylistic/nonblock-statement-body-position": "error",
139
+ "@stylistic/one-var-declaration-per-line": "off",
140
+ "@stylistic/operator-linebreak": ["error", "after", {
141
+ overrides: {
142
+ "?": "before",
143
+ ":": "before",
144
+ "|": "before",
145
+ "&": "before",
146
+ },
147
+ }],
148
+ "@stylistic/padded-blocks": ["error", "never"],
149
+ "@stylistic/padding-line-between-statements": "off", // Вообще шикарное правило, нужно долго настраивать, но мне лень
150
+ "@stylistic/quote-props": ["error", "as-needed"],
151
+ "@stylistic/quotes": ["error", "double"],
152
+ "@stylistic/rest-spread-spacing": ["error", "never"],
153
+ "@stylistic/semi": "error",
154
+ "@stylistic/semi-spacing": "error",
155
+ "@stylistic/semi-style": "error",
156
+ "@stylistic/space-before-blocks": "error",
157
+ "@stylistic/space-before-function-paren": ["error", {
158
+ anonymous: "always", // function () {}
159
+ named: "never", // function foo() {}
160
+ asyncArrow: "always", // async () => {}
161
+ }],
162
+ "@stylistic/space-in-parens": ["error", "never"],
163
+ "@stylistic/space-infix-ops": "error",
164
+ "@stylistic/space-unary-ops": "error",
165
+ "@stylistic/spaced-comment": "error",
166
+ "@stylistic/switch-colon-spacing": "error",
167
+ "@stylistic/template-curly-spacing": "error",
168
+ "@stylistic/template-tag-spacing": ["error", "never"],
169
+ "@stylistic/type-annotation-spacing": "error",
170
+ "@stylistic/type-generic-spacing": ["error", { before: false, after: false }], // foo<T>()
171
+ "@stylistic/type-named-tuple-spacing": "error",
172
+ "@stylistic/wrap-iife": ["error", "inside"],
173
+ "@stylistic/wrap-regex": "off",
174
+ "@stylistic/yield-star-spacing": "error",
175
+ };
149
176
  };
@@ -1,3 +1,3 @@
1
- import { Linter } from "eslint";
1
+ import type { Linter } from "eslint";
2
2
  export declare const typescriptRules: Linter.RulesRecord;
3
3
  export declare const typescriptTypeAwareRules: Linter.RulesRecord;
@@ -1,4 +1,3 @@
1
- import { Linter } from "eslint";
2
1
  export const typescriptRules = {
3
2
  // TypeScript знает лучше
4
3
  "constructor-super": "off",
@@ -19,6 +18,9 @@ export const typescriptRules = {
19
18
  "no-unsafe-negation": "off",
20
19
  "no-invalid-this": "off",
21
20
  "no-redeclare": "off",
21
+ "import-x/default": "off",
22
+ "import-x/named": "off",
23
+ "import-x/namespace": "off",
22
24
  "@typescript-eslint/adjacent-overload-signatures": "error",
23
25
  "@typescript-eslint/array-type": ["error", { default: "array-simple" }],
24
26
  "@typescript-eslint/ban-ts-comment": ["error", { "ts-expect-error": "allow-with-description" }],
@@ -49,6 +51,7 @@ export const typescriptRules = {
49
51
  "@typescript-eslint/no-explicit-any": "error",
50
52
  "@typescript-eslint/no-extra-non-null-assertion": "error",
51
53
  "@typescript-eslint/no-extraneous-class": "off",
54
+ "@typescript-eslint/no-generated-empty-object-type": "error",
52
55
  "@typescript-eslint/no-import-type-side-effects": "off", // есть import/consistent-type-specifier-style
53
56
  "@typescript-eslint/no-inferrable-types": "error",
54
57
  "@typescript-eslint/no-invalid-this": "off", // есть no-invalid-this
@@ -109,46 +112,42 @@ export const typescriptTypeAwareRules = {
109
112
  "id-length": "off",
110
113
  "no-underscore-dangle": "off",
111
114
  camelcase: "off",
112
- "@typescript-eslint/naming-convention": ["error",
113
- {
115
+ "@typescript-eslint/naming-convention": ["error", {
114
116
  selector: "default",
115
117
  format: null,
116
118
  leadingUnderscore: "allowSingleOrDouble",
117
- },
118
- {
119
+ }, {
119
120
  selector: ["variableLike", "import"],
120
121
  format: ["camelCase", "PascalCase"],
121
122
  leadingUnderscore: "allowSingleOrDouble",
122
- },
123
- {
123
+ }, {
124
124
  selector: ["method", "classProperty", "typeProperty"],
125
125
  format: ["camelCase"],
126
126
  leadingUnderscore: "allowSingleOrDouble",
127
- },
128
- {
127
+ }, {
129
128
  selector: ["typeLike", "enumMember"],
130
129
  format: ["PascalCase"],
131
130
  leadingUnderscore: "forbid",
132
- },
133
- {
131
+ }, {
134
132
  selector: "variable",
135
133
  modifiers: ["const", "global"],
136
134
  format: ["UPPER_CASE", "camelCase", "PascalCase"],
137
- },
138
- {
135
+ }, {
139
136
  selector: "variable",
140
137
  modifiers: ["destructured"],
141
138
  format: null, // const { user_id, created_at } = await response.json();
142
- },
143
- ],
139
+ }],
144
140
  "@typescript-eslint/no-array-delete": "error",
145
141
  "@typescript-eslint/no-base-to-string": "error",
146
142
  "@typescript-eslint/no-confusing-void-expression": "off",
143
+ "@typescript-eslint/no-duplicate-type-constituents": "error",
147
144
  "@typescript-eslint/no-floating-promises": ["error", {
148
145
  ignoreIIFE: true,
149
146
  }],
150
147
  "@typescript-eslint/no-for-in-array": "error",
151
- "@typescript-eslint/no-implied-eval": "off", // есть no-implied-eval
148
+ "no-implied-eval": "off", // core ловит только строковые литералы
149
+ "no-new-func": "off",
150
+ "@typescript-eslint/no-implied-eval": "error", // + любые string по типу и new Function
152
151
  "@typescript-eslint/no-meaningless-void-operator": "error",
153
152
  "@typescript-eslint/no-misused-promises": ["error", {
154
153
  checksVoidReturn: {
@@ -159,7 +158,9 @@ export const typescriptTypeAwareRules = {
159
158
  "@typescript-eslint/no-mixed-enums": "error",
160
159
  "@typescript-eslint/no-redundant-type-constituents": "error",
161
160
  "@typescript-eslint/no-unnecessary-boolean-literal-compare": "error",
162
- "@typescript-eslint/no-unnecessary-condition": "error",
161
+ "@typescript-eslint/no-unnecessary-condition": ["error", {
162
+ allowConstantLoopConditions: "only-allowed-literals", // while (true)
163
+ }],
163
164
  "@typescript-eslint/no-unnecessary-qualifier": "error",
164
165
  "@typescript-eslint/no-unnecessary-template-expression": "error",
165
166
  "@typescript-eslint/no-unnecessary-type-arguments": "error",
@@ -178,13 +179,15 @@ export const typescriptTypeAwareRules = {
178
179
  "@typescript-eslint/non-nullable-type-assertion-style": "error",
179
180
  "no-throw-literal": "off",
180
181
  "@typescript-eslint/only-throw-error": ["error", {
181
- allowRethrowing: true
182
+ allowRethrowing: true,
182
183
  }],
183
184
  "prefer-destructuring": "off",
184
185
  "@typescript-eslint/prefer-destructuring": ["error", { array: true, object: false }],
185
186
  "@typescript-eslint/prefer-find": "error",
186
187
  "@typescript-eslint/prefer-includes": "error",
187
- "@typescript-eslint/prefer-nullish-coalescing": "error",
188
+ "@typescript-eslint/prefer-nullish-coalescing": ["error", {
189
+ ignoreIfStatements: true, // if (!a) a = b; -> a ||= b делает logical-assignment-operators, дальше это правило предложит ??=
190
+ }],
188
191
  "@typescript-eslint/prefer-optional-chain": "error",
189
192
  "prefer-promise-reject-errors": "off",
190
193
  "@typescript-eslint/prefer-promise-reject-errors": ["error", {
package/package.json CHANGED
@@ -1,35 +1,38 @@
1
- {
2
- "name": "@xaliksss/eslint-config",
3
- "version": "4.0.4",
4
- "main": "dist/index.js",
5
- "type": "module",
6
- "author": {
7
- "name": "Xaliks",
8
- "url": "https://github.com/Xaliks"
9
- },
10
- "repository": {
11
- "type": "git",
12
- "url": "git+https://github.com/Xaliks/eslint-config.git"
13
- },
14
- "files": [
15
- "dist"
16
- ],
17
- "exports": {
18
- ".": "./dist/index.js"
19
- },
20
- "scripts": {
21
- "build": "tsc"
22
- },
23
- "license": "MIT",
24
- "dependencies": {
25
- "@stylistic/eslint-plugin": "5.10.0",
26
- "eslint": "10.10.0",
27
- "eslint-plugin-import-x": "^4.17.1",
28
- "eslint-plugin-n": "^18.3.0",
29
- "globals": "17.12.0",
30
- "typescript-eslint": "8.69.0"
31
- },
32
- "devDependencies": {
33
- "typescript": "^6.0.3"
34
- }
35
- }
1
+ {
2
+ "name": "@xaliksss/eslint-config",
3
+ "version": "5.0.1",
4
+ "main": "dist/index.js",
5
+ "type": "module",
6
+ "author": {
7
+ "name": "Xaliks",
8
+ "url": "https://github.com/Xaliks"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/Xaliks/eslint-config.git"
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "exports": {
18
+ ".": "./dist/index.js"
19
+ },
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "inspect": "npx @eslint/config-inspector@latest"
23
+ },
24
+ "license": "MIT",
25
+ "dependencies": {
26
+ "@stylistic/eslint-plugin": "6.0.0-beta.6",
27
+ "eslint": "10.11.0",
28
+ "eslint-plugin-import-x": "^4.17.1",
29
+ "eslint-plugin-n": "^18.3.0",
30
+ "globals": "17.12.0",
31
+ "typescript-eslint": "8.70.1"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "24",
35
+ "jiti": "^2.7.0",
36
+ "typescript": "^6.0.3"
37
+ }
38
+ }