@icebreakers/eslint-config 2.1.0 → 2.1.2
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 +5 -4
- package/README.zh.md +5 -4
- package/dist/index.cjs +78 -24
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +78 -24
- package/index.d.ts +2 -1
- package/package.json +16 -8
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 related plugins are bundled with this package. Next.js, Query, and other ecosystem presets remain optional and are skipped automatically when their plugins are missing.
|
|
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. The required React lint plugins are bundled with this package.
|
|
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
|
|
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.js、Query 等生态预设仍保持可选,缺失时会自动跳过对应配置,而不是在解析时直接报错。
|
|
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 lint 插件已内置在当前包里。
|
|
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
|
-
-
|
|
202
|
+
- 如果提示缺少插件,通常是某个功能已开启但当前工作区未安装对应可选依赖。React / Next 相关预设会自动跳过;其他能力可通过 `pnpm add -D` 补齐。
|
|
202
203
|
- 与旧版 `.eslintrc` 混用时建议先改用 `icebreakerLegacy()`,逐步迁移至 Flat Config。
|
|
203
204
|
- Tailwind 校验依赖 `tailwind.config.*`,Monorepo 或自定义构建路径时请确认配置文件位置。
|
package/dist/index.cjs
CHANGED
|
@@ -38,6 +38,7 @@ let node_path = require("node:path");
|
|
|
38
38
|
node_path = __toESM(node_path);
|
|
39
39
|
let node_process = require("node:process");
|
|
40
40
|
node_process = __toESM(node_process);
|
|
41
|
+
let node_url = require("node:url");
|
|
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,66 @@ 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
|
+
const packageSegments = name.split("/");
|
|
167
|
+
return searchPaths.some((searchPath) => {
|
|
168
|
+
let currentDir = node_path.default.resolve(searchPath);
|
|
169
|
+
while (true) {
|
|
170
|
+
const packageJsonPath = node_path.default.join(currentDir, "node_modules", ...packageSegments, "package.json");
|
|
171
|
+
if (node_fs.default.existsSync(packageJsonPath)) return true;
|
|
172
|
+
const parentDir = node_path.default.dirname(currentDir);
|
|
173
|
+
if (parentDir === currentDir) return false;
|
|
174
|
+
currentDir = parentDir;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function hasAllPackages(names, searchPaths) {
|
|
180
|
+
return names.every((name) => isPackageAvailable$1(name, searchPaths));
|
|
181
|
+
}
|
|
182
|
+
//#endregion
|
|
154
183
|
//#region src/features.ts
|
|
184
|
+
const BETTER_TAILWIND_PACKAGES = ["eslint-plugin-better-tailwindcss"];
|
|
185
|
+
const TAILWIND_PACKAGES = ["eslint-plugin-tailwindcss"];
|
|
186
|
+
const STYLELINT_BRIDGE_PACKAGES = ["eslint-plugin-better-stylelint"];
|
|
187
|
+
const MDX_PACKAGES = ["eslint-plugin-mdx"];
|
|
188
|
+
const VUE_A11Y_PACKAGES = ["eslint-plugin-vuejs-accessibility"];
|
|
189
|
+
const REACT_A11Y_PACKAGES = ["eslint-plugin-jsx-a11y"];
|
|
190
|
+
const QUERY_PACKAGES = ["@tanstack/eslint-plugin-query"];
|
|
155
191
|
function resolveStylelintConfigLoader() {
|
|
156
192
|
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
193
|
}
|
|
158
194
|
function resolveTailwindPresets(option) {
|
|
159
195
|
if (!option) return [];
|
|
160
|
-
if (typeof option === "object")
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
196
|
+
if (typeof option === "object") {
|
|
197
|
+
if (!hasAllPackages(BETTER_TAILWIND_PACKAGES)) return [];
|
|
198
|
+
return [(0, antfu_exports.interopDefault)(import("eslint-plugin-better-tailwindcss")).then((eslintPluginBetterTailwindcss) => {
|
|
199
|
+
const betterTailwindcssRules = {
|
|
200
|
+
...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
|
|
201
|
+
...eslintPluginBetterTailwindcss.configs["recommended-error"].rules
|
|
202
|
+
};
|
|
203
|
+
return {
|
|
204
|
+
name: "icebreaker/better-tailwindcss",
|
|
205
|
+
plugins: { "better-tailwindcss": eslintPluginBetterTailwindcss },
|
|
206
|
+
rules: betterTailwindcssRules,
|
|
207
|
+
settings: { "better-tailwindcss": {
|
|
208
|
+
entryPoint: option.entryPoint,
|
|
209
|
+
tailwindConfig: option.tailwindConfig
|
|
210
|
+
} }
|
|
211
|
+
};
|
|
212
|
+
})];
|
|
213
|
+
}
|
|
214
|
+
if (!hasAllPackages(TAILWIND_PACKAGES)) return [];
|
|
175
215
|
return [(0, antfu_exports.interopDefault)(import("eslint-plugin-tailwindcss")).then((tailwind) => {
|
|
176
216
|
return tailwind.configs["flat/recommended"];
|
|
177
217
|
}), { rules: { "tailwindcss/no-custom-classname": "off" } }];
|
|
@@ -186,6 +226,7 @@ function resolveStylelintBridgeOptions(option) {
|
|
|
186
226
|
}
|
|
187
227
|
function resolveStylelintBridgePresets(option) {
|
|
188
228
|
if (!option) return [];
|
|
229
|
+
if (!hasAllPackages(STYLELINT_BRIDGE_PACKAGES)) return [];
|
|
189
230
|
const pluginModulePromise = import("eslint-plugin-better-stylelint");
|
|
190
231
|
const stylelintOptions = resolveStylelintBridgeOptions(option);
|
|
191
232
|
return [
|
|
@@ -214,6 +255,7 @@ function resolveStylelintBridgePresets(option) {
|
|
|
214
255
|
}
|
|
215
256
|
function resolveMdxPresets(isEnabled) {
|
|
216
257
|
if (!isEnabled) return [];
|
|
258
|
+
if (!hasAllPackages(MDX_PACKAGES)) return [];
|
|
217
259
|
return [(0, antfu_exports.interopDefault)(import("eslint-plugin-mdx")).then((mdx) => {
|
|
218
260
|
return [{
|
|
219
261
|
...mdx.flat,
|
|
@@ -230,10 +272,10 @@ function resolveMdxPresets(isEnabled) {
|
|
|
230
272
|
function resolveAccessibilityPresets(isEnabled, vueOption, reactOption) {
|
|
231
273
|
if (!isEnabled) return [];
|
|
232
274
|
const presets = [];
|
|
233
|
-
if (vueOption) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-vuejs-accessibility")).then((pluginVueA11y) => {
|
|
275
|
+
if (vueOption && hasAllPackages(VUE_A11Y_PACKAGES)) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-vuejs-accessibility")).then((pluginVueA11y) => {
|
|
234
276
|
return pluginVueA11y.configs["flat/recommended"];
|
|
235
277
|
}));
|
|
236
|
-
if (reactOption) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-jsx-a11y")).then((jsxA11y) => {
|
|
278
|
+
if (reactOption && hasAllPackages(REACT_A11Y_PACKAGES)) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-jsx-a11y")).then((jsxA11y) => {
|
|
237
279
|
return jsxA11y.flatConfigs.recommended;
|
|
238
280
|
}));
|
|
239
281
|
return presets;
|
|
@@ -247,6 +289,7 @@ function resolveNestPresets(isEnabled) {
|
|
|
247
289
|
}
|
|
248
290
|
function resolveQueryPresets(isEnabled) {
|
|
249
291
|
if (!isEnabled) return [];
|
|
292
|
+
if (!hasAllPackages(QUERY_PACKAGES)) return [];
|
|
250
293
|
return [(0, antfu_exports.interopDefault)(import("@tanstack/eslint-plugin-query")).then((pluginQuery) => pluginQuery.configs["flat/recommended"])];
|
|
251
294
|
}
|
|
252
295
|
//#endregion
|
|
@@ -290,11 +333,6 @@ createDefu((object, key, currentValue) => {
|
|
|
290
333
|
}
|
|
291
334
|
});
|
|
292
335
|
//#endregion
|
|
293
|
-
//#region src/utils.ts
|
|
294
|
-
function isObject(o) {
|
|
295
|
-
return Object.prototype.toString.call(o) === "[object Object]";
|
|
296
|
-
}
|
|
297
|
-
//#endregion
|
|
298
336
|
//#region src/options.ts
|
|
299
337
|
const BASE_DEFAULTS = {
|
|
300
338
|
formatters: true,
|
|
@@ -511,11 +549,27 @@ function getPresets(options, mode) {
|
|
|
511
549
|
}
|
|
512
550
|
//#endregion
|
|
513
551
|
//#region src/factory.ts
|
|
552
|
+
const OPTIONAL_ANTFU_FEATURE_PACKAGES = {
|
|
553
|
+
react: [
|
|
554
|
+
"@eslint-react/eslint-plugin",
|
|
555
|
+
"eslint-plugin-react-hooks",
|
|
556
|
+
"eslint-plugin-react-refresh"
|
|
557
|
+
],
|
|
558
|
+
nextjs: ["@next/eslint-plugin-next"]
|
|
559
|
+
};
|
|
560
|
+
function normalizeOptionalAntfuFeatures(options) {
|
|
561
|
+
const normalized = { ...options };
|
|
562
|
+
if (normalized.react && !hasAllPackages([...OPTIONAL_ANTFU_FEATURE_PACKAGES.react])) normalized.react = false;
|
|
563
|
+
if (normalized.nextjs && !hasAllPackages([...OPTIONAL_ANTFU_FEATURE_PACKAGES.nextjs])) normalized.nextjs = false;
|
|
564
|
+
return normalized;
|
|
565
|
+
}
|
|
514
566
|
function icebreaker(options = {}, ...userConfigs) {
|
|
515
|
-
|
|
567
|
+
const [resolved, ...presets] = getPresets(options);
|
|
568
|
+
return (0, antfu_exports.antfu)(normalizeOptionalAntfuFeatures(resolved), ...presets, ...userConfigs);
|
|
516
569
|
}
|
|
517
570
|
function icebreakerLegacy(options = {}, ...userConfigs) {
|
|
518
|
-
|
|
571
|
+
const [resolved, ...presets] = getPresets(options, "legacy");
|
|
572
|
+
return (0, antfu_exports.antfu)(normalizeOptionalAntfuFeatures(resolved), ...presets, ...userConfigs);
|
|
519
573
|
}
|
|
520
574
|
//#endregion
|
|
521
575
|
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
|
@@ -2,6 +2,7 @@ import { createRequire } from "node:module";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import process from "node:process";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
5
6
|
//#region \0rolldown/runtime.js
|
|
6
7
|
var __defProp = Object.defineProperty;
|
|
7
8
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -142,27 +143,66 @@ 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
|
+
const packageSegments = name.split("/");
|
|
158
|
+
return searchPaths.some((searchPath) => {
|
|
159
|
+
let currentDir = path.resolve(searchPath);
|
|
160
|
+
while (true) {
|
|
161
|
+
const packageJsonPath = path.join(currentDir, "node_modules", ...packageSegments, "package.json");
|
|
162
|
+
if (fs.existsSync(packageJsonPath)) return true;
|
|
163
|
+
const parentDir = path.dirname(currentDir);
|
|
164
|
+
if (parentDir === currentDir) return false;
|
|
165
|
+
currentDir = parentDir;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function hasAllPackages(names, searchPaths) {
|
|
171
|
+
return names.every((name) => isPackageAvailable$1(name, searchPaths));
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
145
174
|
//#region src/features.ts
|
|
175
|
+
const BETTER_TAILWIND_PACKAGES = ["eslint-plugin-better-tailwindcss"];
|
|
176
|
+
const TAILWIND_PACKAGES = ["eslint-plugin-tailwindcss"];
|
|
177
|
+
const STYLELINT_BRIDGE_PACKAGES = ["eslint-plugin-better-stylelint"];
|
|
178
|
+
const MDX_PACKAGES = ["eslint-plugin-mdx"];
|
|
179
|
+
const VUE_A11Y_PACKAGES = ["eslint-plugin-vuejs-accessibility"];
|
|
180
|
+
const REACT_A11Y_PACKAGES = ["eslint-plugin-jsx-a11y"];
|
|
181
|
+
const QUERY_PACKAGES = ["@tanstack/eslint-plugin-query"];
|
|
146
182
|
function resolveStylelintConfigLoader() {
|
|
147
183
|
return import.meta.url.endsWith(".ts") ? new URL("./stylelint.ts", import.meta.url).href : new URL("./stylelint.js", import.meta.url).href;
|
|
148
184
|
}
|
|
149
185
|
function resolveTailwindPresets(option) {
|
|
150
186
|
if (!option) return [];
|
|
151
|
-
if (typeof option === "object")
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
187
|
+
if (typeof option === "object") {
|
|
188
|
+
if (!hasAllPackages(BETTER_TAILWIND_PACKAGES)) return [];
|
|
189
|
+
return [(0, antfu_exports.interopDefault)(import("eslint-plugin-better-tailwindcss")).then((eslintPluginBetterTailwindcss) => {
|
|
190
|
+
const betterTailwindcssRules = {
|
|
191
|
+
...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
|
|
192
|
+
...eslintPluginBetterTailwindcss.configs["recommended-error"].rules
|
|
193
|
+
};
|
|
194
|
+
return {
|
|
195
|
+
name: "icebreaker/better-tailwindcss",
|
|
196
|
+
plugins: { "better-tailwindcss": eslintPluginBetterTailwindcss },
|
|
197
|
+
rules: betterTailwindcssRules,
|
|
198
|
+
settings: { "better-tailwindcss": {
|
|
199
|
+
entryPoint: option.entryPoint,
|
|
200
|
+
tailwindConfig: option.tailwindConfig
|
|
201
|
+
} }
|
|
202
|
+
};
|
|
203
|
+
})];
|
|
204
|
+
}
|
|
205
|
+
if (!hasAllPackages(TAILWIND_PACKAGES)) return [];
|
|
166
206
|
return [(0, antfu_exports.interopDefault)(import("eslint-plugin-tailwindcss")).then((tailwind) => {
|
|
167
207
|
return tailwind.configs["flat/recommended"];
|
|
168
208
|
}), { rules: { "tailwindcss/no-custom-classname": "off" } }];
|
|
@@ -177,6 +217,7 @@ function resolveStylelintBridgeOptions(option) {
|
|
|
177
217
|
}
|
|
178
218
|
function resolveStylelintBridgePresets(option) {
|
|
179
219
|
if (!option) return [];
|
|
220
|
+
if (!hasAllPackages(STYLELINT_BRIDGE_PACKAGES)) return [];
|
|
180
221
|
const pluginModulePromise = import("eslint-plugin-better-stylelint");
|
|
181
222
|
const stylelintOptions = resolveStylelintBridgeOptions(option);
|
|
182
223
|
return [
|
|
@@ -205,6 +246,7 @@ function resolveStylelintBridgePresets(option) {
|
|
|
205
246
|
}
|
|
206
247
|
function resolveMdxPresets(isEnabled) {
|
|
207
248
|
if (!isEnabled) return [];
|
|
249
|
+
if (!hasAllPackages(MDX_PACKAGES)) return [];
|
|
208
250
|
return [(0, antfu_exports.interopDefault)(import("eslint-plugin-mdx")).then((mdx) => {
|
|
209
251
|
return [{
|
|
210
252
|
...mdx.flat,
|
|
@@ -221,10 +263,10 @@ function resolveMdxPresets(isEnabled) {
|
|
|
221
263
|
function resolveAccessibilityPresets(isEnabled, vueOption, reactOption) {
|
|
222
264
|
if (!isEnabled) return [];
|
|
223
265
|
const presets = [];
|
|
224
|
-
if (vueOption) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-vuejs-accessibility")).then((pluginVueA11y) => {
|
|
266
|
+
if (vueOption && hasAllPackages(VUE_A11Y_PACKAGES)) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-vuejs-accessibility")).then((pluginVueA11y) => {
|
|
225
267
|
return pluginVueA11y.configs["flat/recommended"];
|
|
226
268
|
}));
|
|
227
|
-
if (reactOption) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-jsx-a11y")).then((jsxA11y) => {
|
|
269
|
+
if (reactOption && hasAllPackages(REACT_A11Y_PACKAGES)) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-jsx-a11y")).then((jsxA11y) => {
|
|
228
270
|
return jsxA11y.flatConfigs.recommended;
|
|
229
271
|
}));
|
|
230
272
|
return presets;
|
|
@@ -238,6 +280,7 @@ function resolveNestPresets(isEnabled) {
|
|
|
238
280
|
}
|
|
239
281
|
function resolveQueryPresets(isEnabled) {
|
|
240
282
|
if (!isEnabled) return [];
|
|
283
|
+
if (!hasAllPackages(QUERY_PACKAGES)) return [];
|
|
241
284
|
return [(0, antfu_exports.interopDefault)(import("@tanstack/eslint-plugin-query")).then((pluginQuery) => pluginQuery.configs["flat/recommended"])];
|
|
242
285
|
}
|
|
243
286
|
//#endregion
|
|
@@ -281,11 +324,6 @@ createDefu((object, key, currentValue) => {
|
|
|
281
324
|
}
|
|
282
325
|
});
|
|
283
326
|
//#endregion
|
|
284
|
-
//#region src/utils.ts
|
|
285
|
-
function isObject(o) {
|
|
286
|
-
return Object.prototype.toString.call(o) === "[object Object]";
|
|
287
|
-
}
|
|
288
|
-
//#endregion
|
|
289
327
|
//#region src/options.ts
|
|
290
328
|
const BASE_DEFAULTS = {
|
|
291
329
|
formatters: true,
|
|
@@ -502,11 +540,27 @@ function getPresets(options, mode) {
|
|
|
502
540
|
}
|
|
503
541
|
//#endregion
|
|
504
542
|
//#region src/factory.ts
|
|
543
|
+
const OPTIONAL_ANTFU_FEATURE_PACKAGES = {
|
|
544
|
+
react: [
|
|
545
|
+
"@eslint-react/eslint-plugin",
|
|
546
|
+
"eslint-plugin-react-hooks",
|
|
547
|
+
"eslint-plugin-react-refresh"
|
|
548
|
+
],
|
|
549
|
+
nextjs: ["@next/eslint-plugin-next"]
|
|
550
|
+
};
|
|
551
|
+
function normalizeOptionalAntfuFeatures(options) {
|
|
552
|
+
const normalized = { ...options };
|
|
553
|
+
if (normalized.react && !hasAllPackages([...OPTIONAL_ANTFU_FEATURE_PACKAGES.react])) normalized.react = false;
|
|
554
|
+
if (normalized.nextjs && !hasAllPackages([...OPTIONAL_ANTFU_FEATURE_PACKAGES.nextjs])) normalized.nextjs = false;
|
|
555
|
+
return normalized;
|
|
556
|
+
}
|
|
505
557
|
function icebreaker(options = {}, ...userConfigs) {
|
|
506
|
-
|
|
558
|
+
const [resolved, ...presets] = getPresets(options);
|
|
559
|
+
return (0, antfu_exports.antfu)(normalizeOptionalAntfuFeatures(resolved), ...presets, ...userConfigs);
|
|
507
560
|
}
|
|
508
561
|
function icebreakerLegacy(options = {}, ...userConfigs) {
|
|
509
|
-
|
|
562
|
+
const [resolved, ...presets] = getPresets(options, "legacy");
|
|
563
|
+
return (0, antfu_exports.antfu)(normalizeOptionalAntfuFeatures(resolved), ...presets, ...userConfigs);
|
|
510
564
|
}
|
|
511
565
|
//#endregion
|
|
512
566
|
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.
|
|
4
|
+
"version": "2.1.2",
|
|
5
5
|
"description": "ESLint preset from Icebreaker's dev-configs",
|
|
6
6
|
"author": "ice breaker <1324318532@qq.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -48,9 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@antfu/eslint-config": "7.7.3",
|
|
51
|
-
"@eslint-react/eslint-plugin": "^
|
|
52
|
-
"@next/eslint-plugin-next": "^16.2.1",
|
|
53
|
-
"@tanstack/eslint-plugin-query": "^5.95.2",
|
|
51
|
+
"@eslint-react/eslint-plugin": "^2.13.0",
|
|
54
52
|
"eslint-plugin-better-tailwindcss": "^4.3.2",
|
|
55
53
|
"eslint-plugin-format": "2.0.1",
|
|
56
54
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
@@ -58,10 +56,12 @@
|
|
|
58
56
|
"eslint-plugin-react-refresh": "^0.5.2",
|
|
59
57
|
"eslint-plugin-tailwindcss": "3.18.2",
|
|
60
58
|
"eslint-plugin-vuejs-accessibility": "^2.5.0",
|
|
61
|
-
"@icebreakers/stylelint-config": "2.2.
|
|
62
|
-
"eslint-plugin-better-stylelint": "0.1.
|
|
59
|
+
"@icebreakers/stylelint-config": "2.2.1",
|
|
60
|
+
"eslint-plugin-better-stylelint": "0.1.2"
|
|
63
61
|
},
|
|
64
62
|
"optionalDependencies": {
|
|
63
|
+
"@next/eslint-plugin-next": "^16.2.1",
|
|
64
|
+
"@tanstack/eslint-plugin-query": "^5.95.2",
|
|
65
65
|
"@unocss/eslint-plugin": "66.6.7",
|
|
66
66
|
"eslint-plugin-mdx": "3.7.0"
|
|
67
67
|
},
|
|
@@ -72,8 +72,16 @@
|
|
|
72
72
|
"tsd": {
|
|
73
73
|
"directory": "test-d",
|
|
74
74
|
"compilerOptions": {
|
|
75
|
-
"module": "
|
|
76
|
-
"
|
|
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
|
},
|