@open-xchange/linter-presets 0.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.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -0
  3. package/doc/eslint.md +343 -0
  4. package/doc/stylelint.md +3 -0
  5. package/doc/utils.md +30 -0
  6. package/lib/eslint/config/base.js +136 -0
  7. package/lib/eslint/config/directives.js +21 -0
  8. package/lib/eslint/config/js.js +36 -0
  9. package/lib/eslint/config/jsdoc.js +55 -0
  10. package/lib/eslint/config/json.js +37 -0
  11. package/lib/eslint/config/license.js +33 -0
  12. package/lib/eslint/config/promises.js +33 -0
  13. package/lib/eslint/config/stylistic.js +123 -0
  14. package/lib/eslint/config/ts.js +100 -0
  15. package/lib/eslint/config/yaml.js +34 -0
  16. package/lib/eslint/env/browser.d.ts +13 -0
  17. package/lib/eslint/env/browser.js +127 -0
  18. package/lib/eslint/env/codecept.d.ts +13 -0
  19. package/lib/eslint/env/codecept.js +70 -0
  20. package/lib/eslint/env/jest.d.ts +13 -0
  21. package/lib/eslint/env/jest.js +56 -0
  22. package/lib/eslint/env/node.d.ts +21 -0
  23. package/lib/eslint/env/node.js +59 -0
  24. package/lib/eslint/env/plugin.d.ts +13 -0
  25. package/lib/eslint/env/plugin.js +61 -0
  26. package/lib/eslint/env/react.d.ts +19 -0
  27. package/lib/eslint/env/react.js +103 -0
  28. package/lib/eslint/env/tsconfig.d.ts +19 -0
  29. package/lib/eslint/env/tsconfig.js +37 -0
  30. package/lib/eslint/env/vitest.d.ts +13 -0
  31. package/lib/eslint/env/vitest.js +103 -0
  32. package/lib/eslint/index.d.ts +90 -0
  33. package/lib/eslint/index.js +106 -0
  34. package/lib/eslint/shared/constants.js +33 -0
  35. package/lib/eslint/shared/types.d.ts +90 -0
  36. package/lib/index.d.ts +3 -0
  37. package/lib/index.js +3 -0
  38. package/lib/utils/index.d.ts +4 -0
  39. package/lib/utils/index.js +18 -0
  40. package/package.json +61 -0
