@forthtilliath/eslint-config 0.2.1 → 0.3.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/README.md CHANGED
@@ -93,15 +93,30 @@ import { createBaseConfig } from "@forthtilliath/eslint-config";
93
93
  export default createBaseConfig({ strict: false, turbo: false });
94
94
  ```
95
95
 
96
- | Option | Default | Effect |
97
- | ---------- | ------- | ------------------------------------------------------------------------------ |
98
- | `prettier` | `true` | Append `eslint-config-prettier` at the end. |
99
- | `strict` | `true` | Use `strictTypeChecked`/`stylisticTypeChecked` instead of plain `recommended`. |
100
- | `turbo` | `true` | Enable `eslint-plugin-turbo`'s `no-undeclared-env-vars` rule. |
96
+ | Option | Default | Effect |
97
+ | ---------------- | ------- | ----------------------------------------------------------------------------------------------------------- |
98
+ | `prettier` | `true` | Append `eslint-config-prettier` at the end. |
99
+ | `strict` | `true` | Use `strictTypeChecked`/`stylisticTypeChecked` instead of plain `recommended`. |
100
+ | `turbo` | `true` | Enable `eslint-plugin-turbo`'s `no-undeclared-env-vars` rule. |
101
+ | `a11y` | `true` | _(react/nextjs/storybook)_ Enable `eslint-plugin-jsx-a11y`'s recommended rules. |
102
+ | `i18n` | `false` | _(react/nextjs/storybook)_ Enable `eslint-plugin-i18next`'s `no-literal-string` rule. |
103
+ | `testingLibrary` | `false` | _(react/nextjs/storybook)_ Enable `eslint-plugin-testing-library` + `eslint-plugin-jest-dom` on test files. |
101
104
 
102
105
  Options are forwarded down the chain, so `createNextJsConfig({ prettier: false })`
103
106
  also disables Prettier in the `reactConfig`/`baseConfig` layers it builds on.
104
107
 
108
+ ```ts
109
+ // Full i18n project (next-intl, react-intl...): forbid hardcoded JSX strings
110
+ import { createNextJsConfig } from "@forthtilliath/eslint-config/nextjs";
111
+ export default createNextJsConfig({ i18n: true });
112
+ ```
113
+
114
+ ```ts
115
+ // React Native / Expo: jsx-a11y targets DOM semantics and doesn't apply
116
+ import { createReactConfig } from "@forthtilliath/eslint-config/react";
117
+ export default createReactConfig({ a11y: false });
118
+ ```
119
+
105
120
  ### Typed linting and non-project files
106
121
 
107
122
  Rules that need type information (`consistent-type-exports`,
package/dist/nextjs.d.ts CHANGED
@@ -3,10 +3,10 @@
3
3
  * {@link createReactConfig} (same React/naming-convention rules, plus
4
4
  * Next.js's own plugin).
5
5
  *
6
- * @param {import("./base.js").BaseConfigOptions} [options]
6
+ * @param {import("./base.js").BaseConfigOptions & import("./react.js").ReactConfigOptions} [options]
7
7
  * @returns {import("eslint").Linter.Config[]}
8
8
  * */
9
- export function createNextJsConfig(options?: import("./base.js").BaseConfigOptions): import("eslint").Linter.Config[];
9
+ export function createNextJsConfig(options?: import("./base.js").BaseConfigOptions & import("./react.js").ReactConfigOptions): import("eslint").Linter.Config[];
10
10
  /**
11
11
  * A custom ESLint configuration for Next.js applications, with the default
12
12
  * options. Use `createNextJsConfig(options)` instead to customize it.
@@ -1 +1 @@
1
- {"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../src/nextjs.js"],"names":[],"mappings":"AAKA;;;;;;;KAOK;AACL,6CAHW,OAAO,WAAW,EAAE,iBAAiB,GACnC,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CA6C5C;AAED;;;;;KAKK;AACL,2BAFU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAEO"}
1
+ {"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../src/nextjs.js"],"names":[],"mappings":"AAKA;;;;;;;KAOK;AACL,6CAHW,OAAO,WAAW,EAAE,iBAAiB,GAAG,OAAO,YAAY,EAAE,kBAAkB,GAC7E,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAmD5C;AAED;;;;;KAKK;AACL,2BAFU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAEO"}
package/dist/nextjs.js CHANGED
@@ -6,7 +6,7 @@ import { createReactConfig } from "./react.js";
6
6
  * {@link createReactConfig} (same React/naming-convention rules, plus
7
7
  * Next.js's own plugin).
8
8
  *
9
- * @param {import("./base.js").BaseConfigOptions} [options]
9
+ * @param {import("./base.js").BaseConfigOptions & import("./react.js").ReactConfigOptions} [options]
10
10
  * @returns {import("eslint").Linter.Config[]}
11
11
  * */
12
12
  export function createNextJsConfig(options) {
@@ -46,6 +46,12 @@ export function createNextJsConfig(options) {
46
46
  "runtime",
47
47
  "preferredRegion",
48
48
  "maxDuration",
49
+ // icon.tsx / apple-icon.tsx / opengraph-image.tsx /
50
+ // twitter-image.tsx: same convention, for the image-generation
51
+ // route handlers.
52
+ "alt",
53
+ "size",
54
+ "contentType",
49
55
  ],
50
56
  },
51
57
  ],
package/dist/react.d.ts CHANGED
@@ -1,14 +1,56 @@
1
+ /**
2
+ * @typedef {object} ReactConfigOptions
3
+ * @property {boolean} [a11y=true] - Enable eslint-plugin-jsx-a11y's
4
+ * recommended rules.
5
+ * @property {boolean} [i18n=false] - Enable eslint-plugin-i18next's
6
+ * `no-literal-string` rule, forbidding any hardcoded string in JSX. Only
7
+ * makes sense for a project fully committed to i18n (e.g. driven by
8
+ * next-intl) — off by default since it flags every literal otherwise.
9
+ * @property {boolean} [testingLibrary=false] - Enable
10
+ * eslint-plugin-testing-library's React rules and eslint-plugin-jest-dom's
11
+ * recommended rules, scoped to test files only. Off by default:
12
+ * `testing-library/no-manual-cleanup` in particular assumes
13
+ * `@testing-library/*`'s automatic `afterEach(cleanup)` is active, which
14
+ * only happens when `afterEach` is a real global (vitest's `test.globals:
15
+ * true`, or Jest) — without that, a manual `cleanup()` call is genuinely
16
+ * required and this rule would be a false positive.
17
+ */
1
18
  /**
2
19
  * A custom ESLint configuration for libraries that use React.
3
20
  *
4
- * @param {import("./base.js").BaseConfigOptions} [options]
21
+ * @param {import("./base.js").BaseConfigOptions & ReactConfigOptions} [options]
5
22
  * @returns {import("eslint").Linter.Config[]}
6
23
  */
