Skip to content

Commit

Permalink
feat(eslint-config): options for typescript, add some snapshot tests
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Mar 29, 2024
1 parent d77ebe7 commit ae2d78a
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 5 deletions.
16 changes: 14 additions & 2 deletions packages/eslint-config/src/flat/configs/typescript.ts
@@ -1,8 +1,18 @@
import * as parserTs from '@typescript-eslint/parser'
import pluginTs from '@typescript-eslint/eslint-plugin'
import type { FlatConfigItem } from 'eslint-flat-config-utils'
import { resolveOptions } from '../utils'
import type { NuxtESLintConfigOptions } from '@nuxt/eslint-config/flat'

export default function typescript(options: NuxtESLintConfigOptions): FlatConfigItem[] {
const resolved = resolveOptions(options)

if (resolved.features.typescript === false) {
return []
}

const tsOptions = resolved.features.typescript === true ? {} : resolved.features.typescript

export default function typescript(): FlatConfigItem[] {
return [
{
name: 'nuxt:typescript:setup',
Expand All @@ -21,7 +31,9 @@ export default function typescript(): FlatConfigItem[] {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...pluginTs.configs['eslint-recommended'].overrides![0].rules as any,
...pluginTs.configs.recommended.rules,
...pluginTs.configs.strict.rules,
...(tsOptions.strict === false
? {}
: pluginTs.configs.strict.rules),

'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: false, prefer: 'type-imports' }],
Expand Down
3 changes: 2 additions & 1 deletion packages/eslint-config/src/flat/configs/vue.ts
Expand Up @@ -9,6 +9,7 @@ import type { FlatConfigItem } from 'eslint-flat-config-utils'

export default function vue(options: NuxtESLintConfigOptions): FlatConfigItem[] {
const resolved = resolveOptions(options)
const hasTs = resolved.features.typescript !== false

return [
{
Expand All @@ -21,7 +22,7 @@ export default function vue(options: NuxtESLintConfigOptions): FlatConfigItem[]
parserOptions: {
ecmaVersion: 'latest',
extraFileExtensions: ['.vue'],
parser: parserTs,
parser: hasTs ? parserTs : undefined,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-config/src/flat/index.ts
Expand Up @@ -41,7 +41,7 @@ export function createConfigForNuxt(options: NuxtESLintConfigOptions = {}): Flat
pipeline.append(
base(),
javascript(),
typescript(),
typescript(resolved),
vue(resolved),
)
}
Expand Down
14 changes: 14 additions & 0 deletions packages/eslint-config/src/flat/types.ts
Expand Up @@ -17,6 +17,20 @@ export interface NuxtESLintFeaturesOptions {
* @default false
*/
stylistic?: boolean | StylisticCustomizeOptions<true>

/**
* Options for TypeScript setup
*
* @default true
*/
typescript?: boolean | {
/**
* Enable strict rules
* @see https://typescript-eslint.io/users/configs#strict
* @default true
*/
strict?: boolean
}
}

export interface NuxtESLintConfigOptions {
Expand Down
3 changes: 2 additions & 1 deletion packages/eslint-config/src/flat/utils.ts
Expand Up @@ -15,7 +15,7 @@ export function resolveOptions(
...config.dirs,
} as NuxtESLintConfigOptionsResolved['dirs']

dirs.root ||= [process.cwd()]
dirs.root ||= ['.']
dirs.src ||= dirs.root
dirs.pages ||= dirs.src.map(src => `${src}/pages`)
dirs.layouts ||= dirs.src.map(src => `${src}/layouts`)
Expand All @@ -30,6 +30,7 @@ export function resolveOptions(
features: {
standalone: true,
stylistic: false,
typescript: true,
...config.features,
},
dirs,
Expand Down
173 changes: 173 additions & 0 deletions packages/eslint-config/test/__snapshots__/flat-compose.test.ts.snap
@@ -0,0 +1,173 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`flat config composition > custom src dirs 1`] = `
[
{
"ignores": [
"**/dist",
"**/node_modules",
"**/.nuxt",
"**/.output",
"**/.vercel",
"**/.netlify",
],
},
{
"name": "nuxt:javascript",
},
{
"name": "nuxt:typescript:setup",
},
{
"files": [
"**/*.ts",
"**/*.tsx",
"**/*.mts",
"**/*.cts",
"**/*.vue",
],
"name": "nuxt:typescript",
},
{
"files": [
"**/*.ts",
"**/*.tsx",
"**/*.mts",
"**/*.cts",
"**/*.vue",
],
"name": "nuxt:typescript:disables",
},
{
"name": "nuxt:vue:setup",
},
{
"files": [
"**/*.vue",
],
"name": "nuxt:vue",
},
{
"name": "nuxt:rules",
},
{
"files": [
"src1/layouts/**/*.{js,ts,jsx,tsx,vue}",
"src2/layouts/**/*.{js,ts,jsx,tsx,vue}",
"src1/pages/**/*.{js,ts,jsx,tsx,vue}",
"src2/pages/**/*.{js,ts,jsx,tsx,vue}",
],
"name": "nuxt:vue:single-root",
},
{
"files": [
"src1/app.{js,ts,jsx,tsx,vue}",
"src1/error.{js,ts,jsx,tsx,vue}",
"src2/app.{js,ts,jsx,tsx,vue}",
"src2/error.{js,ts,jsx,tsx,vue}",
"src1/layouts/**/*.{js,ts,jsx,tsx,vue}",
"src2/layouts/**/*.{js,ts,jsx,tsx,vue}",
"src1/pages/**/*.{js,ts,jsx,tsx,vue}",
"src2/pages/**/*.{js,ts,jsx,tsx,vue}",
"src1/components/*/**/*.{js,ts,jsx,tsx,vue}",
"src2/components/*/**/*.{js,ts,jsx,tsx,vue}",
],
"name": "nuxt:vue:routes:disables",
},
]
`;

exports[`flat config composition > empty 1`] = `
[
{
"ignores": [
"**/dist",
"**/node_modules",
"**/.nuxt",
"**/.output",
"**/.vercel",
"**/.netlify",
],
},
{
"name": "nuxt:javascript",
},
{
"name": "nuxt:typescript:setup",
},
{
"files": [
"**/*.ts",
"**/*.tsx",
"**/*.mts",
"**/*.cts",
"**/*.vue",
],
"name": "nuxt:typescript",
},
{
"files": [
"**/*.ts",
"**/*.tsx",
"**/*.mts",
"**/*.cts",
"**/*.vue",
],
"name": "nuxt:typescript:disables",
},
{
"name": "nuxt:vue:setup",
},
{
"files": [
"**/*.vue",
],
"name": "nuxt:vue",
},
{
"name": "nuxt:rules",
},
{
"files": [
"layouts/**/*.{js,ts,jsx,tsx,vue}",
"pages/**/*.{js,ts,jsx,tsx,vue}",
],
"name": "nuxt:vue:single-root",
},
{
"files": [
"app.{js,ts,jsx,tsx,vue}",
"error.{js,ts,jsx,tsx,vue}",
"layouts/**/*.{js,ts,jsx,tsx,vue}",
"pages/**/*.{js,ts,jsx,tsx,vue}",
"components/*/**/*.{js,ts,jsx,tsx,vue}",
],
"name": "nuxt:vue:routes:disables",
},
]
`;

exports[`flat config composition > non-standalone 1`] = `
[
{
"name": "nuxt:rules",
},
{
"files": [
"layouts/**/*.{js,ts,jsx,tsx,vue}",
"pages/**/*.{js,ts,jsx,tsx,vue}",
],
"name": "nuxt:vue:single-root",
},
{
"files": [
"app.{js,ts,jsx,tsx,vue}",
"error.{js,ts,jsx,tsx,vue}",
"layouts/**/*.{js,ts,jsx,tsx,vue}",
"pages/**/*.{js,ts,jsx,tsx,vue}",
"components/*/**/*.{js,ts,jsx,tsx,vue}",
],
"name": "nuxt:vue:routes:disables",
},
]
`;
46 changes: 46 additions & 0 deletions packages/eslint-config/test/flat-compose.test.ts
@@ -0,0 +1,46 @@
import { describe, expect, it } from 'vitest'
import { createConfigForNuxt } from '../src/flat'
import type { FlatConfigItem } from 'eslint-flat-config-utils'

const cwd = process.cwd()

function getFlatConfigDigest(configs: FlatConfigItem[]) {
return configs.map((config) => {
return JSON.parse(JSON.stringify({
name: config.name,
files: config.files,
ignores: config.ignores,
}).replaceAll(cwd, '<cwd>'))
})
}

describe('flat config composition', () => {
it('empty', async () => {
const configs = await createConfigForNuxt()

expect(getFlatConfigDigest(configs))
.toMatchSnapshot()
})

it('non-standalone', async () => {
const configs = await createConfigForNuxt({
features: {
standalone: false,
},
})

expect(getFlatConfigDigest(configs))
.toMatchSnapshot()
})

it('custom src dirs', async () => {
const configs = await createConfigForNuxt({
dirs: {
src: ['src1', 'src2'],
},
})

expect(getFlatConfigDigest(configs))
.toMatchSnapshot()
})
})

0 comments on commit ae2d78a

Please sign in to comment.