Skip to content

Commit ac90468

Browse files
committed
docs(eslint-config): supplement README from antfu upstream
Close the gap between @antfu/eslint-config's README and ours by porting five sections that were missing: - Config Composer: fluent .override() / .renamePlugins() / .remove() API for when the plain pleaseai({...}) options aren't granular enough. - Optional Rules — command: document eslint-plugin-command triple-slash codemods (/// to-function, /// keep-sorted, ...) that ship with the config. Marked the example with <!-- eslint-skip --> so our own lint doesn't try to transform it. - Neovim integration: nvim-lspconfig, conform.nvim, none-ls, nvim-lint patterns for format-on-save alongside the existing VS Code section. - Editor Specific Disables: explain isInEditor behaviour for prefer-const, unused-imports, test/no-only-tests and the pnpm/* rules — a common source of "why does it behave differently in my editor" confusion. - Versioning Policy: Node/major refactors are breaking, rule changes are not. Matches the policy inherited from @antfu/eslint-config. Also added a "Top-level function style?" FAQ entry since PleaseAI re-enables antfu/top-level-function and users hit this every time they write an export const arrow function.
1 parent 61af8d5 commit ac90468

1 file changed

Lines changed: 154 additions & 0 deletions

File tree

packages/eslint-config/README.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,37 @@ export default pleaseai(
102102
)
103103
```
104104

105+
### Config Composer
106+
107+
The factory function `pleaseai()` returns a [`FlatConfigComposer` object from `eslint-flat-config-utils`](https://github.com/antfu/eslint-flat-config-utils#composer), so you can chain methods to compose the config even more flexibly:
108+
109+
```js
110+
import pleaseai from '@pleaseai/eslint-config'
111+
112+
export default pleaseai()
113+
.prepend(
114+
// some flat configs before the main config
115+
)
116+
// override any named config block
117+
.override(
118+
'antfu/stylistic/rules',
119+
{
120+
rules: {
121+
'style/generator-star-spacing': ['error', { after: true, before: false }],
122+
},
123+
},
124+
)
125+
// rename plugin prefixes
126+
.renamePlugins({
127+
'old-prefix': 'new-prefix',
128+
// ...
129+
})
130+
// remove a named config block entirely
131+
.remove('antfu/stylistic')
132+
```
133+
134+
This is the composable escape-hatch when the plain `pleaseai({ ... })` options are not granular enough.
135+
105136
### Rules Overrides
106137

107138
Use the `overrides` option in each integration:
@@ -249,6 +280,40 @@ export default pleaseai({
249280
bun add -D @angular-eslint/eslint-plugin @angular-eslint/eslint-plugin-template @angular-eslint/template-parser
250281
```
251282

283+
### Optional Rules — `command`
284+
285+
`@antfu/eslint-config` ships with [`eslint-plugin-command`](https://github.com/antfu/eslint-plugin-command), which `@pleaseai/eslint-config` inherits. It is **not** a typical lint rule — it's an on-demand micro-codemod that triggers on specific triple-slash comments.
286+
287+
A few built-in triggers:
288+
289+
- `/// to-function` — converts an arrow function to a `function` declaration
290+
- `/// to-arrow` — converts a `function` declaration to an arrow function
291+
- `/// to-for-each` — converts a `for`-loop to `.forEach()`
292+
- `/// to-for-of` — converts a `.forEach()` to a `for-of`
293+
- `/// keep-sorted` — sorts the next object/array/interface
294+
- …see the [plugin docs](https://github.com/antfu/eslint-plugin-command#built-in-commands) for the full list
295+
296+
Place the trigger one line above the code you want to transform:
297+
298+
<!-- eslint-skip -->
299+
300+
```ts
301+
/// to-function
302+
const foo = async (msg: string): Promise<void> => {
303+
console.log(msg)
304+
}
305+
```
306+
307+
On the next `eslint --fix` (or auto-fix-on-save) it becomes:
308+
309+
```ts
310+
async function foo(msg: string): Promise<void> {
311+
console.log(msg)
312+
}
313+
```
314+
315+
The trigger comment is one-off — it's removed along with the transformation.
316+
252317
### Formatters
253318

254319
Use external formatters for files that ESLint cannot handle yet (`.css`, `.html`, etc):
@@ -339,6 +404,50 @@ Install [VS Code ESLint extension](https://marketplace.visualstudio.com/items?it
339404
}
340405
```
341406

407+
### Neovim
408+
409+
A few ways to get format-on-save in Neovim:
410+
411+
- **`nvim-lspconfig`** exposes an `EslintFixAll` command. Create an autocmd that runs it on `BufWritePre`:
412+
413+
```lua
414+
lspconfig.eslint.setup({
415+
on_attach = function(client, bufnr)
416+
vim.api.nvim_create_autocmd('BufWritePre', {
417+
buffer = bufnr,
418+
command = 'EslintFixAll',
419+
})
420+
end,
421+
})
422+
```
423+
424+
- [`conform.nvim`](https://github.com/stevearc/conform.nvim)
425+
- [`none-ls.nvim`](https://github.com/nvimtools/none-ls.nvim)
426+
- [`nvim-lint`](https://github.com/mfussenegger/nvim-lint)
427+
428+
### Editor Specific Disables
429+
430+
When ESLint runs inside a code editor, a handful of rules are **disabled for auto-fix** so the editor doesn't aggressively rewrite code you're still typing:
431+
432+
- [`prefer-const`](https://eslint.org/docs/rules/prefer-const)
433+
- [`test/no-only-tests`](https://github.com/levibuzolic/eslint-plugin-no-only-tests)
434+
- [`unused-imports/no-unused-imports`](https://www.npmjs.com/package/eslint-plugin-unused-imports)
435+
- `pnpm/json-enforce-catalog`
436+
- `pnpm/json-prefer-workspace-settings`
437+
- `pnpm/json-valid-catalog`
438+
439+
> Since `@antfu/eslint-config` v3.16.0 these rules are not disabled — they're made **non-fixable** in editor mode. They still report, just without a quick-fix action.
440+
441+
Motivation: an unused import you just pasted shouldn't vanish the moment your editor auto-saves. The rules still apply when you run `eslint` in the terminal or through [Lint Staged](#lint-staged). If you prefer the uniform behaviour across editor and CLI, opt out:
442+
443+
```js
444+
import pleaseai from '@pleaseai/eslint-config'
445+
446+
export default pleaseai({
447+
isInEditor: false,
448+
})
449+
```
450+
342451
### Lint Staged
343452

344453
```json
@@ -378,6 +487,25 @@ This config inherits `@antfu/eslint-config`'s plugin renaming for a consistent D
378487
| `style/*` | `@stylistic/*` | [@stylistic/eslint-plugin](https://github.com/eslint-stylistic/eslint-stylistic) |
379488
| `test/*` | `vitest/*` | [@vitest/eslint-plugin](https://github.com/vitest-dev/eslint-plugin-vitest) |
380489

490+
## Versioning Policy
491+
492+
`@pleaseai/eslint-config` follows [Semantic Versioning](https://semver.org/), but because it's an opinionated style preset with many moving parts, **rule changes are not treated as breaking changes**. The tables below match the policy inherited from `@antfu/eslint-config`.
493+
494+
### Considered breaking
495+
496+
- Node.js version requirement changes
497+
- Large refactors that may break downstream configs
498+
- Major plugin upgrades that may break existing rules
499+
- Changes that likely affect most codebases
500+
501+
### Considered non-breaking
502+
503+
- Enabling/disabling individual rules or plugins (even if stricter)
504+
- Changing rule options
505+
- Dependency version bumps
506+
507+
If a rule tightening breaks your lint, pin to a previous minor version and open an issue so we can discuss the trade-off.
508+
381509
## FAQ
382510

383511
### Prettier?
@@ -390,6 +518,32 @@ If you need to format files that ESLint cannot handle yet (`.css`, `.html`, etc.
390518

391519
You can opt-in to the [`formatters`](#formatters) feature to format your CSS. Note that it only does formatting, not linting. If you want proper linting support, give [`stylelint`](https://stylelint.io/) a try.
392520

521+
### Top-level function style?
522+
523+
PleaseAI re-enables `antfu/top-level-function` on top of `lessOpinionated: true`, so top-level functions should use a `function` declaration rather than an arrow assigned to a `const`:
524+
525+
```ts
526+
// ✓ preferred
527+
export function greet(name: string) {
528+
return `Hello, ${name}`
529+
}
530+
531+
// ✗ flagged
532+
export const greet = (name: string) => `Hello, ${name}`
533+
```
534+
535+
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 with this choice, override it:
536+
537+
```ts
538+
import pleaseai from '@pleaseai/eslint-config'
539+
540+
export default pleaseai({
541+
rules: {
542+
'antfu/top-level-function': 'off',
543+
},
544+
})
545+
```
546+
393547
### Curly braces style?
394548

395549
PleaseAI defaults to `lessOpinionated: true`, which enforces `curly: ['error', 'all']` — always require braces around control flow bodies:

0 commit comments

Comments
 (0)