@icebreakers/eslint-config 4.0.0 → 4.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 +101 -3
- package/README.zh.md +93 -2
- package/dist/index.cjs +136 -15
- package/dist/index.d.cts +1434 -267
- package/dist/index.d.ts +1434 -267
- package/dist/index.js +136 -15
- package/index.d.ts +8 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -53,6 +53,9 @@ export default icebreaker({
|
|
|
53
53
|
tailwindcss: {
|
|
54
54
|
tailwindConfig: './tailwind.config.ts',
|
|
55
55
|
},
|
|
56
|
+
unocss: {
|
|
57
|
+
strict: true,
|
|
58
|
+
},
|
|
56
59
|
mdx: process.env.LINT_MDX === 'true',
|
|
57
60
|
a11y: true,
|
|
58
61
|
nestjs: true,
|
|
@@ -67,14 +70,53 @@ export default icebreaker({
|
|
|
67
70
|
- `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
71
|
- `query` – toggles the TanStack Query plugin (`@tanstack/eslint-plugin-query`) and its recommended lint rules. Missing plugin installs are treated as a no-op.
|
|
69
72
|
- `tailwindcss` – pass `true` to use the built-in Tailwind flat config or provide `{ entryPoint, tailwindConfig }` for Tailwind v4/v3 projects.
|
|
73
|
+
- `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.
|
|
70
74
|
- `mdx` – activates MDX linting via `eslint-plugin-mdx`.
|
|
71
75
|
- `a11y` – wires in JSX (React) and Vue accessibility plugins. Missing framework-specific plugins are skipped independently.
|
|
72
76
|
- `typescript` – extends the TypeScript preset and applies stricter unused diagnostics. Pair with `nestjs` for Nest specific adjustments.
|
|
73
77
|
- `nestjs` – enables NestJS-centric TypeScript tweaks (empty decorated constructors, declaration merging, DI parameter properties, etc.).
|
|
74
|
-
- `formatters` – keeps the built-in formatting rules enabled by default
|
|
78
|
+
- `formatters` – keeps the built-in formatting rules enabled by default, including CSS/SCSS/Less formatting through `eslint-plugin-format`.
|
|
75
79
|
- `test` – relaxes certain Vitest/Jest style rules (`test/prefer-lowercase-title`).
|
|
76
80
|
- `weapp` – legacy alias for `miniProgram`; kept for backward compatibility.
|
|
77
81
|
|
|
82
|
+
### Formatter Engines
|
|
83
|
+
|
|
84
|
+
`@icebreakers/eslint-config` still uses `eslint-plugin-format` as the formatter
|
|
85
|
+
bridge. The default formatter path stays aligned with the upstream Prettier
|
|
86
|
+
setup. Icebreaker still lets you opt specific file types into `oxfmt` when you
|
|
87
|
+
want to experiment or tune a project explicitly:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { icebreaker } from '@icebreakers/eslint-config'
|
|
91
|
+
|
|
92
|
+
export default icebreaker({
|
|
93
|
+
formatters: {
|
|
94
|
+
css: 'oxfmt',
|
|
95
|
+
html: 'oxfmt',
|
|
96
|
+
markdown: 'oxfmt',
|
|
97
|
+
graphql: 'oxfmt',
|
|
98
|
+
oxfmtOptions: {
|
|
99
|
+
lineWidth: 100,
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Support matrix:
|
|
106
|
+
|
|
107
|
+
- default: CSS/SCSS/Less, HTML, GraphQL, Markdown, XML, SVG, Astro, and Slidev
|
|
108
|
+
stay on the upstream Prettier path
|
|
109
|
+
- `css: 'oxfmt'` also switches SCSS and Less to `format/oxfmt`
|
|
110
|
+
- `html: 'oxfmt'` switches HTML to `format/oxfmt`
|
|
111
|
+
- `markdown: 'oxfmt'` switches Markdown to `format/oxfmt`
|
|
112
|
+
- `graphql: 'oxfmt'` switches GraphQL to `format/oxfmt`
|
|
113
|
+
|
|
114
|
+
Current limits:
|
|
115
|
+
|
|
116
|
+
- This is not a full `format/prettier` to `format/oxfmt` migration layer
|
|
117
|
+
- `markdown: 'oxfmt'` cannot be combined with `formatters.slidev`
|
|
118
|
+
- `oxfmtOptions` are passed directly to `format/oxfmt`
|
|
119
|
+
|
|
78
120
|
### Mini Program Preset
|
|
79
121
|
|
|
80
122
|
`miniProgram: true` is the recommended API for `weapp-vite`, `wevu`, and native
|
|
@@ -162,6 +204,58 @@ export default icebreaker({
|
|
|
162
204
|
the `@icebreakers/stylelint-config` options (`presets`, `tailwindcssPreset`,
|
|
163
205
|
`ignores`, `extends`, `overrides`, `rules`).
|
|
164
206
|
|
|
207
|
+
The ESLint bridge surfaces Stylelint diagnostics, but it does not replace a
|
|
208
|
+
full standalone Stylelint workflow. If you want Stylelint CLI, editor-native
|
|
209
|
+
Stylelint integration, or dedicated `stylelint --fix` runs, install `stylelint`
|
|
210
|
+
and `@icebreakers/stylelint-config` in the consuming project as well.
|
|
211
|
+
|
|
212
|
+
Recommended consumer scripts:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"scripts": {
|
|
217
|
+
"lint": "eslint .",
|
|
218
|
+
"lint:fix": "eslint . --fix",
|
|
219
|
+
"lint:styles": "stylelint \"src/**/*.{css,scss,vue}\"",
|
|
220
|
+
"lint:styles:fix": "stylelint \"src/**/*.{css,scss,vue}\" --fix"
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Use `lint:fix` when you want a single ESLint-driven formatting pass, including
|
|
226
|
+
CSS-family files via `formatters`. Add the separate Stylelint scripts when you
|
|
227
|
+
want the full Stylelint toolchain on top.
|
|
228
|
+
|
|
229
|
+
### UnoCSS Projects
|
|
230
|
+
|
|
231
|
+
The UnoCSS integration is still powered by the upstream Antfu preset, but
|
|
232
|
+
`@icebreakers/eslint-config` adds a small wrapper so the config file path can be
|
|
233
|
+
declared next to the other UnoCSS options:
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
import path from 'node:path'
|
|
237
|
+
import { icebreaker } from '@icebreakers/eslint-config'
|
|
238
|
+
|
|
239
|
+
export default icebreaker({
|
|
240
|
+
unocss: {
|
|
241
|
+
strict: true,
|
|
242
|
+
attributify: false,
|
|
243
|
+
configPath: path.resolve(process.cwd(), './uno.config.ts'),
|
|
244
|
+
},
|
|
245
|
+
})
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Behavior details:
|
|
249
|
+
|
|
250
|
+
- `unocss: true` enables the upstream Antfu UnoCSS preset unchanged.
|
|
251
|
+
- `unocss.configPath` is an Icebreaker wrapper for `settings.unocss.configPath`.
|
|
252
|
+
- If `configPath` is omitted, UnoCSS still searches the lint project root for
|
|
253
|
+
`uno.config.*`.
|
|
254
|
+
- If both `unocss.configPath` and `settings.unocss.configPath` are provided,
|
|
255
|
+
`unocss.configPath` wins.
|
|
256
|
+
- If `@unocss/eslint-plugin` is unavailable, the UnoCSS preset is skipped
|
|
257
|
+
instead of throwing.
|
|
258
|
+
|
|
165
259
|
### NestJS Projects
|
|
166
260
|
|
|
167
261
|
Enable `nestjs: true` together with the TypeScript preset to apply rules tailored for Nest idioms:
|
|
@@ -194,10 +288,14 @@ You may also pass other flat configs (e.g. from in-house presets) as additional
|
|
|
194
288
|
|
|
195
289
|
- Install the VS Code ESLint extension (`>=3.0.10`).
|
|
196
290
|
- Set `"eslint.experimental.useFlatConfig": true` for older VS Code builds.
|
|
197
|
-
- Use `
|
|
291
|
+
- Use `lint:fix` for the default ESLint-driven formatting flow, including
|
|
292
|
+
CSS/SCSS/Less. Add `lint:styles:fix` when your project also uses standalone
|
|
293
|
+
Stylelint runs.
|
|
294
|
+
- If you opt specific file types into `oxfmt`, the same `eslint --fix` flow
|
|
295
|
+
continues to work. Only the formatter engine changes.
|
|
198
296
|
|
|
199
297
|
## Troubleshooting
|
|
200
298
|
|
|
201
|
-
- Missing plugin errors usually mean a feature is enabled without its optional dependency being installed in the current workspace. React and
|
|
299
|
+
- Missing plugin errors usually mean a feature is enabled without its optional dependency being installed in the current workspace. React, Next, and UnoCSS related presets now auto-skip in that case; other features can be added with `pnpm add -D`.
|
|
202
300
|
- When combining legacy `.eslintrc` projects, prefer `icebreakerLegacy()` and move overrides into flat config format incrementally.
|
|
203
301
|
- 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
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @icebreakers/eslint-config
|
|
2
2
|
|
|
3
|
+
## UnoCSS 包装层
|
|
4
|
+
|
|
5
|
+
`@icebreakers/eslint-config` 的 UnoCSS 能力仍然复用上游
|
|
6
|
+
`@antfu/eslint-config`,但现在额外提供了一层更贴近本仓库风格的包装 API。
|
|
7
|
+
|
|
8
|
+
推荐写法:
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import path from 'node:path'
|
|
12
|
+
import { icebreaker } from '@icebreakers/eslint-config'
|
|
13
|
+
|
|
14
|
+
export default icebreaker({
|
|
15
|
+
unocss: {
|
|
16
|
+
strict: true,
|
|
17
|
+
attributify: false,
|
|
18
|
+
configPath: path.resolve(process.cwd(), './uno.config.ts'),
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
行为说明:
|
|
24
|
+
|
|
25
|
+
- `unocss: true`:直接启用上游 Antfu 的 UnoCSS preset
|
|
26
|
+
- `unocss.configPath`:会被自动映射为 `settings.unocss.configPath`
|
|
27
|
+
- 不传 `configPath`:仍然按 UnoCSS 默认行为,从 lint 项目根目录查找 `uno.config.*`
|
|
28
|
+
- 同时传 `unocss.configPath` 和 `settings.unocss.configPath`:以前者为准
|
|
29
|
+
- 如果当前 workspace 没有安装 `@unocss/eslint-plugin`:该 preset 会自动跳过,不会直接抛错
|
|
30
|
+
|
|
3
31
|
## 简介
|
|
4
32
|
|
|
5
33
|
`@icebreakers/eslint-config` 基于 `@antfu/eslint-config` 的 flat config 预设,额外补充了 Tailwind CSS、MDX、Vue 无障碍以及 Icebreaker 团队常用的 TypeScript 默认规则。它返回一个 `FlatConfigComposer`,可以按需启用不同预设,并继续追加工作区特定的覆盖项。
|
|
@@ -69,10 +97,47 @@ export default icebreaker({
|
|
|
69
97
|
- `a11y`:按需引入 JSX 与 Vue 的无障碍规则,缺少某一侧插件时只跳过对应框架配置。
|
|
70
98
|
- `typescript`:开启 TypeScript 预设,加强未使用诊断,可与 `nestjs` 搭配使用以获得 Nest 专属优化。
|
|
71
99
|
- `nestjs`:针对 NestJS 场景做 TypeScript 调整(允许带装饰器的空构造函数、依赖注入参数属性、声明合并等)。
|
|
72
|
-
- `formatters
|
|
100
|
+
- `formatters`:默认启用格式化辅助规则,其中也包括通过 `eslint-plugin-format` 处理 CSS / SCSS / Less。
|
|
73
101
|
- `test`:放宽 Vitest / Jest 常见规则,例如关闭 `test/prefer-lowercase-title`。
|
|
74
102
|
- `weapp`:`miniProgram` 的兼容别名,保留但不再推荐作为主入口。
|
|
75
103
|
|
|
104
|
+
### 格式化引擎
|
|
105
|
+
|
|
106
|
+
`@icebreakers/eslint-config` 仍然通过 `eslint-plugin-format` 承载样式类与文档类文件的格式化链路。
|
|
107
|
+
默认行为仍然与上游 Prettier 链路保持一致;如果你想在项目里做专项实验,
|
|
108
|
+
也可以继续手动把部分文件类型切到 `oxfmt`:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { icebreaker } from '@icebreakers/eslint-config'
|
|
112
|
+
|
|
113
|
+
export default icebreaker({
|
|
114
|
+
formatters: {
|
|
115
|
+
css: 'oxfmt',
|
|
116
|
+
html: 'oxfmt',
|
|
117
|
+
markdown: 'oxfmt',
|
|
118
|
+
graphql: 'oxfmt',
|
|
119
|
+
oxfmtOptions: {
|
|
120
|
+
lineWidth: 100,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
})
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
支持范围:
|
|
127
|
+
|
|
128
|
+
- 默认值:CSS / SCSS / Less、HTML、GraphQL、Markdown、XML、SVG、Astro、Slidev
|
|
129
|
+
继续走上游 Prettier 链路
|
|
130
|
+
- `css: 'oxfmt'`:会同时切换 CSS / SCSS / Less
|
|
131
|
+
- `html: 'oxfmt'`:切换 HTML
|
|
132
|
+
- `markdown: 'oxfmt'`:切换 Markdown
|
|
133
|
+
- `graphql: 'oxfmt'`:切换 GraphQL
|
|
134
|
+
|
|
135
|
+
当前限制:
|
|
136
|
+
|
|
137
|
+
- 这不是一次完整的 `format/prettier -> format/oxfmt` 全量迁移
|
|
138
|
+
- `markdown: 'oxfmt'` 不能与 `formatters.slidev` 同时开启
|
|
139
|
+
- `oxfmtOptions` 会原样透传给 `format/oxfmt`
|
|
140
|
+
|
|
76
141
|
### 小程序预设
|
|
77
142
|
|
|
78
143
|
推荐在 `weapp-vite`、`wevu`、原生小程序模板里统一使用 `miniProgram: true`。
|
|
@@ -163,6 +228,28 @@ export default icebreaker({
|
|
|
163
228
|
`@icebreakers/stylelint-config` 的选项结构,例如 `presets`、
|
|
164
229
|
`tailwindcssPreset`、`ignores`、`extends`、`overrides`、`rules`。
|
|
165
230
|
|
|
231
|
+
需要注意的是,这个 bridge 只负责把 Stylelint 诊断桥接到 ESLint,
|
|
232
|
+
并不等价于完整的 Stylelint 工作流。如果你需要独立的 Stylelint CLI、
|
|
233
|
+
编辑器内原生 Stylelint 集成,或单独执行 `stylelint --fix`,仍然建议在
|
|
234
|
+
接入方项目里额外安装 `stylelint` 和 `@icebreakers/stylelint-config`。
|
|
235
|
+
|
|
236
|
+
推荐给接入方使用的脚本约定:
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"scripts": {
|
|
241
|
+
"lint": "eslint .",
|
|
242
|
+
"lint:fix": "eslint . --fix",
|
|
243
|
+
"lint:styles": "stylelint \"src/**/*.{css,scss,vue}\"",
|
|
244
|
+
"lint:styles:fix": "stylelint \"src/**/*.{css,scss,vue}\" --fix"
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
如果你希望继续使用一条 `eslint --fix` 主链路,那么 `lint:fix` 默认也会
|
|
250
|
+
通过 `formatters` 处理 CSS / SCSS / Less。只有在项目需要完整 Stylelint
|
|
251
|
+
工具链时,再补充 `lint:styles` / `lint:styles:fix`。
|
|
252
|
+
|
|
166
253
|
### NestJS 项目
|
|
167
254
|
|
|
168
255
|
建议在 Nest 项目中同时开启 `typescript` 与 `nestjs`,以便应用以下定制:
|
|
@@ -195,7 +282,11 @@ export default icebreaker(
|
|
|
195
282
|
|
|
196
283
|
- VS Code 安装 ESLint 扩展(版本需 ≥ 3.0.10)。
|
|
197
284
|
- 老版本 VS Code 需在设置中启用 `"eslint.experimental.useFlatConfig": true`。
|
|
198
|
-
-
|
|
285
|
+
- 默认可使用 `lint:fix` 作为 ESLint 主修复链路,其中包含 CSS / SCSS /
|
|
286
|
+
Less 的格式化。只有在项目额外启用独立 Stylelint 工作流时,再运行
|
|
287
|
+
`lint:styles:fix`。
|
|
288
|
+
- 如果你把部分文件类型切到 `oxfmt`,仍然继续使用同一条 `eslint --fix`
|
|
289
|
+
链路,只是底层格式化引擎发生变化。
|
|
199
290
|
|
|
200
291
|
## 常见问题
|
|
201
292
|
|
package/dist/index.cjs
CHANGED
|
@@ -188,8 +188,8 @@ const MDX_PACKAGES = ["eslint-plugin-mdx"];
|
|
|
188
188
|
const VUE_A11Y_PACKAGES = ["eslint-plugin-vuejs-accessibility"];
|
|
189
189
|
const REACT_A11Y_PACKAGES = ["eslint-plugin-jsx-a11y"];
|
|
190
190
|
const QUERY_PACKAGES = ["@tanstack/eslint-plugin-query"];
|
|
191
|
-
function resolveStylelintConfigLoader() {
|
|
192
|
-
return
|
|
191
|
+
function resolveStylelintConfigLoader(moduleUrl = require("url").pathToFileURL(__filename).href) {
|
|
192
|
+
return moduleUrl.endsWith(".ts") ? new URL("./stylelint.ts", moduleUrl).href : new URL("./stylelint.js", moduleUrl).href;
|
|
193
193
|
}
|
|
194
194
|
function resolveTailwindPresets(option) {
|
|
195
195
|
if (!option) return [];
|
|
@@ -294,7 +294,7 @@ function resolveQueryPresets(isEnabled) {
|
|
|
294
294
|
}
|
|
295
295
|
//#endregion
|
|
296
296
|
//#region ../../node_modules/.pnpm/defu@6.1.6/node_modules/defu/dist/defu.mjs
|
|
297
|
-
function isPlainObject(value) {
|
|
297
|
+
function isPlainObject$1(value) {
|
|
298
298
|
if (value === null || typeof value !== "object") return false;
|
|
299
299
|
const prototype = Object.getPrototypeOf(value);
|
|
300
300
|
if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) return false;
|
|
@@ -303,7 +303,7 @@ function isPlainObject(value) {
|
|
|
303
303
|
return true;
|
|
304
304
|
}
|
|
305
305
|
function _defu(baseObject, defaults, namespace = ".", merger) {
|
|
306
|
-
if (!isPlainObject(defaults)) return _defu(baseObject, {}, namespace, merger);
|
|
306
|
+
if (!isPlainObject$1(defaults)) return _defu(baseObject, {}, namespace, merger);
|
|
307
307
|
const object = { ...defaults };
|
|
308
308
|
for (const key of Object.keys(baseObject)) {
|
|
309
309
|
if (key === "__proto__" || key === "constructor") continue;
|
|
@@ -311,7 +311,7 @@ function _defu(baseObject, defaults, namespace = ".", merger) {
|
|
|
311
311
|
if (value === null || value === void 0) continue;
|
|
312
312
|
if (merger && merger(object, key, value, namespace)) continue;
|
|
313
313
|
if (Array.isArray(value) && Array.isArray(object[key])) object[key] = [...value, ...object[key]];
|
|
314
|
-
else if (isPlainObject(value) && isPlainObject(object[key])) object[key] = _defu(value, object[key], (namespace ? `${namespace}.` : "") + key.toString(), merger);
|
|
314
|
+
else if (isPlainObject$1(value) && isPlainObject$1(object[key])) object[key] = _defu(value, object[key], (namespace ? `${namespace}.` : "") + key.toString(), merger);
|
|
315
315
|
else object[key] = value;
|
|
316
316
|
}
|
|
317
317
|
return object;
|
|
@@ -407,13 +407,14 @@ function isPackageAvailable(name, paths) {
|
|
|
407
407
|
}
|
|
408
408
|
function getDefaultFormatterOptions(cwd = node_process.default.cwd()) {
|
|
409
409
|
const hasXmlPlugin = isPackageAvailable("@prettier/plugin-xml", [ANTFU_PACKAGE_DIR]);
|
|
410
|
+
const hasSlidev = isPackageAvailable("@slidev/cli", [cwd]);
|
|
410
411
|
return {
|
|
411
412
|
astro: isPackageAvailable("prettier-plugin-astro", [ANTFU_PACKAGE_DIR]),
|
|
412
413
|
css: true,
|
|
413
414
|
graphql: true,
|
|
414
415
|
html: true,
|
|
415
416
|
markdown: true,
|
|
416
|
-
slidev:
|
|
417
|
+
slidev: hasSlidev,
|
|
417
418
|
svg: hasXmlPlugin,
|
|
418
419
|
xml: hasXmlPlugin
|
|
419
420
|
};
|
|
@@ -483,11 +484,14 @@ function resolveFormattersOption(input, cwd = node_process.default.cwd()) {
|
|
|
483
484
|
if (input === false) return false;
|
|
484
485
|
const defaults = getDefaultFormatterOptions(cwd);
|
|
485
486
|
const inferredEndOfLine = inferPrettierEndOfLineFromEditorConfig(cwd);
|
|
486
|
-
const
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
return
|
|
487
|
+
const defaultsWithFormattingEngines = inferredEndOfLine ? defu({
|
|
488
|
+
oxfmtOptions: { endOfLine: inferredEndOfLine },
|
|
489
|
+
prettierOptions: { endOfLine: inferredEndOfLine }
|
|
490
|
+
}, defaults) : defaults;
|
|
491
|
+
if (input === void 0) return defaultsWithFormattingEngines;
|
|
492
|
+
if (input === true) return defaultsWithFormattingEngines;
|
|
493
|
+
if (isObject(input)) return defu(input, defaultsWithFormattingEngines);
|
|
494
|
+
return defaultsWithFormattingEngines;
|
|
491
495
|
}
|
|
492
496
|
function resolveUserOptions(options) {
|
|
493
497
|
const resolved = defu({}, options ?? {}, BASE_DEFAULTS);
|
|
@@ -578,14 +582,74 @@ const OPTIONAL_ANTFU_FEATURE_PACKAGES = {
|
|
|
578
582
|
"eslint-plugin-react-hooks",
|
|
579
583
|
"eslint-plugin-react-refresh"
|
|
580
584
|
],
|
|
581
|
-
nextjs: ["@next/eslint-plugin-next"]
|
|
585
|
+
nextjs: ["@next/eslint-plugin-next"],
|
|
586
|
+
unocss: ["@unocss/eslint-plugin"]
|
|
582
587
|
};
|
|
588
|
+
function isPlainObject(value) {
|
|
589
|
+
return value !== null && Object.prototype.toString.call(value) === "[object Object]";
|
|
590
|
+
}
|
|
591
|
+
function cloneUserDefinedOptions(options) {
|
|
592
|
+
const { settings, ...restOptions } = options;
|
|
593
|
+
if (settings === void 0) return { ...restOptions };
|
|
594
|
+
return {
|
|
595
|
+
...restOptions,
|
|
596
|
+
settings
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
function getSettingsRecord(settings) {
|
|
600
|
+
return isPlainObject(settings) ? settings : {};
|
|
601
|
+
}
|
|
602
|
+
function removeNamespacedSetting(options, namespace) {
|
|
603
|
+
if (!isPlainObject(options.settings)) return options;
|
|
604
|
+
const settings = getSettingsRecord(options.settings);
|
|
605
|
+
if (!(namespace in settings)) return options;
|
|
606
|
+
const { [namespace]: _unusedNamespace, ...restSettings } = settings;
|
|
607
|
+
const { settings: _settings, ...restOptions } = options;
|
|
608
|
+
if (Object.keys(restSettings).length === 0) return { ...restOptions };
|
|
609
|
+
return {
|
|
610
|
+
...restOptions,
|
|
611
|
+
settings: restSettings
|
|
612
|
+
};
|
|
613
|
+
}
|
|
583
614
|
function normalizeOptionalAntfuFeatures(options) {
|
|
584
|
-
const normalized =
|
|
615
|
+
const normalized = cloneUserDefinedOptions(options);
|
|
585
616
|
if (normalized.react && !hasAllPackages([...OPTIONAL_ANTFU_FEATURE_PACKAGES.react])) normalized.react = false;
|
|
586
617
|
if (normalized.nextjs && !hasAllPackages([...OPTIONAL_ANTFU_FEATURE_PACKAGES.nextjs])) normalized.nextjs = false;
|
|
618
|
+
if (normalized.unocss && !hasAllPackages([...OPTIONAL_ANTFU_FEATURE_PACKAGES.unocss])) {
|
|
619
|
+
normalized.unocss = false;
|
|
620
|
+
return removeNamespacedSetting(normalized, "unocss");
|
|
621
|
+
}
|
|
587
622
|
return normalized;
|
|
588
623
|
}
|
|
624
|
+
function mergeNamespacedSetting(options, namespace, value) {
|
|
625
|
+
const currentSettings = getSettingsRecord(options.settings);
|
|
626
|
+
const currentNamespaceSettings = isPlainObject(currentSettings[namespace]) ? currentSettings[namespace] : {};
|
|
627
|
+
return {
|
|
628
|
+
...options,
|
|
629
|
+
settings: {
|
|
630
|
+
...currentSettings,
|
|
631
|
+
[namespace]: {
|
|
632
|
+
...currentNamespaceSettings,
|
|
633
|
+
...value
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function normalizeUnoCssOptions(options) {
|
|
639
|
+
if (!options.unocss || typeof options.unocss !== "object") return options;
|
|
640
|
+
const { configPath, ...unocssOptions } = options.unocss;
|
|
641
|
+
const { settings, ...restOptions } = options;
|
|
642
|
+
const normalized = settings === void 0 ? {
|
|
643
|
+
...restOptions,
|
|
644
|
+
unocss: unocssOptions
|
|
645
|
+
} : {
|
|
646
|
+
...restOptions,
|
|
647
|
+
settings,
|
|
648
|
+
unocss: unocssOptions
|
|
649
|
+
};
|
|
650
|
+
if (!configPath) return normalized;
|
|
651
|
+
return mergeNamespacedSetting(normalized, "unocss", { configPath });
|
|
652
|
+
}
|
|
589
653
|
function hasGlobalIgnoreShape(config) {
|
|
590
654
|
const keys = Object.keys(config).filter((key) => key !== "name");
|
|
591
655
|
return keys.length === 1 && keys[0] === "ignores";
|
|
@@ -615,13 +679,70 @@ function normalizeUserConfig(userConfig) {
|
|
|
615
679
|
const resolvedUserConfig = userConfig;
|
|
616
680
|
return isComposer(resolvedUserConfig) ? resolvedUserConfig : normalizeResolvedUserConfig(resolvedUserConfig);
|
|
617
681
|
}
|
|
682
|
+
function isFormatterOptionsObject(value) {
|
|
683
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
684
|
+
}
|
|
685
|
+
function toOxfmtRuleEntry(options) {
|
|
686
|
+
return ["error", { ...options ?? {} }];
|
|
687
|
+
}
|
|
688
|
+
function normalizePrettierFormatterForAntfu(formatter) {
|
|
689
|
+
return formatter === "oxfmt" ? true : formatter;
|
|
690
|
+
}
|
|
691
|
+
function normalizeMarkdownFormatterForAntfu(formatter) {
|
|
692
|
+
return formatter === "oxfmt" ? true : formatter;
|
|
693
|
+
}
|
|
694
|
+
function toAntfuOptions(options) {
|
|
695
|
+
const { formatters, ...restOptions } = options;
|
|
696
|
+
if (!isFormatterOptionsObject(formatters)) return restOptions;
|
|
697
|
+
const { oxfmtOptions: _oxfmtOptions, css, html, markdown, graphql, ...restFormatters } = formatters;
|
|
698
|
+
return {
|
|
699
|
+
...restOptions,
|
|
700
|
+
formatters: {
|
|
701
|
+
...restFormatters,
|
|
702
|
+
...css === void 0 ? {} : { css: normalizePrettierFormatterForAntfu(css) },
|
|
703
|
+
...html === void 0 ? {} : { html: normalizePrettierFormatterForAntfu(html) },
|
|
704
|
+
...markdown === void 0 ? {} : { markdown: normalizeMarkdownFormatterForAntfu(markdown) },
|
|
705
|
+
...graphql === void 0 ? {} : { graphql: normalizePrettierFormatterForAntfu(graphql) }
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
function applyOxfmtFormatterOverrides(composer, formatters) {
|
|
710
|
+
if (!isFormatterOptionsObject(formatters)) return composer;
|
|
711
|
+
if (formatters.markdown === "oxfmt" && formatters.slidev) throw new Error("`formatters.markdown: \"oxfmt\"` cannot be combined with `formatters.slidev`.");
|
|
712
|
+
const oxfmtOptions = formatters.oxfmtOptions;
|
|
713
|
+
let nextComposer = composer;
|
|
714
|
+
if (formatters.css === "oxfmt") for (const name of [
|
|
715
|
+
"antfu/formatter/css",
|
|
716
|
+
"antfu/formatter/scss",
|
|
717
|
+
"antfu/formatter/less"
|
|
718
|
+
]) nextComposer = nextComposer.override(name, { rules: {
|
|
719
|
+
"format/oxfmt": toOxfmtRuleEntry(oxfmtOptions),
|
|
720
|
+
"format/prettier": "off"
|
|
721
|
+
} });
|
|
722
|
+
if (formatters.html === "oxfmt") nextComposer = nextComposer.override("antfu/formatter/html", { rules: {
|
|
723
|
+
"format/oxfmt": toOxfmtRuleEntry(oxfmtOptions),
|
|
724
|
+
"format/prettier": "off"
|
|
725
|
+
} });
|
|
726
|
+
if (formatters.markdown === "oxfmt") nextComposer = nextComposer.override("antfu/formatter/markdown", { rules: {
|
|
727
|
+
"format/oxfmt": toOxfmtRuleEntry(oxfmtOptions),
|
|
728
|
+
"format/prettier": "off",
|
|
729
|
+
"format/dprint": "off"
|
|
730
|
+
} });
|
|
731
|
+
if (formatters.graphql === "oxfmt") nextComposer = nextComposer.override("antfu/formatter/graphql", { rules: {
|
|
732
|
+
"format/oxfmt": toOxfmtRuleEntry(oxfmtOptions),
|
|
733
|
+
"format/prettier": "off"
|
|
734
|
+
} });
|
|
735
|
+
return nextComposer;
|
|
736
|
+
}
|
|
618
737
|
function icebreaker(options = {}, ...userConfigs) {
|
|
619
738
|
const [resolved, ...presets] = getPresets(options);
|
|
620
|
-
|
|
739
|
+
const normalized = normalizeUnoCssOptions(normalizeOptionalAntfuFeatures(resolved));
|
|
740
|
+
return applyOxfmtFormatterOverrides((0, antfu_exports.antfu)(toAntfuOptions(normalized), ...presets, ...userConfigs.map(normalizeUserConfig)), normalized.formatters);
|
|
621
741
|
}
|
|
622
742
|
function icebreakerLegacy(options = {}, ...userConfigs) {
|
|
623
743
|
const [resolved, ...presets] = getPresets(options, "legacy");
|
|
624
|
-
|
|
744
|
+
const normalized = normalizeUnoCssOptions(normalizeOptionalAntfuFeatures(resolved));
|
|
745
|
+
return applyOxfmtFormatterOverrides((0, antfu_exports.antfu)(toAntfuOptions(normalized), ...presets, ...userConfigs.map(normalizeUserConfig)), normalized.formatters);
|
|
625
746
|
}
|
|
626
747
|
//#endregion
|
|
627
748
|
exports.__toESM = __toESM;
|