@icebreakers/eslint-config 6.0.0 → 7.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.
package/README.md CHANGED
@@ -50,8 +50,10 @@ export default icebreaker({
50
50
  query: true,
51
51
  typescript: true,
52
52
  test: true,
53
- tailwindcss: {
54
- tailwindConfig: './tailwind.config.ts',
53
+ tailwindcss: true,
54
+ betterTailwindcss: {
55
+ entryPoint: './src/tailwind.css',
56
+ rules: 'recommended',
55
57
  },
56
58
  unocss: {
57
59
  strict: true,
@@ -69,7 +71,8 @@ export default icebreaker({
69
71
  - `vue` – enables Vue + optionally version specific overrides (Vue 2/3) and ionic/miniProgram adjustments.
70
72
  - `react` – defers to the upstream React preset. The required React core lint plugins are bundled with this package; React accessibility still requires `eslint-plugin-jsx-a11y` when `a11y` is enabled.
71
73
  - `query` – toggles the TanStack Query plugin (`@tanstack/eslint-plugin-query`) and its recommended lint rules. Missing plugin installs are treated as a no-op.
72
- - `tailwindcss` – pass `true` to use the built-in Tailwind flat config or provide `{ entryPoint, tailwindConfig }` for Tailwind v4/v3 projects.
74
+ - `tailwindcss` – pass `true` to enable `eslint-plugin-tailwindcss`.
75
+ - `betterTailwindcss` – pass `true` or `{ entryPoint, tailwindConfig }` to enable `eslint-plugin-better-tailwindcss` for Tailwind v4/v3 projects. Object mode defaults to fast syntax checks (`no-duplicate-classes` and `no-unnecessary-whitespace`) and scopes relative entry points to their source directory; set `rules: 'recommended'` to opt into the full recommended preset.
73
76
  - `unocss` – pass `true` to use the upstream Antfu UnoCSS preset, or provide `{ strict, attributify, configPath }` to keep the same preset while using the Icebreaker wrapper API.
74
77
  - `mdx` – activates MDX linting via `eslint-plugin-mdx`.
75
78
  - `a11y` – wires in JSX (React) and Vue accessibility plugins. Missing framework-specific plugins are skipped independently.
package/README.zh.md CHANGED
@@ -76,8 +76,10 @@ export default icebreaker({
76
76
  query: true,
77
77
  typescript: true,
78
78
  test: true,
79
- tailwindcss: {
80
- tailwindConfig: './tailwind.config.ts',
79
+ tailwindcss: true,
80
+ betterTailwindcss: {
81
+ entryPoint: './src/tailwind.css',
82
+ rules: 'recommended',
81
83
  },
82
84
  mdx: process.env.LINT_MDX === 'true',
83
85
  a11y: true,
@@ -92,7 +94,8 @@ export default icebreaker({
92
94
  - `vue`:启用 Vue 规则,可根据 Vue 2/3 自动切换,并在 `ionic`、`miniProgram` 选项开启时追加对应覆盖。
93
95
  - `react`:复用上游 React 预设;React 核心 lint 插件已内置在当前包里,配合 `a11y` 使用的 React 无障碍插件仍需按需安装。
94
96
  - `query`:按需启用 TanStack Query 插件(`@tanstack/eslint-plugin-query`)及其推荐规则;缺少插件时按 no-op 处理。
95
- - `tailwindcss`:传入 `true` 使用内置 Tailwind flat 配置,或通过对象指定 Tailwind v4 的入口文件 / v3 的配置文件路径。
97
+ - `tailwindcss`:传入 `true` 启用 `eslint-plugin-tailwindcss`。
98
+ - `betterTailwindcss`:传入 `true` 或 `{ entryPoint, tailwindConfig }` 启用 `eslint-plugin-better-tailwindcss`,用于 Tailwind v4 / v3 项目。对象模式默认只启用较快的语法检查(`no-duplicate-classes` 和 `no-unnecessary-whitespace`),并会把相对入口文件限制到对应源码目录;如需完整推荐规则,可设置 `rules: 'recommended'`。
96
99
  - `mdx`:激活 `eslint-plugin-mdx` 处理 `.mdx` 文件。
97
100
  - `a11y`:按需引入 JSX 与 Vue 的无障碍规则,缺少某一侧插件时只跳过对应框架配置。
98
101
  - `typescript`:开启 TypeScript 预设,加强未使用诊断,可与 `nestjs` 搭配使用以获得 Nest 专属优化。
package/dist/index.cjs CHANGED
@@ -1,16 +1,47 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_rolldown_runtime = require("./rolldown-runtime-DzWaZAza.cjs");
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __exportAll = (all, no_symbols) => {
10
+ let target = {};
11
+ for (var name in all) __defProp(target, name, {
12
+ get: all[name],
13
+ enumerable: true
14
+ });
15
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
16
+ return target;
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
20
+ key = keys[i];
21
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
22
+ get: ((k) => from[k]).bind(null, key),
23
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
24
+ });
25
+ }
26
+ return to;
27
+ };
28
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
29
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
30
+ value: mod,
31
+ enumerable: true
32
+ }) : target, mod));
33
+ //#endregion
34
+ let node_module = require("node:module");
3
35
  let node_path = require("node:path");
4
- node_path = require_rolldown_runtime.__toESM(node_path, 1);
5
- let node_process = require("node:process");
6
- node_process = require_rolldown_runtime.__toESM(node_process, 1);
36
+ node_path = __toESM(node_path, 1);
7
37
  let node_fs = require("node:fs");
8
- node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
9
- let node_module = require("node:module");
38
+ node_fs = __toESM(node_fs, 1);
39
+ let node_process = require("node:process");
40
+ node_process = __toESM(node_process, 1);
10
41
  let node_url = require("node:url");
11
42
  //#region src/antfu.ts
12
- var antfu_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({});
13
- require_rolldown_runtime.__reExport(antfu_exports, require("@antfu/eslint-config"));
43
+ var antfu_exports = /* @__PURE__ */ __exportAll({});
44
+ __reExport(antfu_exports, require("@antfu/eslint-config"));
14
45
  //#endregion
15
46
  //#region src/defaults.ts
16
47
  const nestjsTypeScriptRules = {
@@ -99,14 +130,14 @@ function getDefaultTypescriptOptions(opts) {
99
130
  }
100
131
  //#endregion
101
132
  //#region src/utils.ts
102
- const require$2 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
133
+ const require$3 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
103
134
  const PACKAGE_DIR = node_path.default.dirname((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
104
135
  function isObject(o) {
105
136
  return Object.prototype.toString.call(o) === "[object Object]";
106
137
  }
107
138
  function isPackageAvailable$1(name, searchPaths = [node_process.default.cwd(), PACKAGE_DIR]) {
108
139
  try {
109
- require$2.resolve(name, { paths: searchPaths });
140
+ require$3.resolve(name, { paths: searchPaths });
110
141
  return true;
111
142
  } catch {
112
143
  const packageSegments = name.split("/");
@@ -128,13 +159,14 @@ function hasAllPackages(names, searchPaths) {
128
159
  //#endregion
129
160
  //#region src/features.ts
130
161
  const BETTER_TAILWIND_PACKAGES = ["eslint-plugin-better-tailwindcss"];
131
- const TAILWIND_PACKAGES = ["eslint-plugin-tailwindcss"];
162
+ const TAILWIND_PACKAGES = ["eslint-plugin-tailwindcss", "tailwindcss"];
132
163
  const STYLELINT_BRIDGE_PACKAGES = ["eslint-plugin-better-stylelint"];
133
164
  const MDX_PACKAGES = ["eslint-plugin-mdx"];
134
165
  const VUE_A11Y_PACKAGES = ["eslint-plugin-vuejs-accessibility"];
135
166
  const REACT_A11Y_PACKAGES = ["eslint-plugin-jsx-a11y"];
136
167
  const QUERY_PACKAGES = ["@tanstack/eslint-plugin-query"];
137
- const BETTER_TAILWIND_FILES = ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx,vue,html,md,mdx,astro,svelte}"];
168
+ const BETTER_TAILWIND_EXTENSIONS = "js,mjs,cjs,ts,mts,cts,jsx,tsx,vue,html,md,mdx,astro,svelte";
169
+ const BETTER_TAILWIND_FILES = [`**/*.{${BETTER_TAILWIND_EXTENSIONS}}`];
138
170
  const BETTER_TAILWIND_IGNORES = [
139
171
  "**/*.json",
140
172
  "**/*.json5",
@@ -152,38 +184,69 @@ const BETTER_TAILWIND_IGNORES = [
152
184
  "**/Gemfile.lock",
153
185
  "**/go.sum"
154
186
  ];
187
+ const BETTER_TAILWIND_SYNTAX_RULES = {
188
+ "better-tailwindcss/no-duplicate-classes": "warn",
189
+ "better-tailwindcss/no-unnecessary-whitespace": "warn"
190
+ };
191
+ const require$2 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
192
+ function interopPluginDefault(modulePromise) {
193
+ return (0, antfu_exports.interopDefault)(modulePromise);
194
+ }
155
195
  function resolveStylelintConfigLoader(moduleUrl = require("url").pathToFileURL(__filename).href) {
156
196
  return moduleUrl.endsWith(".ts") ? new URL("./stylelint.ts", moduleUrl).href : new URL("./stylelint.js", moduleUrl).href;
157
197
  }
198
+ function resolveDefaultTailwindCssConfigPath() {
199
+ try {
200
+ return require$2.resolve("tailwindcss/index.css");
201
+ } catch {
202
+ return;
203
+ }
204
+ }
205
+ function normalizeGlobPath(filePath) {
206
+ return filePath.replaceAll(node_path.default.sep, "/").replace(/^\.\//, "");
207
+ }
208
+ function resolveBetterTailwindFiles(option) {
209
+ if (option.files?.length) return option.files;
210
+ if (!option.entryPoint || node_path.default.isAbsolute(option.entryPoint)) return BETTER_TAILWIND_FILES;
211
+ const sourceDir = normalizeGlobPath(node_path.default.dirname(option.entryPoint));
212
+ if (!sourceDir || sourceDir === ".") return BETTER_TAILWIND_FILES;
213
+ return [`${sourceDir}/**/*.{${BETTER_TAILWIND_EXTENSIONS}}`];
214
+ }
215
+ function resolveBetterTailwindRules(plugin, option) {
216
+ if (option.rules === "recommended") return plugin.configs.recommended?.rules ?? {};
217
+ return BETTER_TAILWIND_SYNTAX_RULES;
218
+ }
219
+ function resolveBetterTailwindPresets(option) {
220
+ if (!option) return [];
221
+ if (!hasAllPackages(BETTER_TAILWIND_PACKAGES)) return [];
222
+ const betterTailwindcssOption = typeof option === "object" ? option : {};
223
+ return [interopPluginDefault(import("eslint-plugin-better-tailwindcss")).then((eslintPluginBetterTailwindcss) => {
224
+ const betterTailwindcssRules = resolveBetterTailwindRules(eslintPluginBetterTailwindcss, betterTailwindcssOption);
225
+ return {
226
+ name: "icebreaker/better-tailwindcss",
227
+ files: resolveBetterTailwindFiles(betterTailwindcssOption),
228
+ ignores: BETTER_TAILWIND_IGNORES,
229
+ plugins: { "better-tailwindcss": eslintPluginBetterTailwindcss },
230
+ rules: betterTailwindcssRules,
231
+ settings: { "better-tailwindcss": {
232
+ cwd: betterTailwindcssOption.cwd,
233
+ entryPoint: betterTailwindcssOption.entryPoint,
234
+ tailwindConfig: betterTailwindcssOption.tailwindConfig
235
+ } }
236
+ };
237
+ })];
238
+ }
158
239
  function resolveTailwindPresets(option) {
159
240
  if (!option) return [];
160
- if (typeof option === "object") {
161
- if (!hasAllPackages(BETTER_TAILWIND_PACKAGES)) return [];
162
- return [(0, antfu_exports.interopDefault)(import("eslint-plugin-better-tailwindcss")).then((eslintPluginBetterTailwindcss) => {
163
- const cwd = option.cwd ?? (option.entryPoint ? node_path.default.dirname(option.entryPoint) : void 0) ?? node_process.default.cwd();
164
- const betterTailwindcssRules = {
165
- ...eslintPluginBetterTailwindcss.configs["recommended-warn"].rules,
166
- ...eslintPluginBetterTailwindcss.configs["recommended-error"].rules
167
- };
168
- return {
169
- name: "icebreaker/better-tailwindcss",
170
- files: BETTER_TAILWIND_FILES,
171
- ignores: BETTER_TAILWIND_IGNORES,
172
- plugins: { "better-tailwindcss": eslintPluginBetterTailwindcss },
173
- rules: betterTailwindcssRules,
174
- settings: { "better-tailwindcss": {
175
- cwd,
176
- entryPoint: option.entryPoint,
177
- tailwindConfig: option.tailwindConfig
178
- } }
179
- };
180
- })];
181
- }
182
241
  if (!hasAllPackages(TAILWIND_PACKAGES)) return [];
183
- return [(0, antfu_exports.interopDefault)(import("eslint-plugin-tailwindcss")).then((tailwind) => {
242
+ const cssConfigPath = resolveDefaultTailwindCssConfigPath();
243
+ return [interopPluginDefault(import("eslint-plugin-tailwindcss")).then((tailwind) => {
184
244
  const tailwindPlugin = tailwind;
185
245
  return tailwindPlugin.configs["flat/recommended"] ?? tailwindPlugin.configs.recommended ?? [];
186
- }), { rules: { "tailwindcss/no-custom-classname": "off" } }];
246
+ }), {
247
+ ...cssConfigPath ? { settings: { tailwindcss: { cssConfigPath } } } : {},
248
+ rules: { "tailwindcss/no-custom-classname": "off" }
249
+ }];
187
250
  }
188
251
  function resolveStylelintBridgeOptions(option) {
189
252
  const { cwd, ...stylelintConfigOptions } = typeof option === "object" ? option : {};
@@ -225,7 +288,7 @@ function resolveStylelintBridgePresets(option) {
225
288
  function resolveMdxPresets(isEnabled) {
226
289
  if (!isEnabled) return [];
227
290
  if (!hasAllPackages(MDX_PACKAGES)) return [];
228
- return [(0, antfu_exports.interopDefault)(import("eslint-plugin-mdx")).then((mdx) => {
291
+ return [interopPluginDefault(import("eslint-plugin-mdx")).then((mdx) => {
229
292
  return [{
230
293
  ...mdx.flat,
231
294
  processor: mdx.createRemarkProcessor({
@@ -241,10 +304,10 @@ function resolveMdxPresets(isEnabled) {
241
304
  function resolveAccessibilityPresets(isEnabled, vueOption, reactOption) {
242
305
  if (!isEnabled) return [];
243
306
  const presets = [];
244
- if (vueOption && hasAllPackages(VUE_A11Y_PACKAGES)) presets.push((0, antfu_exports.interopDefault)(Promise.resolve().then(() => /* @__PURE__ */ require_rolldown_runtime.__toESM(require("./dist-Cfcd4odI.cjs").default, 1))).then((pluginVueA11y) => {
307
+ if (vueOption && hasAllPackages(VUE_A11Y_PACKAGES)) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-vuejs-accessibility")).then((pluginVueA11y) => {
245
308
  return pluginVueA11y.configs["flat/recommended"];
246
309
  }));
247
- if (reactOption && hasAllPackages(REACT_A11Y_PACKAGES)) presets.push((0, antfu_exports.interopDefault)(Promise.resolve().then(() => /* @__PURE__ */ require_rolldown_runtime.__toESM(require("./lib-CcedSpss.cjs").default, 1))).then((jsxA11y) => {
310
+ if (reactOption && hasAllPackages(REACT_A11Y_PACKAGES)) presets.push((0, antfu_exports.interopDefault)(import("eslint-plugin-jsx-a11y")).then((jsxA11y) => {
248
311
  return jsxA11y.flatConfigs.recommended;
249
312
  }));
250
313
  return presets;
@@ -259,7 +322,7 @@ function resolveNestPresets(isEnabled) {
259
322
  function resolveQueryPresets(isEnabled) {
260
323
  if (!isEnabled) return [];
261
324
  if (!hasAllPackages(QUERY_PACKAGES)) return [];
262
- return [(0, antfu_exports.interopDefault)(Promise.resolve().then(() => require("./modern-y8Mo-zyc.cjs"))).then((pluginQuery) => pluginQuery.configs["flat/recommended"])];
325
+ return [interopPluginDefault(Promise.resolve().then(() => require("./modern-Dnpu3mfI.cjs"))).then((pluginQuery) => pluginQuery.configs["flat/recommended"])];
263
326
  }
264
327
  //#endregion
265
328
  //#region ../../node_modules/.pnpm/defu@6.1.7/node_modules/defu/dist/defu.mjs
@@ -456,6 +519,11 @@ function resolveUserOptions(options) {
456
519
  resolved.miniProgram = true;
457
520
  delete resolved.weapp;
458
521
  }
522
+ const legacyTailwindcssOption = resolved.tailwindcss;
523
+ if (isObject(legacyTailwindcssOption)) {
524
+ resolved.betterTailwindcss ??= legacyTailwindcssOption;
525
+ delete resolved.tailwindcss;
526
+ }
459
527
  const resolvedVue = mergeOptionWithDefaults(resolved.vue, getDefaultVueOptions(options), { postProcess: applyVueVersionSpecificRules });
460
528
  if (resolvedVue === void 0) delete resolved.vue;
461
529
  else resolved.vue = resolvedVue;
@@ -521,7 +589,7 @@ function getPresets(options, mode) {
521
589
  languageOptions: { parser: antfu_exports.parserPlain },
522
590
  rules: {}
523
591
  });
524
- presets.push(...resolveStylelintBridgePresets(resolved.stylelint), ...resolveTailwindPresets(resolved.tailwindcss), ...resolveMdxPresets(resolved.mdx), ...resolveNestPresets(resolved.nestjs), ...resolveQueryPresets(resolved.query), ...resolveAccessibilityPresets(resolved.a11y, resolved.vue, resolved.react));
592
+ presets.push(...resolveStylelintBridgePresets(resolved.stylelint), ...resolveTailwindPresets(resolved.tailwindcss), ...resolveBetterTailwindPresets(resolved.betterTailwindcss), ...resolveMdxPresets(resolved.mdx), ...resolveNestPresets(resolved.nestjs), ...resolveQueryPresets(resolved.query), ...resolveAccessibilityPresets(resolved.a11y, resolved.vue, resolved.react));
525
593
  return [resolved, ...presets];
526
594
  }
527
595
  //#endregion
@@ -646,7 +714,7 @@ function isComposer(value) {
646
714
  return !!value && typeof value === "object" && "toConfigs" in value && typeof value.toConfigs === "function";
647
715
  }
648
716
  function normalizeUserConfig(userConfig) {
649
- if (typeof userConfig?.then === "function") return Promise.resolve(userConfig).then((resolved) => {
717
+ if (typeof userConfig?.then === "function") return userConfig.then((resolved) => {
650
718
  return isComposer(resolved) ? resolved : normalizeResolvedUserConfig(resolved);
651
719
  });
652
720
  const resolvedUserConfig = userConfig;