@icebreakers/eslint-config 2.1.0 → 2.1.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.
package/README.md CHANGED
@@ -10,6 +10,7 @@
10
10
 
11
11
  - Node.js 18 or newer
12
12
  - ESLint 9 with flat config support
13
+ - React and Next related plugins are optional. If they are missing, `react`, `nextjs`, `query`, and React-side `a11y` helpers are skipped automatically instead of failing config resolution.
13
14
  - Install optional peer plugins when you turn on Tailwind (`eslint-plugin-tailwindcss` or `eslint-plugin-better-tailwindcss`), MDX (`eslint-plugin-mdx`), or UnoCSS (`@unocss/eslint-plugin`)
14
15
 
15
16
  ## Installation
@@ -63,11 +64,11 @@ export default icebreaker({
63
64
 
64
65
  - `miniProgram` – injects Mini Program globals, ignores common outputs/config files, and enables Vue-side Mini Program compatibility tweaks when `vue` is on.
65
66
  - `vue` – enables Vue + optionally version specific overrides (Vue 2/3) and ionic/miniProgram adjustments.
66
- - `react` – defers to the upstream React preset and unlocks accessibility helpers when `a11y` is enabled.
67
- - `query` – toggles the TanStack Query plugin (`@tanstack/eslint-plugin-query`) and its recommended lint rules.
67
+ - `react` – defers to the upstream React preset and unlocks accessibility helpers when `a11y` is enabled. If the React plugin set is not installed, this flag is ignored automatically.
68
+ - `query` – toggles the TanStack Query plugin (`@tanstack/eslint-plugin-query`) and its recommended lint rules. Missing plugin installs are treated as a no-op.
68
69
  - `tailwindcss` – pass `true` to use the built-in Tailwind flat config or provide `{ entryPoint, tailwindConfig }` for Tailwind v4/v3 projects.
69
70
  - `mdx` – activates MDX linting via `eslint-plugin-mdx`.
70
- - `a11y` – wires in JSX (React) and Vue accessibility plugins.
71
+ - `a11y` – wires in JSX (React) and Vue accessibility plugins. Missing framework-specific plugins are skipped independently.
71
72
  - `typescript` – extends the TypeScript preset and applies stricter unused diagnostics. Pair with `nestjs` for Nest specific adjustments.
72
73
  - `nestjs` – enables NestJS-centric TypeScript tweaks (empty decorated constructors, declaration merging, DI parameter properties, etc.).
73
74
  - `formatters` – keeps the built-in formatting rules enabled by default.
@@ -197,6 +198,6 @@ You may also pass other flat configs (e.g. from in-house presets) as additional
197
198
 
198
199
  ## Troubleshooting
199
200
 
200
- - Missing plugin errors usually mean the optional dependency is not installed in the current workspace. Add it with `pnpm add -D`.
201
+ - Missing plugin errors usually mean a feature is enabled without its optional dependency being installed in the current workspace. React and Next related presets now auto-skip in that case; other features can be added with `pnpm add -D`.
201
202
  - When combining legacy `.eslintrc` projects, prefer `icebreakerLegacy()` and move overrides into flat config format incrementally.
202
203
  - Tailwind class validation reads from your `tailwind.config.*`; double check the path when using monorepo roots or custom build tooling.
package/README.zh.md CHANGED
@@ -8,6 +8,7 @@
8
8
 
9
9
  - Node.js 18 或更高版本
10
10
  - 支持 Flat Config 的 ESLint 9
11
+ - React / Next 相关插件现在是可选项。缺失时会自动跳过 `react`、`nextjs`、`query` 以及 React 侧的 `a11y` 配置,而不是在解析配置时直接报错。
11
12
  - 如需启用 Tailwind、MDX、UnoCSS 等,可安装对应的可选依赖:`eslint-plugin-tailwindcss` / `eslint-plugin-better-tailwindcss`、`eslint-plugin-mdx`、`@unocss/eslint-plugin`
12
13
 
13
14
  ## 安装
@@ -61,11 +62,11 @@ export default icebreaker({
61
62
 
62
63
  - `miniProgram`:启用小程序预设,注入全局变量、忽略常见产物/配置文件,并在 `vue: true` 时补充小程序模板兼容调整。
63
64
  - `vue`:启用 Vue 规则,可根据 Vue 2/3 自动切换,并在 `ionic`、`miniProgram` 选项开启时追加对应覆盖。
64
- - `react`:复用上游 React 预设,配合 `a11y` 注入无障碍插件。
65
- - `query`:按需启用 TanStack Query 插件(`@tanstack/eslint-plugin-query`)及其推荐规则。
65
+ - `react`:复用上游 React 预设,配合 `a11y` 注入无障碍插件;如果 React 插件组未安装,会自动忽略该选项。
66
+ - `query`:按需启用 TanStack Query 插件(`@tanstack/eslint-plugin-query`)及其推荐规则;缺少插件时按 no-op 处理。
66
67
  - `tailwindcss`:传入 `true` 使用内置 Tailwind flat 配置,或通过对象指定 Tailwind v4 的入口文件 / v3 的配置文件路径。
67
68
  - `mdx`:激活 `eslint-plugin-mdx` 处理 `.mdx` 文件。
68
- - `a11y`:按需引入 JSX 与 Vue 的无障碍规则。
69
+ - `a11y`:按需引入 JSX 与 Vue 的无障碍规则,缺少某一侧插件时只跳过对应框架配置。
69
70
  - `typescript`:开启 TypeScript 预设,加强未使用诊断,可与 `nestjs` 搭配使用以获得 Nest 专属优化。
70
71
  - `nestjs`:针对 NestJS 场景做 TypeScript 调整(允许带装饰器的空构造函数、依赖注入参数属性、声明合并等)。
71
72
  - `formatters`:默认启用格式化辅助规则。
@@ -198,6 +199,6 @@ export default icebreaker(
198
199
 
199
200
  ## 常见问题
200
201
 
201
- - 如果提示缺少插件,说明当前工作区未安装对应可选依赖,可通过 `pnpm add -D` 补齐。
202
+ - 如果提示缺少插件,通常是某个功能已开启但当前工作区未安装对应可选依赖。React / Next 相关预设会自动跳过;其他能力可通过 `pnpm add -D` 补齐。
202
203
  - 与旧版 `.eslintrc` 混用时建议先改用 `icebreakerLegacy()`,逐步迁移至 Flat Config。
203
204
  - Tailwind 校验依赖 `tailwind.config.*`,Monorepo 或自定义构建路径时请确认配置文件位置。
package/dist/index.cjs CHANGED
@@ -31,13 +31,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  enumerable: true
32
32
  }) : target, mod));
33
33
  //#endregion
34
- let node_fs = require("node:fs");
35
- node_fs = __toESM(node_fs);
36
34
  let node_module = require("node:module");
37
35
  let node_path = require("node:path");
38
36
  node_path = __toESM(node_path);
39
37
  let node_process = require("node:process");
40
38
  node_process = __toESM(node_process);
39
+ let node_url = require("node:url");
40
+ let node_fs = require("node:fs");
41
+ node_fs = __toESM(node_fs);
41
42
  //#region src/antfu.ts
42
43
  var antfu_exports = /* @__PURE__ */ __exportAll({});
43
44
  __reExport(antfu_exports, require("@antfu/eslint-config"));
@@ -151,27 +152,56 @@ function getDefaultTypescriptOptions(opts) {
151
152
  return { overrides };
152
153
  }
153
154
  //#endregion
155
+ //#region src/utils.ts
156
+ const require$2 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
157
+ const PACKAGE_DIR = node_path.default.dirname((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
158
+ function isObject(o) {
159
+ return Object.prototype.toString.call(o) === "[object Object]";
160
+ }
161
+ function isPackageAvailable$1(name, searchPaths = [node_process.default.cwd(), PACKAGE_DIR]) {
162
+ try {
163
+ require$2.resolve(name, { paths: searchPaths });
164
+ return true;
165
+ } catch {
166
+ return false;
167
+ }
168
+ }
169
+ function hasAllPackages(names, searchPaths) {
170
+ return names.every((name) => isPackageAvailable$1(name, searchPaths));
171
+ }
172
+ //#endregion
154
173
  //#region src/features.ts
174
+ const BETTER_TAILWIND_PACKAGES = ["eslint-plugin-better-tailwindcss"];
175
+ const TAILWIND_PACKAGES = ["eslint-plugin-tailwindcss"];
176
+ const STYLELINT_BRIDGE_PACKAGES = ["eslint-plugin-better-stylelint"];
177
+ const MDX_PACKAGES = ["eslint-plugin-mdx"];
178
+ const VUE_A11Y_PACKAGES = ["eslint-plugin-vuejs-accessibility"];
179
+ const REACT_A11Y_PACKAGES = ["eslint-plugin-jsx-a11y"];
180
+ const QUERY_PACKAGES = ["@tanstack/eslint-plugin-query"];
155
181
  function resolveStylelintConfigLoader() {
156
182
  return require("url").pathToFileURL(__filename).href.endsWith(".ts") ? new URL("./stylelint.ts", require("url").pathToFileURL(__filename).href).href : new URL("./stylelint.js", require("url").pathToFileURL(__filename).href).href;
157
183
  }
158
184
  function resolveTailwindPresets(option) {
159
185
  if (!option) return [];
160
- if (typeof option === "object") return [(0, antfu_exports.interopDefault)(import("eslint-plugin-better-tailwindcss")).then((eslintPluginBetterTailwindcss) => {
161
- const betterTailwindcssRules = {
162
- ...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
163
- ...eslintPluginBetterTailwindcss.configs["recommended-error"].rules
164
- };
165
- return {
166
- name: "icebreaker/better-tailwindcss",
167
- plugins: { "better-tailwindcss": eslintPluginBetterTailwindcss },
168
- rules: betterTailwindcssRules,
169
- settings: { "better-tailwindcss": {
170
- entryPoint: option.entryPoint,
171
- tailwindConfig: option.tailwindConfig
172
- } }
173
- };
174
- })];
186
+ if (typeof option === "object") {
187
+ if (!hasAllPackages(BETTER_TAILWIND_PACKAGES)) return [];
188
+ return [(0, antfu_exports.interopDefault)(import("eslint-plugin-better-tailwindcss")).then((eslintPluginBetterTailwindcss) => {
189
+ const betterTailwindcssRules = {
190
+ ...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
191
+ ...eslintPluginBetterTailwindcss.configs["recommended-error"].rules
192
+ };
193
+ return {
194
+ name: "icebreaker/better-tailwindcss",
195
+ plugins: { "better-tailwindcss": eslintPluginBetterTailwindcss },
196
+ rules: betterTailwindcssRules,
197
+ settings: { "better-tailwindcss": {
198
+ entryPoint: option.entryPoint,
199
+ tailwindConfig: option.tailwindConfig
200
+ } }
201
+ };
202
+ })];
203
+ }
204
+ if (!hasAllPackages(TAILWIND_PACKAGES)) return [];
175
205
  return [(0, antfu_exports.interopDefault)(import("eslint-plugin-tailwindcss")).then((tailwind) => {
176
206
  return tailwind.configs["flat/recommended"];
177
207
  }), { rules: { "tailwindcss/no-custom-classname": "off" } }];
@@ -186,6 +216,7 @@ function resolveStylelintBridgeOptions(option) {
186
216
  }
187
217
  function resolveStylelintBridgePresets(option) {
188
218
  if (!option) return [];
219
+ if (!hasAllPackages(STYLELINT_BRIDGE_PACKAGES)) return [];
189
220
  const pluginModulePromise = import("eslint-plugin-better-stylelint");
190
221
  const stylelintOptions = resolveStylelintBridgeOptions(option);
191
222
  return [
@@ -214,6 +245,7 @@ function resolveStylelintBridgePresets(option) {
214
245
  }
215
246
  function resolveMdxPresets(isEnabled) {
216
247
  if (!isEnabled) return [];
248
+ if (!hasAllPackages(MDX_PACKAGES)) return [];
217
249
  return [(0, antfu_exports.interopDefault)(import("eslint-plugin-mdx")).then((mdx) => {
218
250
  return [{
219
251
  ...mdx.flat,
@@ -230,10 +262,10 @@ function resolveMdxPresets(isEnabled) {
230
262
  function resolveAccessibilityPresets(isEnabled, vueOption, reactOption) {
231
263
  if (!isEnabled) return [];
232
264
  const presets = [];
233
- if (vueOption) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-vuejs-accessibility")).then((pluginVueA11y) => {
265
+ if (vueOption && hasAllPackages(VUE_A11Y_PACKAGES)) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-vuejs-accessibility")).then((pluginVueA11y) => {
234
266
  return pluginVueA11y.configs["flat/recommended"];
235
267
  }));
236
- if (reactOption) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-jsx-a11y")).then((jsxA11y) => {
268
+ if (reactOption && hasAllPackages(REACT_A11Y_PACKAGES)) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-jsx-a11y")).then((jsxA11y) => {
237
269
  return jsxA11y.flatConfigs.recommended;
238
270
  }));
239
271
  return presets;
@@ -247,6 +279,7 @@ function resolveNestPresets(isEnabled) {
247
279
  }
248
280
  function resolveQueryPresets(isEnabled) {
249
281
  if (!isEnabled) return [];
282
+ if (!hasAllPackages(QUERY_PACKAGES)) return [];
250
283
  return [(0, antfu_exports.interopDefault)(import("@tanstack/eslint-plugin-query")).then((pluginQuery) => pluginQuery.configs["flat/recommended"])];
251
284
  }
252
285
  //#endregion
@@ -290,11 +323,6 @@ createDefu((object, key, currentValue) => {
290
323
  }
291
324
  });
292
325
  //#endregion
293
- //#region src/utils.ts
294
- function isObject(o) {
295
- return Object.prototype.toString.call(o) === "[object Object]";
296
- }
297
- //#endregion
298
326
  //#region src/options.ts
299
327
  const BASE_DEFAULTS = {
300
328
  formatters: true,
@@ -511,11 +539,27 @@ function getPresets(options, mode) {
511
539
  }
512
540
  //#endregion
513
541
  //#region src/factory.ts
542
+ const OPTIONAL_ANTFU_FEATURE_PACKAGES = {
543
+ react: [
544
+ "@eslint-react/eslint-plugin",
545
+ "eslint-plugin-react-hooks",
546
+ "eslint-plugin-react-refresh"
547
+ ],
548
+ nextjs: ["@next/eslint-plugin-next"]
549
+ };
550
+ function normalizeOptionalAntfuFeatures(options) {
551
+ const normalized = { ...options };
552
+ if (normalized.react && !hasAllPackages([...OPTIONAL_ANTFU_FEATURE_PACKAGES.react])) normalized.react = false;
553
+ if (normalized.nextjs && !hasAllPackages([...OPTIONAL_ANTFU_FEATURE_PACKAGES.nextjs])) normalized.nextjs = false;
554
+ return normalized;
555
+ }
514
556
  function icebreaker(options = {}, ...userConfigs) {
515
- return (0, antfu_exports.antfu)(...getPresets(options), ...userConfigs);
557
+ const [resolved, ...presets] = getPresets(options);
558
+ return (0, antfu_exports.antfu)(normalizeOptionalAntfuFeatures(resolved), ...presets, ...userConfigs);
516
559
  }
517
560
  function icebreakerLegacy(options = {}, ...userConfigs) {
518
- return (0, antfu_exports.antfu)(...getPresets(options, "legacy"), ...userConfigs);
561
+ const [resolved, ...presets] = getPresets(options, "legacy");
562
+ return (0, antfu_exports.antfu)(normalizeOptionalAntfuFeatures(resolved), ...presets, ...userConfigs);
519
563
  }
520
564
  //#endregion
521
565
  exports.__toESM = __toESM;
package/dist/index.d.cts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Awaitable, ConfigNames, OptionsConfig, TypedFlatConfigItem, TypedFlatConfigItem as TypedFlatConfigItem$1 } from "@antfu/eslint-config";
2
+ import { IcebreakerStylelintOptions } from "@icebreakers/stylelint-config";
2
3
 
3
4
  //#region ../../node_modules/.pnpm/@types+json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts
4
5
  // ==================================================================================================
@@ -2956,7 +2957,7 @@ interface TailwindcssOption {
2956
2957
  tailwindConfig?: string;
2957
2958
  }
2958
2959
  type TailwindcssConfig = boolean | TailwindcssOption;
2959
- interface StylelintBridgeOption {
2960
+ interface StylelintBridgeOption extends IcebreakerStylelintOptions {
2960
2961
  cwd?: string;
2961
2962
  }
2962
2963
  type StylelintBridgeConfig = boolean | StylelintBridgeOption;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Awaitable, ConfigNames, OptionsConfig, TypedFlatConfigItem, TypedFlatConfigItem as TypedFlatConfigItem$1 } from "@antfu/eslint-config";
2
+ import { IcebreakerStylelintOptions } from "@icebreakers/stylelint-config";
2
3
 
3
4
  //#region ../../node_modules/.pnpm/@types+json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts
4
5
  // ==================================================================================================
@@ -2956,7 +2957,7 @@ interface TailwindcssOption {
2956
2957
  tailwindConfig?: string;
2957
2958
  }
2958
2959
  type TailwindcssConfig = boolean | TailwindcssOption;
2959
- interface StylelintBridgeOption {
2960
+ interface StylelintBridgeOption extends IcebreakerStylelintOptions {
2960
2961
  cwd?: string;
2961
2962
  }
2962
2963
  type StylelintBridgeConfig = boolean | StylelintBridgeOption;
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { createRequire } from "node:module";
2
- import fs from "node:fs";
3
2
  import path from "node:path";
4
3
  import process from "node:process";
4
+ import { fileURLToPath } from "node:url";
5
+ import fs from "node:fs";
5
6
  //#region \0rolldown/runtime.js
6
7
  var __defProp = Object.defineProperty;
7
8
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -142,27 +143,56 @@ function getDefaultTypescriptOptions(opts) {
142
143
  return { overrides };
143
144
  }
144
145
  //#endregion
146
+ //#region src/utils.ts
147
+ const require$1 = createRequire(import.meta.url);
148
+ const PACKAGE_DIR = path.dirname(fileURLToPath(import.meta.url));
149
+ function isObject(o) {
150
+ return Object.prototype.toString.call(o) === "[object Object]";
151
+ }
152
+ function isPackageAvailable$1(name, searchPaths = [process.cwd(), PACKAGE_DIR]) {
153
+ try {
154
+ require$1.resolve(name, { paths: searchPaths });
155
+ return true;
156
+ } catch {
157
+ return false;
158
+ }
159
+ }
160
+ function hasAllPackages(names, searchPaths) {
161
+ return names.every((name) => isPackageAvailable$1(name, searchPaths));
162
+ }
163
+ //#endregion
145
164
  //#region src/features.ts
165
+ const BETTER_TAILWIND_PACKAGES = ["eslint-plugin-better-tailwindcss"];
166
+ const TAILWIND_PACKAGES = ["eslint-plugin-tailwindcss"];
167
+ const STYLELINT_BRIDGE_PACKAGES = ["eslint-plugin-better-stylelint"];
168
+ const MDX_PACKAGES = ["eslint-plugin-mdx"];
169
+ const VUE_A11Y_PACKAGES = ["eslint-plugin-vuejs-accessibility"];
170
+ const REACT_A11Y_PACKAGES = ["eslint-plugin-jsx-a11y"];
171
+ const QUERY_PACKAGES = ["@tanstack/eslint-plugin-query"];
146
172
  function resolveStylelintConfigLoader() {
147
173
  return import.meta.url.endsWith(".ts") ? new URL("./stylelint.ts", import.meta.url).href : new URL("./stylelint.js", import.meta.url).href;
148
174
  }
149
175
  function resolveTailwindPresets(option) {
150
176
  if (!option) return [];
151
- if (typeof option === "object") return [(0, antfu_exports.interopDefault)(import("eslint-plugin-better-tailwindcss")).then((eslintPluginBetterTailwindcss) => {
152
- const betterTailwindcssRules = {
153
- ...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
154
- ...eslintPluginBetterTailwindcss.configs["recommended-error"].rules
155
- };
156
- return {
157
- name: "icebreaker/better-tailwindcss",
158
- plugins: { "better-tailwindcss": eslintPluginBetterTailwindcss },
159
- rules: betterTailwindcssRules,
160
- settings: { "better-tailwindcss": {
161
- entryPoint: option.entryPoint,
162
- tailwindConfig: option.tailwindConfig
163
- } }
164
- };
165
- })];
177
+ if (typeof option === "object") {
178
+ if (!hasAllPackages(BETTER_TAILWIND_PACKAGES)) return [];
179
+ return [(0, antfu_exports.interopDefault)(import("eslint-plugin-better-tailwindcss")).then((eslintPluginBetterTailwindcss) => {
180
+ const betterTailwindcssRules = {
181
+ ...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
182
+ ...eslintPluginBetterTailwindcss.configs["recommended-error"].rules
183
+ };
184
+ return {
185
+ name: "icebreaker/better-tailwindcss",
186
+ plugins: { "better-tailwindcss": eslintPluginBetterTailwindcss },
187
+ rules: betterTailwindcssRules,
188
+ settings: { "better-tailwindcss": {
189
+ entryPoint: option.entryPoint,
190
+ tailwindConfig: option.tailwindConfig
191
+ } }
192
+ };
193
+ })];
194
+ }
195
+ if (!hasAllPackages(TAILWIND_PACKAGES)) return [];
166
196
  return [(0, antfu_exports.interopDefault)(import("eslint-plugin-tailwindcss")).then((tailwind) => {
167
197
  return tailwind.configs["flat/recommended"];
168
198
  }), { rules: { "tailwindcss/no-custom-classname": "off" } }];
@@ -177,6 +207,7 @@ function resolveStylelintBridgeOptions(option) {
177
207
  }
178
208
  function resolveStylelintBridgePresets(option) {
179
209
  if (!option) return [];
210
+ if (!hasAllPackages(STYLELINT_BRIDGE_PACKAGES)) return [];
180
211
  const pluginModulePromise = import("eslint-plugin-better-stylelint");
181
212
  const stylelintOptions = resolveStylelintBridgeOptions(option);
182
213
  return [
@@ -205,6 +236,7 @@ function resolveStylelintBridgePresets(option) {
205
236
  }
206
237
  function resolveMdxPresets(isEnabled) {
207
238
  if (!isEnabled) return [];
239
+ if (!hasAllPackages(MDX_PACKAGES)) return [];
208
240
  return [(0, antfu_exports.interopDefault)(import("eslint-plugin-mdx")).then((mdx) => {
209
241
  return [{
210
242
  ...mdx.flat,
@@ -221,10 +253,10 @@ function resolveMdxPresets(isEnabled) {
221
253
  function resolveAccessibilityPresets(isEnabled, vueOption, reactOption) {
222
254
  if (!isEnabled) return [];
223
255
  const presets = [];
224
- if (vueOption) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-vuejs-accessibility")).then((pluginVueA11y) => {
256
+ if (vueOption && hasAllPackages(VUE_A11Y_PACKAGES)) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-vuejs-accessibility")).then((pluginVueA11y) => {
225
257
  return pluginVueA11y.configs["flat/recommended"];
226
258
  }));
227
- if (reactOption) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-jsx-a11y")).then((jsxA11y) => {
259
+ if (reactOption && hasAllPackages(REACT_A11Y_PACKAGES)) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-jsx-a11y")).then((jsxA11y) => {
228
260
  return jsxA11y.flatConfigs.recommended;
229
261
  }));
230
262
  return presets;
@@ -238,6 +270,7 @@ function resolveNestPresets(isEnabled) {
238
270
  }
239
271
  function resolveQueryPresets(isEnabled) {
240
272
  if (!isEnabled) return [];
273
+ if (!hasAllPackages(QUERY_PACKAGES)) return [];
241
274
  return [(0, antfu_exports.interopDefault)(import("@tanstack/eslint-plugin-query")).then((pluginQuery) => pluginQuery.configs["flat/recommended"])];
242
275
  }
243
276
  //#endregion
@@ -281,11 +314,6 @@ createDefu((object, key, currentValue) => {
281
314
  }
282
315
  });
283
316
  //#endregion
284
- //#region src/utils.ts
285
- function isObject(o) {
286
- return Object.prototype.toString.call(o) === "[object Object]";
287
- }
288
- //#endregion
289
317
  //#region src/options.ts
290
318
  const BASE_DEFAULTS = {
291
319
  formatters: true,
@@ -502,11 +530,27 @@ function getPresets(options, mode) {
502
530
  }
503
531
  //#endregion
504
532
  //#region src/factory.ts
533
+ const OPTIONAL_ANTFU_FEATURE_PACKAGES = {
534
+ react: [
535
+ "@eslint-react/eslint-plugin",
536
+ "eslint-plugin-react-hooks",
537
+ "eslint-plugin-react-refresh"
538
+ ],
539
+ nextjs: ["@next/eslint-plugin-next"]
540
+ };
541
+ function normalizeOptionalAntfuFeatures(options) {
542
+ const normalized = { ...options };
543
+ if (normalized.react && !hasAllPackages([...OPTIONAL_ANTFU_FEATURE_PACKAGES.react])) normalized.react = false;
544
+ if (normalized.nextjs && !hasAllPackages([...OPTIONAL_ANTFU_FEATURE_PACKAGES.nextjs])) normalized.nextjs = false;
545
+ return normalized;
546
+ }
505
547
  function icebreaker(options = {}, ...userConfigs) {
506
- return (0, antfu_exports.antfu)(...getPresets(options), ...userConfigs);
548
+ const [resolved, ...presets] = getPresets(options);
549
+ return (0, antfu_exports.antfu)(normalizeOptionalAntfuFeatures(resolved), ...presets, ...userConfigs);
507
550
  }
508
551
  function icebreakerLegacy(options = {}, ...userConfigs) {
509
- return (0, antfu_exports.antfu)(...getPresets(options, "legacy"), ...userConfigs);
552
+ const [resolved, ...presets] = getPresets(options, "legacy");
553
+ return (0, antfu_exports.antfu)(normalizeOptionalAntfuFeatures(resolved), ...presets, ...userConfigs);
510
554
  }
511
555
  //#endregion
512
556
  export { getPresets, icebreaker, icebreakerLegacy };
package/index.d.ts CHANGED
@@ -4,6 +4,7 @@ import type {
4
4
  OptionsConfig,
5
5
  TypedFlatConfigItem,
6
6
  } from '@antfu/eslint-config'
7
+ import type { IcebreakerStylelintOptions } from '@icebreakers/stylelint-config'
7
8
  import type { Linter } from 'eslint'
8
9
  import type { FlatConfigComposer } from 'eslint-flat-config-utils'
9
10
 
@@ -13,7 +14,7 @@ export interface TailwindcssOption {
13
14
  }
14
15
 
15
16
  export type TailwindcssConfig = boolean | TailwindcssOption
16
- export interface StylelintBridgeOption {
17
+ export interface StylelintBridgeOption extends IcebreakerStylelintOptions {
17
18
  cwd?: string
18
19
  }
19
20
  export type StylelintBridgeConfig = boolean | StylelintBridgeOption
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@icebreakers/eslint-config",
3
3
  "type": "module",
4
- "version": "2.1.0",
4
+ "version": "2.1.1",
5
5
  "description": "ESLint preset from Icebreaker's dev-configs",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",
@@ -48,22 +48,22 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "@antfu/eslint-config": "7.7.3",
51
- "@eslint-react/eslint-plugin": "^3.0.0",
52
- "@next/eslint-plugin-next": "^16.2.1",
53
- "@tanstack/eslint-plugin-query": "^5.95.2",
54
51
  "eslint-plugin-better-tailwindcss": "^4.3.2",
55
52
  "eslint-plugin-format": "2.0.1",
56
- "eslint-plugin-jsx-a11y": "^6.10.2",
57
- "eslint-plugin-react-hooks": "^7.0.1",
58
- "eslint-plugin-react-refresh": "^0.5.2",
59
53
  "eslint-plugin-tailwindcss": "3.18.2",
60
54
  "eslint-plugin-vuejs-accessibility": "^2.5.0",
61
- "@icebreakers/stylelint-config": "2.2.0",
55
+ "@icebreakers/stylelint-config": "2.2.1",
62
56
  "eslint-plugin-better-stylelint": "0.1.1"
63
57
  },
64
58
  "optionalDependencies": {
59
+ "@eslint-react/eslint-plugin": "^3.0.0",
60
+ "@next/eslint-plugin-next": "^16.2.1",
61
+ "@tanstack/eslint-plugin-query": "^5.95.2",
65
62
  "@unocss/eslint-plugin": "66.6.7",
66
- "eslint-plugin-mdx": "3.7.0"
63
+ "eslint-plugin-jsx-a11y": "^6.10.2",
64
+ "eslint-plugin-mdx": "3.7.0",
65
+ "eslint-plugin-react-hooks": "^7.0.1",
66
+ "eslint-plugin-react-refresh": "^0.5.2"
67
67
  },
68
68
  "publishConfig": {
69
69
  "access": "public",
@@ -72,8 +72,16 @@
72
72
  "tsd": {
73
73
  "directory": "test-d",
74
74
  "compilerOptions": {
75
- "module": "esnext",
76
- "moduleResolution": "bundler",
75
+ "module": "nodenext",
76
+ "baseUrl": ".",
77
+ "paths": {
78
+ "@icebreakers/stylelint-config": [
79
+ "../stylelint/dist/index.d.ts"
80
+ ],
81
+ "eslint-plugin-better-stylelint": [
82
+ "../eslint-plugin-better-stylelint/dist/index.d.ts"
83
+ ]
84
+ },
77
85
  "skipLibCheck": true
78
86
  }
79
87
  },