7
- export function createReactConfig(options?: import("./base.js").BaseConfigOptions): import("eslint").Linter.Config[];
24
+ export function createReactConfig({ a11y, i18n, testingLibrary, ...options }?: import("./base.js").BaseConfigOptions & ReactConfigOptions): import("eslint").Linter.Config[];
8
25
  /**
9
26
  * A custom ESLint configuration for libraries that use React, with the
10
27
  * default options. Use `createReactConfig(options)` instead to customize it.
11
28
  *
12
29
  * @type {import("eslint").Linter.Config[]} */
13
30
  export const reactConfig: import("eslint").Linter.Config[];
31
+ export type ReactConfigOptions = {
32
+ /**
33
+ * - Enable eslint-plugin-jsx-a11y's
34
+ * recommended rules.
35
+ */
36
+ a11y?: boolean | undefined;
37
+ /**
38
+ * - Enable eslint-plugin-i18next's
39
+ * `no-literal-string` rule, forbidding any hardcoded string in JSX. Only
40
+ * makes sense for a project fully committed to i18n (e.g. driven by
41
+ * next-intl) — off by default since it flags every literal otherwise.
42
+ */
43
+ i18n?: boolean | undefined;
44
+ /**
45
+ * - Enable
46
+ * eslint-plugin-testing-library's React rules and eslint-plugin-jest-dom's
47
+ * recommended rules, scoped to test files only. Off by default:
48
+ * `testing-library/no-manual-cleanup` in particular assumes
49
+ * `@testing-library/*`'s automatic `afterEach(cleanup)` is active, which
50
+ * only happens when `afterEach` is a real global (vitest's `test.globals:
51
+ * true`, or Jest) — without that, a manual `cleanup()` call is genuinely
52
+ * required and this rule would be a false positive.
53
+ */
54
+ testingLibrary?: boolean | undefined;
55
+ };
14
56
  //# sourceMappingURL=react.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.js"],"names":[],"mappings":"AASA;;;;;GAKG;AACH,4CAHW,OAAO,WAAW,EAAE,iBAAiB,GACnC,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAuE5C;AAED;;;;8CAI8C;AAC9C,0BADU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CACK"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.js"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;GAKG;AACH,+EAHW,OAAO,WAAW,EAAE,iBAAiB,GAAG,kBAAkB,GACxD,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CA+F5C;AAED;;;;8CAI8C;AAC9C,0BADU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CACK"}
