Skip to content

Commit 01bc596

Browse files
committed
docs(eslint-config): expand site into proper reference
The /eslint-config page was a thin quick-start that forced users to hop to the npm README for anything beyond "install and export pleaseai()". Turn it into a real reference so the docs site can stand on its own. New pages: - /eslint-config/frameworks — React, Next.js, Vue, Svelte, Astro, Solid, UnoCSS, Angular with per-integration peer-dep install snippets and per-integration rule override pattern. - /eslint-config/advanced — Config Composer, type-aware rules, eslint-plugin-command codemods, plugin renaming table, view enabled rules, re-exports, versioning policy. - /eslint-config/editor — VS Code settings (with the full rules.customizations block), Neovim patterns, editor-specific disables with motivation, and lint-staged/simple-git-hooks setup. Expanded /eslint-config landing page: - Full PleaseAI Defaults table including lessOpinionated rationale - Rules Overrides subsection showing per-integration overrides - Formatters section for eslint-plugin-format - Type Aware Rules teaser with link to advanced page - Next Steps card grid pointing at the four subpages - FAQ expanded: Prettier?, How do I format CSS?, Curly braces style?, Top-level function style? - CLI tip callout linking to /cli for hands-off setup The trailing examples for `/// to-function` and the curly-braces "wrong" snippet are marked with `<!-- eslint-skip -->` so our own command plugin and curly rule don't try to auto-fix the documentation illustrations.
1 parent 12f4ed5 commit 01bc596

4 files changed

Lines changed: 703 additions & 50 deletions

File tree

docs/content/1.eslint-config/1.index.md

Lines changed: 185 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
---
22
title: ESLint Config
3-
description: Opinionated ESLint flat config for PleaseAI projects.
3+
description: Opinionated ESLint flat config for PleaseAI projects — built on @antfu/eslint-config.
44
navigation:
55
icon: i-lucide-shield-check
66
---
77

88
# ESLint Config
99

