@ncontiero/eslint-config 8.3.3 → 8.4.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/dist/index.mjs CHANGED
@@ -75,7 +75,7 @@ async function interopDefault(m) {
75
75
  return resolved.default || resolved;
76
76
  }
77
77
  function ensurePackages(packages) {
78
- if (process.env.CI || !process.stdout.isTTY || !isCwdInScope) return;
78
+ if (!isCwdInScope || process.env.CI || !process.stdout.isTTY) return;
79
79
  const nonExistingPackages = packages.filter((i) => i && !isPackageExists(i));
80
80
  if (nonExistingPackages.length === 0) return;
81
81
  throw new Error(`This package(s) are required for this config: ${nonExistingPackages.join(", ")}. Please install them.`);
@@ -164,6 +164,7 @@ async function e18e(options = {}) {
164
164
  //#endregion
165
165
  //#region src/globs.ts
166
166
  const GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
167
+ const GLOB_EXT_TS_TSX = "?([cm])ts?(x)";
167
168
  const GLOB_SRC = "**/*.?([cm])[jt]s?(x)";
168
169
  const GLOB_JS = "**/*.?([cm])js";
169
170
  const GLOB_JSX = "**/*.?([cm])jsx";
@@ -183,6 +184,20 @@ const GLOB_YAML = "**/*.y?(a)ml";
183
184
  const GLOB_TOML = "**/*.toml";
184
185
  const GLOB_HTML = "**/*.htm?(l)";
185
186
  const GLOB_MARKDOWN_CODE = `${GLOB_MARKDOWN}/${GLOB_SRC}`;
187
+ const GLOB_TESTS = [
188
+ `**/__tests__/**/*.${GLOB_SRC_EXT}`,
189
+ `**/*.spec.${GLOB_SRC_EXT}`,
190
+ `**/*.test.${GLOB_SRC_EXT}`,
191
+ `**/*.bench.${GLOB_SRC_EXT}`,
192
+ `**/*.benchmark.${GLOB_SRC_EXT}`
193
+ ];
194
+ const GLOB_TS_TESTS = [
195
+ `**/__tests__/**/*.${GLOB_EXT_TS_TSX}`,
196
+ `**/*.spec.${GLOB_EXT_TS_TSX}`,
197
+ `**/*.test.${GLOB_EXT_TS_TSX}`,
198
+ `**/*.bench.${GLOB_EXT_TS_TSX}`,
199
+ `**/*.benchmark.${GLOB_EXT_TS_TSX}`
200
+ ];
186
201
  const GLOB_ALL_SRC = [
187
202
  GLOB_SRC,
188
203
  GLOB_STYLE,
@@ -558,6 +573,7 @@ async function jsonc(options = {}) {
558
573
  GLOB_JSONC
559
574
  ], overrides = {}, style = true } = options;
560
575
  const { indent = 2 } = typeof style === "boolean" ? {} : style;
576
+ const quotes = options.quotes ?? "double";
561
577
  const [pluginJsonc] = await Promise.all([interopDefault(import("eslint-plugin-jsonc"))]);
562
578
  return [...pluginJsonc.configs["recommended-with-jsonc"].map((config) => ({
563
579
  ...config,
@@ -579,8 +595,8 @@ async function jsonc(options = {}) {
579
595
  }],
580
596
  "jsonc/object-curly-spacing": ["error", "always"],
581
597
  "jsonc/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
582
- "jsonc/quote-props": "off",
583
- "jsonc/quotes": "off",
598
+ "jsonc/quote-props": "error",
599
+ "jsonc/quotes": ["error", quotes],
584
600
  ...overrides
585
601
  }
586
602
  }];
@@ -929,7 +945,7 @@ const TanstackRouterPackages = ["@tanstack/react-router"];
929
945
  const NextJsPackages = ["next"];
930
946
  async function react(options = {}) {
931
947
  const { files = [GLOB_SRC], filesTypeAware = [GLOB_TS, GLOB_TSX], ignoresTypeAware = [`${GLOB_MARKDOWN}/**`], overrides = {}, tsconfigPath } = options;
932
- const isTypeAware = !!tsconfigPath;
948
+ const isTypeAware = !!tsconfigPath || !!options.typeAware;
933
949
  const typeAwareRules = {
934
950
  "react/no-leaked-conditional-rendering": "error",
935
951
  "react/no-unused-props": "warn"
@@ -1348,6 +1364,61 @@ async function tanstackQuery(options = {}) {
1348
1364
  }];
1349
1365
  }
1350
1366
  //#endregion
1367
+ //#region src/configs/test.ts
1368
+ let _pluginTest;
1369
+ async function test(options = {}) {
1370
+ const { files = GLOB_TESTS, overrides = {}, tsconfigPath, typescript = false } = options;
1371
+ const filesTypeAware = [GLOB_TS_TESTS];
1372
+ const isTypeAware = typescript && (!!tsconfigPath || !!options.typeAware);
1373
+ const [pluginVitest, pluginNoOnlyTests] = await Promise.all([interopDefault(import("@vitest/eslint-plugin")), interopDefault(import("eslint-plugin-no-only-tests"))]);
1374
+ _pluginTest = _pluginTest || {
1375
+ ...pluginVitest,
1376
+ rules: {
1377
+ ...pluginVitest.rules,
1378
+ ...pluginNoOnlyTests.rules
1379
+ }
1380
+ };
1381
+ const typeAwareRules = {
1382
+ "test/unbound-method": "error",
1383
+ "ts/unbound-method": "off"
1384
+ };
1385
+ return [
1386
+ {
1387
+ name: "ncontiero/test/setup",
1388
+ plugins: { test: _pluginTest }
1389
+ },
1390
+ {
1391
+ files,
1392
+ name: "ncontiero/test/rules",
1393
+ rules: {
1394
+ "test/consistent-test-it": ["error", {
1395
+ fn: "it",
1396
+ withinDescribe: "it"
1397
+ }],
1398
+ "test/hoisted-apis-on-top": "warn",
1399
+ "test/no-duplicate-hooks": "warn",
1400
+ "test/no-identical-title": "error",
1401
+ "test/no-import-node-test": "error",
1402
+ "test/no-only-tests": "error",
1403
+ "test/prefer-hooks-in-order": "error",
1404
+ "test/prefer-lowercase-title": ["error", { ignore: ["describe"] }],
1405
+ "antfu/no-top-level-await": "off",
1406
+ "e18e/prefer-static-regex": "off",
1407
+ "no-unused-expressions": "off",
1408
+ "node/prefer-global/process": "off",
1409
+ "ts/explicit-function-return-type": "off",
1410
+ ...overrides
1411
+ }
1412
+ },
1413
+ ...isTypeAware ? [{
1414
+ files: filesTypeAware,
1415
+ name: "ncontiero/test/rules-type-aware",
1416
+ rules: typeAwareRules,
1417
+ settings: { vitest: { typecheck: true } }
1418
+ }] : []
1419
+ ];
1420
+ }
1421
+ //#endregion
1351
1422
  //#region src/configs/toml.ts
1352
1423
  async function toml(options = {}) {
1353
1424
  const { files = [GLOB_TOML], overrides = {}, style = true } = options;
@@ -1393,7 +1464,7 @@ async function typescript(options = {}) {
1393
1464
  const filesTypeAware = options.filesTypeAware ?? ["**/*.?([cm])ts", "**/*.?([cm])tsx"];
1394
1465
  const ignoresTypeAware = options.ignoresTypeAware ?? [`**/*.md/**`];
1395
1466
  const tsconfigPath = options?.tsconfigPath ? options.tsconfigPath : void 0;
1396
- const isTypeAware = !!tsconfigPath;
1467
+ const isTypeAware = !!tsconfigPath || !!options.typeAware;
1397
1468
  const typeAwareRules = {
1398
1469
  "dot-notation": "off",
1399
1470
  "no-implied-eval": "off",
@@ -1439,7 +1510,7 @@ async function typescript(options = {}) {
1439
1510
  ...typeAware ? {
1440
1511
  projectService: {
1441
1512
  allowDefaultProject: ["./*.js"],
1442
- defaultProject: tsconfigPath
1513
+ ...tsconfigPath ? { defaultProject: tsconfigPath } : {}
1443
1514
  },
1444
1515
  tsconfigRootDir: process.cwd()
1445
1516
  } : {},
@@ -1723,7 +1794,8 @@ const flatConfigProps = [
1723
1794
  ];
1724
1795
  const defaultPluginRenaming = {
1725
1796
  "@eslint-react": "react",
1726
- "@typescript-eslint": "ts"
1797
+ "@typescript-eslint": "ts",
1798
+ vitest: "test"
1727
1799
  };
1728
1800
  function resolveSubOptions(options, key) {
1729
1801
  return typeof options[key] === "boolean" ? {} : options[key] || {};
@@ -1785,19 +1857,26 @@ function ncontiero(options = {}, ...userConfigs) {
1785
1857
  }));
1786
1858
  if (enableTanStackQuery) configs.push(tanstackQuery({ overrides: getOverrides(options, "tanstackQuery") }));
1787
1859
  if (enableJsonc) configs.push(jsonc({
1860
+ ...resolveSubOptions(options, "jsonc"),
1788
1861
  overrides: getOverrides(options, "jsonc"),
1789
1862
  style: styleOptions
1790
1863
  }), sortPackageJson(), sortTsconfig());
1791
- if (options.yaml ?? true) configs.push(yml({
1864
+ if (options.yaml !== false) configs.push(yml({
1792
1865
  overrides: getOverrides(options, "yaml"),
1793
1866
  style: styleOptions
1794
1867
  }));
1795
- if (options.toml ?? true) configs.push(toml({
1868
+ if (options.toml !== false) configs.push(toml({
1796
1869
  overrides: getOverrides(options, "toml"),
1797
1870
  style: styleOptions
1798
1871
  }));
1799
1872
  if (enableMarkdown) configs.push(markdown({ overrides: getOverrides(options, "markdown") }));
1800
1873
  if (enableRegexp) configs.push(regexp(typeof enableRegexp === "boolean" ? {} : enableRegexp));
1874
+ if (options.test !== false) configs.push(test({
1875
+ ...typescriptOptions,
1876
+ overrides: getOverrides(options, "test"),
1877
+ tsconfigPath,
1878
+ typescript: !!enableTypescript
1879
+ }));
1801
1880
  if (enableReact) configs.push(react({
1802
1881
  ...typescriptOptions,
1803
1882
  overrides: getOverrides(options, "react"),
@@ -1826,4 +1905,4 @@ function ncontiero(options = {}, ...userConfigs) {
1826
1905
  });
1827
1906
  }
1828
1907
  //#endregion
1829
- export { GLOB_ALL_SRC, GLOB_CSS, GLOB_DIST, GLOB_EXCLUDE, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_LOCKFILE, GLOB_MARKDOWN, GLOB_MARKDOWN_CODE, GLOB_MARKDOWN_IN_MARKDOWN, GLOB_NODE_MODULES, GLOB_POSTCSS, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_STYLE, GLOB_TOML, GLOB_TS, GLOB_TSX, GLOB_YAML, combine, command, comments, composer, deMorgan, defaultPluginRenaming, e18e, ensurePackages, getOverrides, hasNextJs, hasReact, hasTailwind, hasTypeScript, html, ignores, imports, interopDefault, javascript, jsdoc, jsonc, jsx, markdown, ncontiero, nextJs, node, parserPlain, perfectionist, prettier, promise, react, regexp, renamePluginInConfigs, renameRules, resolveSubOptions, restrictedSyntaxJs, sortPackageJson, sortPnpmWorkspace, sortTsconfig, tailwindcss, tanstackQuery, toArray, toml, typescript, unicorn, yml };
1908
+ export { GLOB_ALL_SRC, GLOB_CSS, GLOB_DIST, GLOB_EXCLUDE, GLOB_EXT_TS_TSX, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_LOCKFILE, GLOB_MARKDOWN, GLOB_MARKDOWN_CODE, GLOB_MARKDOWN_IN_MARKDOWN, GLOB_NODE_MODULES, GLOB_POSTCSS, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_STYLE, GLOB_TESTS, GLOB_TOML, GLOB_TS, GLOB_TSX, GLOB_TS_TESTS, GLOB_YAML, combine, command, comments, composer, deMorgan, defaultPluginRenaming, e18e, ensurePackages, getOverrides, hasNextJs, hasReact, hasTailwind, hasTypeScript, html, ignores, imports, interopDefault, javascript, jsdoc, jsonc, jsx, markdown, ncontiero, nextJs, node, parserPlain, perfectionist, prettier, promise, react, regexp, renamePluginInConfigs, renameRules, resolveSubOptions, restrictedSyntaxJs, sortPackageJson, sortPnpmWorkspace, sortTsconfig, tailwindcss, tanstackQuery, test, toArray, toml, typescript, unicorn, yml };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ncontiero/eslint-config",
3
3
  "type": "module",
4
- "version": "8.3.3",
4
+ "version": "8.4.0",
5
5
  "description": "Nicolas's ESLint config.",
6
6
  "author": {
7
7
  "name": "Nicolas Contiero",
@@ -39,59 +39,61 @@
39
39
  "dependencies": {
40
40
  "@e18e/eslint-plugin": "^0.5.1",
41
41
  "@eslint-community/eslint-plugin-eslint-comments": "^4.7.2",
42
- "@eslint-react/eslint-plugin": "^5.9.2",
43
- "@eslint/markdown": "^8.0.2",
44
- "@html-eslint/eslint-plugin": "^0.62.0",
45
- "@html-eslint/parser": "^0.62.0",
46
- "@next/eslint-plugin-next": "^16.2.9",
47
- "@typescript-eslint/eslint-plugin": "^8.62.0",
48
- "@typescript-eslint/parser": "^8.62.0",
42
+ "@eslint-react/eslint-plugin": "^5.14.10",
43
+ "@eslint/markdown": "^8.0.3",
44
+ "@html-eslint/eslint-plugin": "^0.64.0",
45
+ "@html-eslint/parser": "^0.64.0",
46
+ "@next/eslint-plugin-next": "^16.2.10",
47
+ "@typescript-eslint/eslint-plugin": "^8.64.0",
48
+ "@typescript-eslint/parser": "^8.64.0",
49
+ "@vitest/eslint-plugin": "^1.6.23",
49
50
  "eslint-config-flat-gitignore": "^2.3.0",
50
51
  "eslint-merge-processors": "^2.0.0",
51
52
  "eslint-plugin-antfu": "^3.2.3",
52
- "eslint-plugin-better-tailwindcss": "4.6.0",
53
- "eslint-plugin-command": "^3.5.2",
54
- "eslint-plugin-de-morgan": "^2.1.2",
55
- "eslint-plugin-import-x": "^4.17.0",
56
- "eslint-plugin-jsdoc": "^63.0.8",
57
- "eslint-plugin-jsonc": "^3.2.0",
53
+ "eslint-plugin-better-tailwindcss": "4.6.1",
54
+ "eslint-plugin-command": "^3.5.3",
55
+ "eslint-plugin-de-morgan": "^2.1.3",
56
+ "eslint-plugin-import-x": "^4.17.1",
57
+ "eslint-plugin-jsdoc": "^63.0.13",
58
+ "eslint-plugin-jsonc": "^3.3.0",
58
59
  "eslint-plugin-jsx-a11y": "^6.10.2",
59
- "eslint-plugin-n": "^18.1.0",
60
- "eslint-plugin-perfectionist": "^5.9.1",
60
+ "eslint-plugin-n": "^18.2.2",
61
+ "eslint-plugin-no-only-tests": "^3.4.0",
62
+ "eslint-plugin-perfectionist": "^5.10.0",
61
63
  "eslint-plugin-prettier": "^5.5.6",
62
64
  "eslint-plugin-promise": "^7.3.0",
63
65
  "eslint-plugin-react-refresh": "^0.5.3",
64
- "eslint-plugin-regexp": "^3.1.0",
66
+ "eslint-plugin-regexp": "^3.1.1",
65
67
  "eslint-plugin-toml": "^1.4.0",
66
- "eslint-plugin-unicorn": "^69.0.0",
68
+ "eslint-plugin-unicorn": "^72.0.0",
67
69
  "eslint-plugin-unused-imports": "^4.4.1",
68
- "eslint-plugin-yml": "^3.5.0",
70
+ "eslint-plugin-yml": "^3.6.0",
69
71
  "globals": "^17.7.0",
70
72
  "local-pkg": "^1.2.1",
71
- "prettier": "^3.8.4",
73
+ "prettier": "^3.9.5",
72
74
  "toml-eslint-parser": "^1.0.3",
73
- "yaml-eslint-parser": "^2.0.0"
75
+ "yaml-eslint-parser": "^2.1.0"
74
76
  },
75
77
  "devDependencies": {
76
- "@changesets/cli": "^2.31.0",
77
- "@commitlint/cli": "^21.1.0",
78
- "@commitlint/config-conventional": "^21.1.0",
79
- "@eslint/config-inspector": "^3.0.4",
80
- "@ncontiero/changelog-github": "^2.1.4",
81
- "@ncontiero/prettier-config": "^1.0.0",
82
- "@tanstack/eslint-plugin-query": "^5.101.1",
83
- "@types/eslint-plugin-jsx-a11y": "^6.10.1",
84
- "@types/node": "^25.9.4",
85
- "eslint": "^10.5.0",
86
- "eslint-typegen": "^2.3.1",
87
- "husky": "^9.1.7",
88
- "nano-staged": "^1.0.2",
89
- "tinyexec": "^1.2.4",
90
- "tinyglobby": "^0.2.17",
91
- "tsdown": "^0.22.3",
92
- "tsx": "^4.22.4",
93
- "typescript": "^6.0.3",
94
- "vitest": "^4.1.9"
78
+ "@changesets/cli": "2.31.0",
79
+ "@commitlint/cli": "21.2.1",
80
+ "@commitlint/config-conventional": "21.2.0",
81
+ "@eslint/config-inspector": "3.1.0",
82
+ "@ncontiero/changelog-github": "2.1.4",
83
+ "@ncontiero/prettier-config": "1.0.0",
84
+ "@tanstack/eslint-plugin-query": "5.101.2",
85
+ "@types/eslint-plugin-jsx-a11y": "6.10.1",
86
+ "@types/node": "26.1.1",
87
+ "eslint": "10.7.0",
88
+ "eslint-typegen": "2.3.1",
89
+ "husky": "9.1.7",
90
+ "nano-staged": "1.0.2",
91
+ "tinyexec": "1.2.4",
92
+ "tinyglobby": "0.2.17",
93
+ "tsdown": "0.22.7",
94
+ "tsx": "4.23.1",
95
+ "typescript": "6.0.3",
96
+ "vitest": "4.1.10"
95
97
  },
96
98
  "engines": {
97
99
  "node": ">=20.19.0"
@@ -111,6 +113,7 @@
111
113
  "lint:fix": "pnpm lint --fix",
112
114
  "typecheck": "tsc --noEmit",
113
115
  "check": "pnpm lint && pnpm typecheck",
114
- "release": "changeset publish"
116
+ "release": "pnpm build && changeset publish",
117
+ "postinstall": "pnpm typegen"
115
118
  }
116
119
  }