package/dist/react.js CHANGED
@@ -1,19 +1,66 @@
1
1
  import pluginEslintReact from "@eslint-react/eslint-plugin";
2
2
  import { defineConfig } from "eslint/config";
3
+ import pluginI18next from "eslint-plugin-i18next";
4
+ import pluginJestDom from "eslint-plugin-jest-dom";
5
+ import pluginJsxA11y from "eslint-plugin-jsx-a11y";
3
6
  import pluginReact from "eslint-plugin-react";
4
7
  import pluginReactHooks from "eslint-plugin-react-hooks";
5
8
  import pluginReactRefresh from "eslint-plugin-react-refresh";
9
+ import pluginTestingLibrary from "eslint-plugin-testing-library";
6
10
  import globals from "globals";
7
11
  import { createBaseConfig } from "./base.js";
12
+ /**
13
+ * Any file matching this is a test file, whatever runner or naming
14
+ * convention is used to suffix it (`.test.`, `.spec.`, `.dom.test.`...) —
15
+ * `*` matches across dots, so `*.test.tsx` already covers `foo.dom.test.tsx`.
16
+ * @type {string[]}
17
+ */
18
+ const TEST_FILE_GLOBS = ["**/*.{test,spec}.{ts,tsx,js,jsx}"];
19
+ /**
20
+ * @typedef {object} ReactConfigOptions
21
+ * @property {boolean} [a11y=true] - Enable eslint-plugin-jsx-a11y's
22
+ * recommended rules.
23
+ * @property {boolean} [i18n=false] - Enable eslint-plugin-i18next's
24
+ * `no-literal-string` rule, forbidding any hardcoded string in JSX. Only
25
+ * makes sense for a project fully committed to i18n (e.g. driven by
26
+ * next-intl) — off by default since it flags every literal otherwise.
27
+ * @property {boolean} [testingLibrary=false] - Enable
28
+ * eslint-plugin-testing-library's React rules and eslint-plugin-jest-dom's
29
+ * recommended rules, scoped to test files only. Off by default:
30
+ * `testing-library/no-manual-cleanup` in particular assumes
31
+ * `@testing-library/*`'s automatic `afterEach(cleanup)` is active, which
32
+ * only happens when `afterEach` is a real global (vitest's `test.globals:
33
+ * true`, or Jest) — without that, a manual `cleanup()` call is genuinely
34
+ * required and this rule would be a false positive.
35
+ */
8
36
  /**
9
37
  * A custom ESLint configuration for libraries that use React.
10
38
  *
11
- * @param {import("./base.js").BaseConfigOptions} [options]
39
+ * @param {import("./base.js").BaseConfigOptions & ReactConfigOptions} [options]
12
40
  * @returns {import("eslint").Linter.Config[]}
13
41
  */