10-
`@pleaseai/eslint-config` is an opinionated ESLint flat config built on top of [`@antfu/eslint-config`](https://github.com/antfu/eslint-config).
10+
`@pleaseai/eslint-config` is an opinionated ESLint flat config built on top of [`@antfu/eslint-config`](https://github.com/antfu/eslint-config). It gives you a single `pleaseai()` function that wires up linting **and formatting** for JS/TS/JSX/Vue/JSON/YAML/Markdown out of the box — no Prettier required.
1111

1212
## Features
1313

14-
- ESLint flat config format
15-
- Single quotes, no semicolons, 2-space indent
16-
- TypeScript support out of the box
14+
- [ESLint flat config](https://eslint.org/docs/latest/use/configure/configuration-files-new) format, composable and future-proof
15+
- Auto-fix for formatting — **use standalone without Prettier**
16+
- TypeScript, JSX, Vue, JSON, YAML, Markdown, TOML, XML, GraphQL, Svelte, Astro, CSS support
17+
- Optional [React, Next.js, Svelte, UnoCSS, Astro, Solid, Angular](/eslint-config/frameworks) integrations
18+
- Optional [formatters](#formatters) for CSS / HTML / Markdown via `eslint-plugin-format`
19+
- Includes [`eslint-plugin-package-json`](/eslint-config/package-json) configs
1720
- Auto-detects `.gitignore` patterns
18-
- Re-exports all `@antfu/eslint-config` utilities
21+
- Requires ESLint v9.10.0+
1922

2023
## Installation
2124

@@ -33,33 +36,51 @@ npm install -D @pleaseai/eslint-config eslint
3336
```
3437
:::
3538

39+
::tip{to="/cli"}
40+
Prefer not to set this up by hand? Run `bunx @pleaseai/code-style` — the CLI installs the packages, writes `eslint.config.mjs`, and can also manage a rules block in `AGENTS.md` for AI coding assistants.
41+
::
42+
3643
## Usage
3744

38-
Create an `eslint.config.ts` (or `eslint.config.mjs`) in your project root:
45+
Create `eslint.config.ts` (or `eslint.config.mjs`) in your project root:
3946

4047
```ts [eslint.config.ts]
4148
import pleaseai from '@pleaseai/eslint-config'
4249

4350
export default pleaseai()
4451
```
4552

53+
That's it. ESLint will pick it up automatically on the next run.
54+
4655
### With Options
4756

48-
The `pleaseai()` function accepts the same options as `@antfu/eslint-config`:
57+
`pleaseai()` accepts the same options as `@antfu/eslint-config`:
4958

5059
```ts [eslint.config.ts]
5160
import pleaseai from '@pleaseai/eslint-config'
5261

5362
export default pleaseai({
63+
// Override PleaseAI defaults
64+
stylistic: {
65+
indent: 4,
66+
},
67+
68+
// Enable framework support
5469
vue: true,
5570
react: true,
56-
// Override any @antfu/eslint-config option
71+
72+
// Add ignores
73+
ignores: [
74+
'**/fixtures',
75+
],
5776
})
5877
```
5978

79+
See [Framework Integrations](/eslint-config/frameworks) for the full list of framework flags and their peer dependencies.
80+
6081
### With Additional Configs
6182

62-
You can pass additional flat config items as rest arguments:
83+
Pass additional flat config items as rest arguments — they're merged after the PleaseAI preset:
6384

6485
```ts [eslint.config.ts]
6586
import pleaseai from '@pleaseai/eslint-config'
@@ -69,35 +90,44 @@ export default pleaseai(
6990
typescript: true,
7091
},
7192
{
93+
files: ['**/*.ts'],
7294
rules: {
7395
'no-console': 'warn',
7496
},
7597
},
7698
)
7799
```
78100

79-
### Config Composer
101+
### Rules Overrides
80102

81-
`pleaseai()` returns a [`FlatConfigComposer`](https://github.com/antfu/eslint-flat-config-utils#composer), so you can fluently override, prepend, or remove named config blocks when the plain options object isn't granular enough:
103+
Every framework integration accepts an `overrides` object so you can tune rules without replacing the whole preset:
82104

83105
```ts [eslint.config.ts]
84106
import pleaseai from '@pleaseai/eslint-config'
85107

86-
export default pleaseai()
87-
.override('antfu/stylistic/rules', {
88-
rules: {
89-
'style/generator-star-spacing': ['error', { after: true, before: false }],
108+
export default pleaseai({
109+
vue: {
110+
overrides: {
111+
'vue/operator-linebreak': ['error', 'before'],
112+
},
113+
},
114+
typescript: {
115+
overrides: {
116+
'ts/consistent-type-definitions': ['error', 'interface'],
90117
},
91-
})
92-
.renamePlugins({
93-
'old-prefix': 'new-prefix',
94-
})
95-
.remove('antfu/stylistic')
118+
},
119+
})
96120
```
97121

122+
For overrides that don't fit a specific integration, pass a second argument with a `rules` object as shown in [With Additional Configs](#with-additional-configs).
123+
124+
::note{to="/eslint-config/advanced#plugins-renaming"}
125+
Plugin prefixes are renamed for ergonomics — use `ts/*`, `style/*`, `test/*`, `import/*`, etc. See the full mapping in Advanced Usage.
126+
::
127+
98128
## NPM Scripts
99129

100-
Add the lint commands to your `package.json` script section:
130+
Add the lint commands to your `package.json`:
101131

102132
```json [package.json]
103133
{
@@ -108,46 +138,164 @@ Add the lint commands to your `package.json` script section:
108138
}
109139
```
110140

111-
Run `npm run lint` to check if the code style is correct, or `npm run lint:fix` to automatically fix issues.
141+
Run `npm run lint` to check, or `npm run lint:fix` to auto-fix.
142+
143+
## PleaseAI Defaults
144+
145+
This config wraps `@antfu/eslint-config` with these PleaseAI-specific defaults:
146+
147+
| Option | Value | Note |
148+
| --- | --- | --- |
149+
| `stylistic.indent` | `2` | Two-space indent |
150+
| `stylistic.quotes` | `single` | Single quotes |
151+
| `stylistic.semi` | `false` | No trailing semicolons |
152+
| `typescript` | `true` | Enabled out of the box |
153+
| `gitignore` | `true` | Ignores anything in `.gitignore` |
154+
| `lessOpinionated` | `true` | Disables `antfu/if-newline` and `antfu/curly`, enables `curly: ['error', 'all']` |
155+
| `antfu/top-level-function` | Re-enabled | Prefer `function` declarations at top level |
156+
| `test/prefer-lowercase-title` | Disabled | Test titles can start with any case |
157+
158+
The `lessOpinionated: true` + `curly: ['error', 'all']` combination is the key PleaseAI divergence from antfu's defaults: control-flow statements must always use braces, but antfu's top-level-function preference is still honoured.
159+
160+
## Formatters
161+
162+
ESLint can't natively format `.css`, `.html`, `.xml`, or Markdown frontmatter. Opt in to the `formatters` feature to delegate those files to [`eslint-plugin-format`](https://github.com/antfu/eslint-plugin-format) (which wraps Prettier / dprint) while keeping everything else on pure ESLint:
163+
164+
```ts [eslint.config.ts]
165+
import pleaseai from '@pleaseai/eslint-config'
166+
167+
export default pleaseai({
168+
formatters: {
169+
css: true,
170+
html: true,
171+
markdown: 'prettier',
172+
},
173+
})
174+
```
175+
176+
:::code-group
177+
```bash [bun]
178+
bun add -D eslint-plugin-format
179+
```
112180

113-
## Defaults
181+
```bash [pnpm]
182+
pnpm add -D eslint-plugin-format
183+
```
114184

115-
| Option | Value |
116-
|--------|-------|
117-
| `indent` | `2` (spaces) |
118-
| `quotes` | `single` |
119-
| `semi` | `false` |
120-
| `typescript` | `true` |
121-
| `gitignore` | `true` |
185+
```bash [npm]
186+
npm install -D eslint-plugin-format
187+
```
188+
:::
122189

123-
## Editor Specific Disables
190+
::note
191+
`formatters` only handles formatting, not linting. For proper CSS **linting** use [Stylelint](https://stylelint.io/) alongside it.
192+
::
124193

125-
When ESLint runs inside a code editor, a handful of rules (`prefer-const`, `unused-imports/no-unused-imports`, `test/no-only-tests`, several `pnpm/*` rules) report as non-fixable so your editor doesn't aggressively rewrite code you're still typing. The same rules apply normally when you run `eslint` in the terminal or through a pre-commit hook, so nothing slips through.
194+
## Type Aware Rules
126195

127-
If you want editor and CLI to behave identically, opt out:
196+
The strongest TypeScript rules require type information. Opt in by pointing at your `tsconfig.json`:
128197

129198
```ts [eslint.config.ts]
130199
import pleaseai from '@pleaseai/eslint-config'
131200

132201
export default pleaseai({
133-
isInEditor: false,
202+
typescript: {
203+
tsconfigPath: 'tsconfig.json',
204+
},
134205
})
135206
```
136207

208+
Read more in [Advanced Usage → Type Aware Rules](/eslint-config/advanced#type-aware-rules).
209+
210+
## Next Steps
211+
212+
::card-group
213+
::card
214+
---
215+
title: Framework Integrations
216+
icon: i-lucide-package
217+
to: /eslint-config/frameworks
218+
---
219+
React, Next.js, Vue, Svelte, Astro, Solid, UnoCSS, and Angular — with peer deps.
220+
::
221+
222+
::card
223+
---
224+
title: Advanced Usage
225+
icon: i-lucide-settings-2
226+
to: /eslint-config/advanced
227+
---
228+
Config Composer, `command` codemods, plugin renaming, versioning policy.
229+
::
230+
231+
::card
232+
---
233+
title: Editor & CI
234+
icon: i-lucide-monitor
235+
to: /eslint-config/editor
236+
---
237+
VS Code, Neovim, editor-specific disables, and lint-staged.
238+
::
239+
240+
::card
241+
---
242+
title: Nuxt Integration
243+
icon: i-lucide-mountain
244+
to: /eslint-config/nuxt
245+
---
246+
Compose with `@nuxt/eslint` for auto-import-aware linting.
247+
::
248+
::
249+
137250
## FAQ
138251

252+
### Prettier?
253+
254+
This config uses ESLint for both linting **and** formatting, so Prettier isn't needed. See [Why I don't use Prettier](https://antfu.me/posts/why-not-prettier) by Anthony Fu for the reasoning.
255+
256+
If you need to format files ESLint can't handle yet (`.css`, `.html`, etc.), use the [formatters](#formatters) option — it wraps Prettier/dprint under the hood without adding a separate tool to your workflow.
257+
258+
### How do I format CSS?
259+
260+
Opt in to the [`formatters`](#formatters) feature. It formats but does not lint — for proper CSS linting pair it with [Stylelint](https://stylelint.io/).
261+
262+
### Curly braces style?
263+
264+
PleaseAI enforces `curly: ['error', 'all']` — always wrap control-flow bodies in braces:
265+
266+
<!-- eslint-skip -->
267+
268+
```ts
269+
// ✓ required
270+
function example() {
271+
if (foo) {
272+
return true
273+
}
274+
}
275+
276+
// ✗ rejected
277+
function example() {
278+
if (foo) return true
279+
}
280+
```
281+
282+
This diverges from antfu's default (which allows brace-less single-line `if`). We made this choice because brace-less bodies interact badly with our other rules like `style/max-statements-per-line` — mixing them produces hard-to-read one-liners.
283+
139284
### Top-level function style?
140285

141-
PleaseAI re-enables `antfu/top-level-function`, so top-level functions should use a `function` declaration rather than an arrow assigned to a `const`. Arrow functions are still fine inside function bodies, as callbacks, or for inline JSX handlers — the rule only targets top-level declarations.
286+
PleaseAI re-enables `antfu/top-level-function`, so top-level functions should use a `function` declaration rather than an arrow assigned to a `const`:
142287

143288
```ts
144289
// ✓ preferred
145290
export function greet(name: string) {
146291
return `Hello, ${name}`
147292
}
293+
294+
// ✗ flagged
295+
export const greet = (name: string) => `Hello, ${name}`
148296
```
149297

150-
Override it if you disagree:
298+
Arrow functions are still fine inside function bodies, as callbacks, or for inline JSX handlers — the rule only targets top-level declarations. If you disagree, override it:
151299

152300
```ts [eslint.config.ts]
153301
import pleaseai from '@pleaseai/eslint-config'
@@ -158,16 +306,3 @@ export default pleaseai({
158306
},
159307
})
160308
```
161-
162-
## VS Code Integration
163-
164-
Install the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) and add to your `.vscode/settings.json`:
165-
166-
```json [.vscode/settings.json]
167-
{
168-
"eslint.format.enable": true,
169-
"editor.codeActionsOnSave": {
170-
"source.fixAll.eslint": "explicit"
171-
}
172-
}
173-
```

0 commit comments

Comments
 (0)