Skip to content

Commit

Permalink
feat: allow flexible rules customization
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Mar 27, 2024
1 parent b018319 commit 6bbc357
Show file tree
Hide file tree
Showing 14 changed files with 97 additions and 55 deletions.
25 changes: 25 additions & 0 deletions docs/content/1.packages/0.module.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,31 @@ export default defineNuxtConfig({

Learn more about all the available options in the [ESLint Stylistic documentation](https://eslint.style/guide/config-presets#configuration-factory).

### Config Customizations

`withNuxt()` returns a chainable [`FlatConfigPipeline` instance](https://github.com/antfu/eslint-flat-config-utils#pipe) from [`eslint-flat-config-utils`](https://github.com/antfu/eslint-flat-config-utils) which allows you to manipulate the ESLint flat config with ease.

```ts [eslint.config.mjs]
import withNuxt from './.nuxt/eslint.config.mjs'

export default withNuxt(
// ...Custom flat configs append after nuxt's configs
)
.prepend(
// ...Prepend some flat configs in front
)
// Override some rules in a specific config, based on their name
.override('nuxt:typescript', {
rules: {
// ...Override rules, for example:
'@typescript-eslint/ban-types': 'off'
}
})
// ...you can chain more operations as needed
```

You can learn more about the options available with the types can JSDocs of the instance.

### Dev Server Checker

Usually you don't need this setting as most IDEs are capable of running ESLint directly to inform you of issues. It's also possible to set up a [pre-commit hook with `lint-staged`](https://github.com/lint-staged/lint-staged) to guard your codebase before committing.
Expand Down
43 changes: 21 additions & 22 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
// @ts-check
import { createConfigForNuxt, defineFlatConfigs } from '@nuxt/eslint-config/flat'
import { createConfigForNuxt } from '@nuxt/eslint-config/flat'

export default defineFlatConfigs(
export default createConfigForNuxt({
features: {
stylistic: true,
},
dirs: {
src: 'playground',
pages: [
'playground/pages',
'docs/pages',
],
layouts: [
'playground/layouts',
'docs/layouts',
],
components: [
'playground/components',
'docs/components',
],
},
}).append(
{
ignores: [
'packages-legacy/**',
],
},
createConfigForNuxt({
features: {
stylistic: true,
},
dirs: {
src: 'playground',
pages: [
'playground/pages',
'docs/pages',
],
layouts: [
'playground/layouts',
'docs/layouts',
],
components: [
'playground/components',
'docs/components',
],
},
}),
{
files: ['docs/**/*.vue'],
rules: {
Expand Down
1 change: 1 addition & 0 deletions packages/eslint-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"eslint-plugin-vue": "^9.24.0",
"globals": "^15.0.0",
"pathe": "^1.1.2",
"eslint-flat-config-utils": "^0.1.0",
"vue-eslint-parser": "^9.4.2"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-config/src/flat/configs/base.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FlatConfig } from '../types'
import type { FlatConfigItem } from 'eslint-flat-config-utils'

export default function base(): FlatConfig[] {
export default function base(): FlatConfigItem[] {
return [
{
ignores: [
Expand Down
7 changes: 4 additions & 3 deletions packages/eslint-config/src/flat/configs/disables.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { join } from 'pathe'
import { GLOB_EXTS } from '../constants'
import type { FlatConfig, NuxtESLintConfigOptions } from '../types'
import type { NuxtESLintConfigOptions } from '../types'
import { FlatConfigItem } from 'eslint-flat-config-utils'

export default function disables(options: NuxtESLintConfigOptions): FlatConfig[] {
export default function disables(options: NuxtESLintConfigOptions): FlatConfigItem[] {
const dirs = options.dirs ?? {}
const nestedGlobPattern = `**/*.${GLOB_EXTS}`

Expand All @@ -21,7 +22,7 @@ export default function disables(options: NuxtESLintConfigOptions): FlatConfig[]
...(dirs.components?.map(componentsDir => join(componentsDir, '*', nestedGlobPattern)) || []),
]

const configs: FlatConfig[] = []
const configs: FlatConfigItem[] = []

if (fileRoutes.length) {
configs.push({
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-config/src/flat/configs/javascript.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// @ts-expect-error missing types
import pluginESLint from '@eslint/js'
import type { Linter } from 'eslint'
import { FlatConfigItem } from 'eslint-flat-config-utils'
import globals from 'globals'

export default function javascript(): Linter.FlatConfig[] {
export default function javascript(): FlatConfigItem[] {
return [
{
name: 'nuxt:javascript',
Expand Down
7 changes: 4 additions & 3 deletions packages/eslint-config/src/flat/configs/nuxt.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { join } from 'pathe'
import type { FlatConfig, NuxtESLintConfigOptions } from '../types'
import type { NuxtESLintConfigOptions } from '../types'
import nuxtPlugin from '@nuxt/eslint-plugin'
import { GLOB_EXTS } from '../constants'
import { FlatConfigItem } from 'eslint-flat-config-utils'

export default function nuxt(options: NuxtESLintConfigOptions): FlatConfig[] {
export default function nuxt(options: NuxtESLintConfigOptions): FlatConfigItem[] {
const dirs = options.dirs ?? {}

const fileSingleRoot = [
...(dirs.layouts?.map(layoutsDir => join(layoutsDir, `**/*.${GLOB_EXTS}`)) || []),
...(dirs.pages?.map(pagesDir => join(pagesDir, `**/*.${GLOB_EXTS}`)) || []),
]

const configs: FlatConfig[] = [
const configs: FlatConfigItem[] = [
{
name: 'nuxt:rules',
plugins: {
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-config/src/flat/configs/typescript.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as parserTs from '@typescript-eslint/parser'
import pluginTs from '@typescript-eslint/eslint-plugin'
import { FlatConfig } from '../types'
import { FlatConfigItem } from 'eslint-flat-config-utils'

export default function typescript(): FlatConfig[] {
export default function typescript(): FlatConfigItem[] {
return [
{
name: 'nuxt:setup:typescript',
Expand Down
5 changes: 3 additions & 2 deletions packages/eslint-config/src/flat/configs/vue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import * as parserTs from '@typescript-eslint/parser'

// @ts-expect-error missing types
import pluginVue from 'eslint-plugin-vue'
import { FlatConfig, NuxtESLintConfigOptions } from '../types'
import { NuxtESLintConfigOptions } from '../types'
import { removeUndefined } from '../utils'
import { FlatConfigItem } from 'eslint-flat-config-utils'

export default function vue(options: NuxtESLintConfigOptions): FlatConfig[] {
export default function vue(options: NuxtESLintConfigOptions): FlatConfigItem[] {
return [
{
name: 'nuxt:setup-vue',
Expand Down
31 changes: 19 additions & 12 deletions packages/eslint-config/src/flat/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { Awaitable, FlatConfig, NuxtESLintConfigOptions } from './types'
import type { Awaitable, NuxtESLintConfigOptions } from './types'
import disables from './configs/disables'
import nuxt from './configs/nuxt'
import base from './configs/base'
import javascript from './configs/javascript'
import typescript from './configs/typescript'
import vue from './configs/vue'
import stylistic from './configs/stylistic'
import { pipe, FlatConfigPipeline, FlatConfigItem } from 'eslint-flat-config-utils'

export * from './types'

Expand All @@ -15,7 +16,7 @@ export * from './types'
* This function takes flat config item, or an array of them as rest arguments.
* It also automatically resolves the promise if the config item is a promise.
*/
export async function defineFlatConfigs(...configs: Awaitable<FlatConfig | FlatConfig[]>[]): Promise<FlatConfig[]> {
export async function defineFlatConfigs(...configs: Awaitable<FlatConfigItem | FlatConfigItem[]>[]): Promise<FlatConfigItem[]> {
const resolved = await Promise.all(configs)
return resolved.flat()
}
Expand All @@ -27,22 +28,28 @@ export async function defineFlatConfigs(...configs: Awaitable<FlatConfig | FlatC
*
* @see https://eslint.nuxt.com/packages/module
*/
export async function createConfigForNuxt(options: NuxtESLintConfigOptions = {}): Promise<FlatConfig[]> {
const items: FlatConfig[] = []
export function createConfigForNuxt(options: NuxtESLintConfigOptions = {}): FlatConfigPipeline<FlatConfigItem> {
const pipeline = pipe()

if (options.features?.standalone !== false) {
items.push(...base())
items.push(...javascript())
items.push(...typescript())
items.push(...vue(options))
pipeline.append(
base(),
javascript(),
typescript(),
vue(options),
)
}

if (options.features?.stylistic) {
items.push(stylistic(options.features.stylistic === true ? {} : options.features.stylistic))
pipeline.append(
stylistic(options.features.stylistic === true ? {} : options.features.stylistic),
)
}

items.push(...nuxt(options))
items.push(...disables(options))
pipeline.append(
nuxt(options),
disables(options),
)

return items
return pipeline
}
5 changes: 0 additions & 5 deletions packages/eslint-config/src/flat/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { StylisticCustomizeOptions } from '@stylistic/eslint-plugin'
import type { Linter } from 'eslint'

export interface NuxtESLintFeaturesOptions {
/**
Expand Down Expand Up @@ -76,8 +75,4 @@ export interface NuxtESLintConfigOptions {
}
}

export interface FlatConfig extends Linter.FlatConfig {
name?: string
}

export type Awaitable<T> = T | Promise<T>
1 change: 1 addition & 0 deletions packages/module/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"@nuxt/eslint-plugin": "workspace:*",
"@nuxt/kit": "^3.11.1",
"chokidar": "^3.6.0",
"eslint-flat-config-utils": "^0.1.0",
"eslint-flat-config-viewer": "^0.1.14",
"get-port-please": "^3.1.2",
"pathe": "^1.1.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/module/src/config-addons/globals.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Nuxt } from '@nuxt/schema'
import type { Unimport } from 'unimport'
import type { ESLintConfigGenAddon } from '../types'
import type { FlatConfig } from '@nuxt/eslint-config/flat'
import type { FlatConfigItem } from 'eslint-flat-config-utils'

export function createAddonGlobals(nuxt: Nuxt): ESLintConfigGenAddon {
let unimport: Unimport
Expand All @@ -16,7 +16,7 @@ export function createAddonGlobals(nuxt: Nuxt): ESLintConfigGenAddon {
return {
configs: [
'// Set globals from imports registry\n'
+ JSON.stringify(<FlatConfig>{
+ JSON.stringify(<FlatConfigItem>{
name: 'nuxt:import-globals',
languageOptions: {
globals: Object.fromEntries((await unimport.getImports()).map(i => [i.as || i.name, 'readonly'])),
Expand Down
11 changes: 11 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 6bbc357

Please sign in to comment.