14
- export function createReactConfig(options) {
42
+ export function createReactConfig({ a11y = true, i18n = false, testingLibrary = false, ...options } = {}) {
15
43
  return defineConfig([
16
44
  ...createBaseConfig(options),
45
+ a11y ? pluginJsxA11y.flatConfigs.recommended : [],
46
+ i18n
47
+ ? {
48
+ plugins: { i18next: pluginI18next },
49
+ rules: { "i18next/no-literal-string": "error" },
50
+ }
51
+ : [],
52
+ testingLibrary
53
+ ? [
54
+ {
55
+ ...pluginTestingLibrary.configs["flat/react"],
56
+ files: TEST_FILE_GLOBS,
57
+ },
58
+ {
59
+ ...pluginJestDom.configs["flat/recommended"],
60
+ files: TEST_FILE_GLOBS,
61
+ },
62
+ ]
63
+ : [],
17
64
  pluginReact.configs.flat["jsx-runtime"],
18
65
  pluginEslintReact.configs["recommended-type-checked"],
19
66
  {
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * A custom ESLint configuration for libraries that use React and Storybook.
3
3
  *
4
- * @param {import("./base.js").BaseConfigOptions} [options]
4
+ * @param {import("./base.js").BaseConfigOptions & import("./react.js").ReactConfigOptions} [options]
5
5
  * @returns {import("eslint").Linter.Config[]} */
6
- export function createStorybookConfig(options?: import("./base.js").BaseConfigOptions): import("eslint").Linter.Config[];
6
+ export function createStorybookConfig(options?: import("./base.js").BaseConfigOptions & import("./react.js").ReactConfigOptions): import("eslint").Linter.Config[];
7
7
  /**
8
8
  * A custom ESLint configuration for libraries that use React and Storybook,
9
9
  * with the default options. Use `createStorybookConfig(options)` instead to
@@ -1 +1 @@
1
- {"version":3,"file":"storybook.d.ts","sourceRoot":"","sources":["../src/storybook.js"],"names":[],"mappings":"AAKA;;;;iDAIiD;AACjD,gDAFW,OAAO,WAAW,EAAE,iBAAiB,GACnC,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAiB5C;AAED;;;;;8CAK8C;AAC9C,8BADU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CACa"}
1
+ {"version":3,"file":"storybook.d.ts","sourceRoot":"","sources":["../src/storybook.js"],"names":[],"mappings":"AAKA;;;;iDAIiD;AACjD,gDAFW,OAAO,WAAW,EAAE,iBAAiB,GAAG,OAAO,YAAY,EAAE,kBAAkB,GAC7E,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAiB5C;AAED;;;;;8CAK8C;AAC9C,8BADU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CACa"}
package/dist/storybook.js CHANGED
@@ -4,7 +4,7 @@ import { createReactConfig } from "./react.js";
4
4
  /**
5
5
  * A custom ESLint configuration for libraries that use React and Storybook.
6
6
  *
7
- * @param {import("./base.js").BaseConfigOptions} [options]
7
+ * @param {import("./base.js").BaseConfigOptions & import("./react.js").ReactConfigOptions} [options]
8
8
  * @returns {import("eslint").Linter.Config[]} */
9
9
  export function createStorybookConfig(options) {
10
10
  return defineConfig([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forthtilliath/eslint-config",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -26,11 +26,15 @@
26
26
  "@next/eslint-plugin-next": "^16.3.0",
27
27
  "angular-eslint": "^21.4.0",
28
28
  "eslint-config-prettier": "^10.1.8",
29
+ "eslint-plugin-i18next": "^6.1.5",
30
+ "eslint-plugin-jest-dom": "^5.10.1",
31
+ "eslint-plugin-jsx-a11y": "^6.10.2",
29
32
  "eslint-plugin-react": "^7.37.5",
30
33
  "eslint-plugin-react-hooks": "^7.1.1",
31
34
  "eslint-plugin-react-refresh": "^0.5.4",
32
35
  "eslint-plugin-simple-import-sort": "^13.0.0",
33
36
  "eslint-plugin-storybook": "^9.1.20",
37
+ "eslint-plugin-testing-library": "^7.16.2",
34
38
  "eslint-plugin-turbo": "^2.10.9",
35
39
  "globals": "^17.9.0",
36
40
  "typescript-eslint": "^8.67.0"