@@ -0,0 +1,56 @@
1
+
2
+ import jestPlugin from "eslint-plugin-jest";
3
+
4
+ // functions ==================================================================
5
+
6
+ /**
7
+ * Creates configuration objects with global symbols and linter rules for unit
8
+ * tests using Jest.
9
+ *
10
+ * Wraps the following packages:
11
+ * - `eslint-plugin-jest`
12
+ *
13
+ * @param {import("./jest").EnvJestOptions} options
14
+ * Configuration options for the environment.
15
+ *
16
+ * @returns {import("../shared/types").FlatConfigArray}
17
+ * An array of configuration objects to be added to the flat configuration.
18
+ */
19
+ export default function jest(options) {
20
+
21
+ // config properties
22
+ const { files, ignores = [], rules } = options;
23
+
24
+ return [{
25
+ files,
26
+ ignores,
27
+
28
+ // register rule implementations, globals
29
+ ...jestPlugin.configs["flat/recommended"],
30
+
31
+ // configure plugin rules
32
+ rules: {
33
+ // recommended rules
34
+ ...jestPlugin.configs["flat/recommended"].rules,
35
+ ...jestPlugin.configs["flat/style"].rules,
36
+ // extra rules
37
+ "jest/consistent-test-it": ["error", { fn: "it" }],
38
+ "jest/no-commented-out-tests": "error",
39
+ "jest/no-conditional-expect": "off",
40
+ "jest/no-confusing-set-timeout": "error",
41
+ "jest/no-duplicate-hooks": "error",
42
+ "jest/no-test-return-statement": "error",
43
+ "jest/prefer-comparison-matcher": "error",
44
+ "jest/prefer-equality-matcher": "error",
45
+ "jest/prefer-expect-resolves": "error",
46
+ "jest/prefer-hooks-on-top": "error",
47
+ "jest/prefer-lowercase-title": "error",
48
+ "jest/prefer-mock-promise-shorthand": "error",
49
+ "jest/prefer-spy-on": "error",
50
+ "jest/prefer-todo": "error",
51
+ "jest/require-top-level-describe": "error",
52
+ // custom rules
53
+ ...rules,
54
+ },
55
+ }];
56
+ }
@@ -0,0 +1,21 @@
1
+
2
+ import { FlatConfigArray, LanguageOptions, EnvBaseOptions } from "../shared/types.js";
3
+
4
+ // types ======================================================================
5
+
6
+ /**
7
+ * Configuration options for the environment preset "env.node".
8
+ */
9
+ export interface EnvNodeOptions extends EnvBaseOptions {
10
+
11
+ /**
12
+ * The module mode used by the linted files.
13
+ *
14
+ * Default value is "module".
15
+ */
16
+ sourceType?: LanguageOptions["sourceType"];
17
+ }
18
+
19
+ // functions ==================================================================
20
+
21
+ export default function node(options: EnvNodeOptions): FlatConfigArray;
@@ -0,0 +1,59 @@
1
+
2
+ // replacement for abandoned "eslint-plugin-node"
3
+ // - https://github.com/mysticatea/eslint-plugin-node/issues/341
4
+ import nodePlugin from "eslint-plugin-n";
5
+
6
+ import { RESTRICTED_GLOBALS, RESTRICTED_SYNTAX } from "../shared/constants.js";
7
+
8
+ // functions ==================================================================
9
+
10
+ /**
11
+ * Creates configuration objects with global symbols and linter rules for
12
+ * NodeJS modules.
13
+ *
14
+ * Wraps the following packages:
15
+ * - `eslint-plugin-n`
16
+ *
17
+ * @param {import("./node").EnvNodeOptions} options
18
+ * Configuration options for the environment.
19
+ *
20
+ * @returns {import("../shared/types").FlatConfigArray}
21
+ * An array of configuration objects to be added to the flat configuration.
22
+ */
23
+ export default function node(options) {
24
+
25
+ // configuration properties
26
+ const { files, ignores = [], sourceType = "module", rules } = options;
27
+ // the plugin configuration
28
+ const configKey = (sourceType === "commonjs") ? "flat/recommended-script" : "flat/recommended-module";
29
+ const nodeConfig = nodePlugin.configs[configKey];
30
+
31
+ return [
32
+
33
+ // register rule implementations and global symbols
34
+ {
35
+ files,
36
+ ignores,
37
+ ...nodeConfig,
38
+ // automatically add missing extensions in imports of CommonJS scripts
39
+ settings: {
40
+ node: {
41
+ tryExtensions: [".js", ".ts"],
42
+ },
43
+ },
44
+ },
45
+
46
+ // reconfigure plugin rules
47
+ {
48
+ files,
49
+ ignores,
50
+ rules: {
51
+ "no-restricted-globals": ["error", ...RESTRICTED_GLOBALS],
52
+ "no-restricted-syntax": ["error", ...RESTRICTED_SYNTAX],
53
+ "n/no-unsupported-features/node-builtins": ["error", { allowExperimental: true }],
54
+ "n/prefer-node-protocol": "error",
55
+ ...rules,
56
+ },
57
+ },
58
+ ];
59
+ }
@@ -0,0 +1,13 @@
1
+
2
+ import { FlatConfigArray, EnvBaseOptions } from "../shared/types.js";
3
+
4
+ // types ======================================================================
5
+
6
+ /**
7
+ * Configuration options for the environment preset "env.plugin".
8
+ */
9
+ export interface EnvPluginOptions extends EnvBaseOptions { }
10
+
11
+ // functions ==================================================================
12
+
13
+ export default function plugin(options: EnvPluginOptions): FlatConfigArray;
@@ -0,0 +1,61 @@
1
+ /*
2
+ * @copyright Copyright (c) Open-Xchange GmbH, Germany <info@open-xchange.com>
3
+ * @license AGPL-3.0
4
+ *
5
+ * This code is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU Affero General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU Affero General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License
16
+ * along with OX App Suite. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
17
+ *
18
+ * Any use of the work other than as authorized under this license or copyright law is prohibited.
19
+ *
20
+ */
21
+
22
+ import eslintPlugin from "eslint-plugin-eslint-plugin";
23
+
24
+ // exports ====================================================================
25
+
26
+ /**
27
+ * Adds linter rules for ESLint plugin implementations.
28
+ *
29
+ * Wraps the following packages:
30
+ * - `eslint-plugin-eslint-plugin`
31
+ *
32
+ * @param {import("./plugin").EnvPluginOptions} options
33
+ * Configuration options for the environment.
34
+ *
35
+ * @returns {import("../shared/types").FlatConfigArray}
36
+ * An array of configuration objects to be added to the flat configuration.
37
+ */
38
+ export default function plugin(options) {
39
+
40
+ // configuration properties
41
+ const { files, ignores = [], rules = {} } = options;
42
+ // the plugin configuration
43
+ const pluginConfig = eslintPlugin.configs["flat/rules-recommended"];
44
+
45
+ return [
46
+
47
+ // register rule implementations and recommended rules
48
+ {
49
+ files,
50
+ ignores,
51
+ ...pluginConfig,
52
+ },
53
+
54
+ // reconfigure plugin rules
55
+ {
56
+ files,
57
+ ignores,
58
+ rules,
59
+ },
60
+ ];
61
+ }
@@ -0,0 +1,19 @@
1
+
2
+ import { FlatConfigArray, EnvBaseOptions } from "../shared/types.js";
3
+
4
+ // types ======================================================================
5
+
6
+ /**
7
+ * Configuration options for the environment preset "env.react".
8
+ */
9
+ export interface EnvReactOptions extends EnvBaseOptions {
10
+
11
+ /**
12
+ * Configuration for the rule "react-hooks-static-deps/exhaustive-deps".
13
+ */
14
+ staticHooks?: Record<string, boolean | readonly boolean[] | Record<string, boolean>>;
15
+ }
16
+
17
+ // functions ==================================================================
18
+
19
+ export default function react(options: EnvReactOptions): FlatConfigArray;
@@ -0,0 +1,103 @@
1
+
2
+ import { fixupPluginRules } from "@eslint/compat";
3
+ import reactPlugin from "eslint-plugin-react";
4
+ import reactHooksPlugin from "eslint-plugin-react-hooks";
5
+ import reactHooksStaticDepsPlugin from "eslint-plugin-react-hooks-static-deps";
6
+ import reactRefreshPlugin from "eslint-plugin-react-refresh";
7
+ import jsxExpressionsPlugin from "eslint-plugin-jsx-expressions";
8
+ import jsxA11yPlugin from "eslint-plugin-jsx-a11y";
9
+
10
+ // functions ==================================================================
11
+
12
+ /**
13
+ * Creates configuration objects with linter rules for ReactJS.
14
+ *
15
+ * Wraps the following packages:
16
+ * - `eslint-plugin-react`
17
+ * - `eslint-plugin-react-hooks`
18
+ * - `eslint-plugin-react-hooks-static-deps`
19
+ * - `eslint-plugin-react-refresh`
20
+ * - `eslint-plugin-jsx-expressions`
21
+ * - `eslint-plugin-jsx-a11y`
22
+ *
23
+ * @param {import("./react").EnvReactOptions} options
24
+ * Configuration options for the environment.
25
+ *
26
+ * @returns {import("../shared/types").FlatConfigArray}
27
+ * An array of configuration objects to be added to the flat configuration.
28
+ */
29
+ export default function react(options) {
30
+
31
+ // configuration properties
32
+ const { files, ignores = [], rules, staticHooks = {} } = options;
33
+
34
+ return [
35
+
36
+ // configure plugins and rules for all source files (JSX and TSX)
37
+ {
38
+ files,
39
+ ignores,
40
+
41
+ // register rule implementations of the plugins
42
+ plugins: {
43
+ react: fixupPluginRules(reactPlugin), // https://github.com/jsx-eslint/eslint-plugin-react/issues/3699
44
+ "react-hooks": reactHooksPlugin,
45
+ "react-hooks-static-deps": fixupPluginRules(reactHooksStaticDepsPlugin), // https://github.com/stoikio/eslint-plugin-react-hooks-static-deps/issues/1
46
+ "react-refresh": reactRefreshPlugin,
47
+ "jsx-expressions": fixupPluginRules(jsxExpressionsPlugin), // https://github.com/hluisson/eslint-plugin-jsx-expressions/issues/18
48
+ "jsx-a11y": jsxA11yPlugin,
49
+ },
50
+
51
+ settings: {
52
+ react: {
53
+ version: "detect",
54
+ },
55
+ },
56
+
57
+ // enable JSX support
58
+ languageOptions: {
59
+ parserOptions: reactPlugin.configs.recommended.parserOptions,
60
+ },
61
+
62
+ // configure plugin rules
63
+ rules: {
64
+ // recommended rules
65
+ ...reactPlugin.configs.recommended.rules,
66
+ ...reactPlugin.configs["jsx-runtime"].rules,
67
+ ...reactHooksPlugin.configs.recommended.rules,
68
+ ...jsxA11yPlugin.flatConfigs.recommended.rules,
69
+ // "react" plugin: change or disable a few recommended rules
70
+ "react/hook-use-state": "error",
71
+ "react/iframe-missing-sandbox": "error",
72
+ "react/jsx-boolean-value": "error",
73
+ "react/jsx-no-script-url": "error",
74
+ "react/jsx-no-useless-fragment": "error",
75
+ "react/no-danger": "error",
76
+ "react/no-invalid-html-attribute": "error",
77
+ "react/no-typos": "error",
78
+ "react/prop-types": ["error", { skipUndeclared: true }],
79
+ "react/style-prop-object": "error",
80
+ "react/void-dom-elements-no-children": "error",
81
+ // replace "react-hooks/exhaustive-deps" rule with advanced alternative
82
+ "react-hooks/exhaustive-deps": "off",
83
+ "react-hooks-static-deps/exhaustive-deps": ["error", { staticHooks }],
84
+ // "react-refresh" plugin
85
+ "react-refresh/only-export-components": ["error", { allowConstantExport: true }],
86
+ // custom rules
87
+ ...rules,
88
+ },
89
+ },
90
+
91
+ // additional rules for TSX only
92
+ {
93
+ files,
94
+ ignores: [...ignores, "**/*.{js,jsx}"],
95
+
96
+ // configure plugin rules
97
+ rules: {
98
+ // replace "react/jsx-no-leaked-render" rule with advanced alternative
99
+ "jsx-expressions/strict-logical-expressions": "error",
100
+ },
101
+ },
102
+ ];
103
+ }
@@ -0,0 +1,19 @@
1
+
2
+ import { FlatConfigArray, EnvBaseOptions } from "../shared/types.js";
3
+
4
+ // types ======================================================================
5
+
6
+ /**
7
+ * Configuration options for the environment preset "env.tsconfig".
8
+ */
9
+ export interface EnvTSConfigOptions extends EnvBaseOptions {
10
+
11
+ /**
12
+ * The path to the TypeScript project configuration file (`tsconfig.json`).
13
+ */
14
+ project: string;
15
+ }
16
+
17
+ // functions ==================================================================
18
+
19
+ export default function tsconfig(options: EnvTSConfigOptions): FlatConfigArray;
@@ -0,0 +1,37 @@
1
+
2
+ // functions ==================================================================
3
+
4
+ /**
5
+ * Creates configuration objects for TypeScript projects.
6
+ *
7
+ * @param {import("./tsconfig").EnvTSConfigOptions} options
8
+ * Configuration options for the environment.
9
+ *
10
+ * @returns {import("../shared/types").FlatConfigArray}
11
+ * An array of configuration objects to be added to the flat configuration.
12
+ */
13
+ export default function tsconfig(options) {
14
+
15
+ // configuration properties
16
+ const { files, ignores = [], rules } = options;
17
+
18
+ return [{
19
+ files,
20
+ ignores,
21
+
22
+ // path to project configuration file
23
+ languageOptions: {
24
+ parserOptions: {
25
+ project: options.project,
26
+ },
27
+ },
28
+
29
+ // configure plugin rules
30
+ rules: {
31
+ // imports will be checked by TSC
32
+ "n/no-missing-import": "off",
33
+ // custom rules
34
+ ...rules,
35
+ },
36
+ }];
37
+ }
@@ -0,0 +1,13 @@
1
+
2
+ import { FlatConfigArray, EnvBaseOptions } from "../shared/types.js";
3
+
4
+ // types ======================================================================
5
+
6
+ /**
7
+ * Configuration options for the environment preset "env.vitest".
8
+ */
9
+ export interface EnvVitestOptions extends EnvBaseOptions { }
10
+
11
+ // functions ==================================================================
12
+
13
+ export default function vitest(options: EnvVitestOptions): FlatConfigArray;
@@ -0,0 +1,103 @@
1
+
2
+ import { fixupPluginRules } from "@eslint/compat";
3
+ import vitestPlugin from "eslint-plugin-vitest";
4
+ import jestDomPlugin from "eslint-plugin-jest-dom";
5
+ import testingLibraryPlugin from "eslint-plugin-testing-library";
6
+
7
+ // functions ==================================================================
8
+
9
+ /**
10
+ * Creates configuration objects with global symbols and linter rules for unit
11
+ * tests using Vitest.
12
+ *
13
+ * Wraps the following packages:
14
+ * - `eslint-plugin-vitest`
15
+ * - `eslint-plugin-jest-dom`
16
+ * - `eslint-plugin-testing-library`
17
+ *
18
+ * @param {import("./vitest").EnvVitestOptions} options
19
+ * Configuration options for the environment.
20
+ *
21
+ * @returns {import("../shared/types").FlatConfigArray}
22
+ * An array of configuration objects to be added to the flat configuration.
23
+ */
24
+ export default function vitest(options) {
25
+
26
+ // configuration properties
27
+ const { files, ignores = [], rules } = options;
28
+
29
+ return [
30
+
31
+ // "vitest" plugin
32
+ {
33
+ files,
34
+ ignores,
35
+
36
+ // register rule implementations of the plugins
37
+ plugins: {
38
+ vitest: vitestPlugin,
39
+ },
40
+
41
+ // register global symbols of Vitest
42
+ languageOptions: {
43
+ globals: vitestPlugin.environments.env.globals,
44
+ },
45
+
46
+ // configure plugin rules
47
+ rules: {
48
+ // recommended rules
49
+ ...vitestPlugin.configs.recommended.rules,
50
+ // extra rules
51
+ "vitest/consistent-test-it": "error",
52
+ "vitest/no-alias-methods": "error",
53
+ "vitest/no-disabled-tests": "warn",
54
+ "vitest/no-duplicate-hooks": "error",
55
+ "vitest/no-focused-tests": "error",
56
+ "vitest/no-standalone-expect": "error",
57
+ "vitest/no-test-prefixes": "error",
58
+ "vitest/no-test-return-statement": "error",
59
+ "vitest/prefer-comparison-matcher": "error",
60
+ "vitest/prefer-each": "error",
61
+ "vitest/prefer-equality-matcher": "error",
62
+ "vitest/prefer-expect-resolves": "error",
63
+ "vitest/prefer-hooks-in-order": "error",
64
+ "vitest/prefer-hooks-on-top": "error",
65
+ "vitest/prefer-mock-promise-shorthand": "error",
66
+ "vitest/prefer-spy-on": "error",
67
+ "vitest/prefer-strict-equal": "error",
68
+ "vitest/prefer-to-be": "error",
69
+ "vitest/prefer-to-contain": "error",
70
+ "vitest/prefer-to-have-length": "error",
71
+ "vitest/require-top-level-describe": "error",
72
+ // custom rules
73
+ ...rules,
74
+ },
75
+ },
76
+
77
+ // "jest-dom" plugin
78
+ {
79
+ files,
80
+ ignores,
81
+ ...jestDomPlugin.configs["flat/recommended"],
82
+ },
83
+
84
+ // "testing-library" plugin
85
+ {
86
+ files,
87
+ ignores,
88
+
89
+ // register rule implementations of the plugins
90
+ plugins: {
91
+ "testing-library": fixupPluginRules(testingLibraryPlugin), // https://github.com/testing-library/eslint-plugin-testing-library/issues/899
92
+ },
93
+
94
+ // configure plugin rules
95
+ rules: {
96
+ // recommended rules
97
+ ...testingLibraryPlugin.configs.react.rules,
98
+ // extra rules
99
+ "testing-library/no-node-access": ["error", { allowContainerFirstChild: true }],
100
+ },
101
+ },
102
+ ];
103
+ }
@@ -0,0 +1,90 @@
1
+
2
+ import { Linter } from "eslint";
3
+
4
+ import { FlatConfigArray, LanguageOptions, StylisticOptions } from "./shared/types";
5
+
6
+ import tsconfig from "./env/tsconfig";
7
+ import node from "./env/node";
8
+ import browser from "./env/browser";
9
+ import jest from "./env/jest";
10
+ import vitest from "./env/vitest";
11
+ import codecept from "./env/codecept";
12
+ import react from "./env/react";
13
+ import plugin from "./env/plugin";
14
+
15
+ // types ======================================================================
16
+
17
+ /**
18
+ * Configuration options for linting the entire project.
19
+ */
20
+ export interface ESLintPresetsOptions {
21
+
22
+ /**
23
+ * Glob patterns with all files and folders to be ignored by ESlint.
24
+ */
25
+ ignores?: readonly string[];
26
+
27
+ /**
28
+ * Full path to the template file containing the license header to be used
29
+ * in all source files. The function `resolver` helps to to convert a local
30
+ * path to an absolute path.
31
+ */
32
+ license?: string;
33
+
34
+ /**
35
+ * Configuration options for language and project setup.
36
+ */
37
+ language?: LanguageOptions;
38
+
39
+ /**
40
+ * Configuration options for code style.
41
+ */
42
+ stylistic?: StylisticOptions;
43
+
44
+ /**
45
+ * Additional linter rules to be added to the global configuration.
46
+ */
47
+ rules?: Linter.RulesRecord;
48
+ }
49
+
50
+ // environments ===============================================================
51
+
52
+ /**
53
+ * A collection with all available environment presets.
54
+ */
55
+ export const env: {
56
+ tsconfig: typeof tsconfig;
57
+ node: typeof node;
58
+ browser: typeof browser;
59
+ jest: typeof jest;
60
+ vitest: typeof vitest;
61
+ codecept: typeof codecept;
62
+ react: typeof react;
63
+ plugin: typeof plugin;
64
+ };
65
+
66
+ // functions ==================================================================
67
+
68
+ /**
69
+ * Creates and returns a resolver function for file paths relative to the given
70
+ * base URL of a script file.
71
+ *
72
+ * @param url
73
+ * The base URL of the calling script, usually `import.meta.url`.
74
+ *
75
+ * @returns
76
+ * A function that converts relative file paths to absolute file paths.
77
+ */
78
+ export function resolver(url: string): (file: string) => string;
79
+
80
+ /**
81
+ * Defines standard configuration objects targeting the source files in the
82
+ * entire project.
83
+ *
84
+ * @param config
85
+ * Plugin configuration.
86
+ *
87
+ * @returns
88
+ * An array of configuration objects to be added to the flat configuration.
89
+ */
90
+ export function configure(config?: ESLintPresetsOptions): FlatConfigArray;