Skip to content

lincenying/eslint-config

Repository files navigation

@lincy/eslint-config Eslint扁平化规则

npm

Thanks to sxzz/eslint-config and antfu/eslint-config for the inspiration and reference.

  • 单引号,无结尾分号
  • 自动格式化
  • 专为与 TypeScript、Vue(2/3)、React 一起使用而设计,开箱即用
  • 也适用于 json、yaml、markdown
  • import导入排序, 对象字⾯量项尾逗号
  • 合理的默认值,最佳实践,只需一行配置
  • ESLint Flat config
  • 使用 ESLint Stylistic
  • 风格原则: 读取最小,差异稳定

Usage

Install

pnpm add -D eslint @lincy/eslint-config

Create config file

// eslint.config.js
import lincy from '@lincy/eslint-config'

export default lincy()

通常您不需要.eslintignore,因为它已由预设提供。

在 package.json 中添加脚本

{
  "scripts": {
    "lint": "eslint .",
    "lint:fix": "eslint . --fix"
  }
}

VS Code support (保存时自动修复)

安装 VS Code ESLint扩展

将以下设置添加到您的“settings.json”:

{
  // 禁用默认的格式化
  "prettier.enable": false,
  "editor.formatOnSave": false,

  // 开启自动修复
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit",
    "source.organizeImports": "never"
  },

  // 在 IDE 中静默样式规则,但仍会自动修复它们
  "eslint.rules.customizations": [
    { "rule": "style/*", "severity": "off" },
    { "rule": "format/*", "severity": "off" },
    { "rule": "*-indent", "severity": "off" },
    { "rule": "*-spacing", "severity": "off" },
    { "rule": "*-spaces", "severity": "off" },
    { "rule": "*-order", "severity": "off" },
    { "rule": "*-dangle", "severity": "off" },
    { "rule": "*-newline", "severity": "off" },
    { "rule": "*quotes", "severity": "off" },
    { "rule": "*semi", "severity": "off" }
  ],

  // 为所有支持的语言启用 eslint
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "vue",
    "html",
    "markdown",
    "json",
    "jsonc",
    "yaml",
    "toml",
    "xml",
    "gql",
    "graphql",
    "css",
    "less",
    "scss",
    "pcss",
    "postcss"
  ]
}

定制化

通常你只需要导入 lincy 预设:

esm

如果 package.json 中开启了"type": "module",

// eslint.config.js
import lincy from '@lincy/eslint-config'

// or
// import { lincy } from '@lincy/eslint-config'

export default lincy()

cjs

如果 package.json 中没有开启"type": "module",

// eslint.config.js
const lincy = require('@lincy/eslint-config').lincy

module.exports = lincy()

您可以单独配置每个功能,例如:

// eslint.config.js
import lincy from '@lincy/eslint-config'

export default lincy({
    /**
     * 是否启用 stylistic 格式化规则
     * @default 默认值: true
     * @example 可选: false |
     * {
     *   indent?: number | 'tab';
     *   quotes?: 'single' | 'double';
     *   jsx?: boolean;
     *   semi?: boolean;
     *   lessOpinionated?: boolean;
     * }
     */
    stylistic: true,
    /**
     * 是否启用 typescript 规则
     * @default 默认值: 检测是否安装typescript依赖,
     * @example 可选: false | true |
     * {
     *   files?: string[], // 自定义 glob 覆盖 “files” 选项
     *   componentExts: string[], // 组件的附加扩展
     *   parserOptions: {};
     *   filesTypeAware: string[],
     *   ignoresTypeAware?: string[],
     *   tsconfigPath?: string,
     *   type: 'app' | 'lib'
     * }
     */
    typescript: true,
    /**
     * 是否启用 vue 规则
     * @default 默认值: 检测是否安装vue依赖,
     * @example 可选: false | true |
     * {
     *   files?: string[]; // 自定义 glob 覆盖 “files” 选项
     *   stylistic: boolean; // 是否开启 stylistic
     *   sfcBlocks: boolean; // 为 Vue SFC 创建虚拟文件以启用 linting
     *   typescript: boolean; // 是否开启 typescript
     * }
     */
    vue: true,
    /**
     * 是否启用 jsx 规则
     * @default 默认值: true,
     * @example 可选: false
     */
    jsx: true,
    /**
     * 是否启用 react 规则
     * @default 默认值: 检测是否安装react依赖,
     * @example 可选: false | true |
     * {
     *   files?: string[], // 自定义 glob 覆盖 “files” 选项
     *   filesTypeAware?: string[], // 应该识别类型的文件的全局模式.
     *   ignoresTypeAware?: string[], // 不应具有类型感知的文件的 Glob 模式
     *   tsconfigPath?: string, // 提供此选项后,将启用类型感知规则
     * }
     */
    react: true,
    /**
     * 是否启用 unocss 规则
     * @default 默认值: false,
     * @example 可选: true |
     * {
     *   attributify?: boolean; // 启用 attributify 支持.
     *   strict?: boolean; // 启用严格模式,抛出有关阻止列表类的错误
     * }
     */
    unocss: true,
    /**
     * 是否启用 jsonc 规则
     * @default 默认值: true,
     * @example 可选: false |
     * {
     *   files?: string[]; // 自定义 glob 覆盖 “files” 选项
     *   stylistic: boolean; // 是否开启 stylistic
     * }
     */
    jsonc: false,
    /**
     * 是否启用 yaml 规则
     * @default 默认值: true,
     * @example 可选: false |
     * {
     *   files?: string[]; // 自定义 glob 覆盖 “files” 选项
     *   stylistic: boolean; // 是否开启 stylistic
     * }
     */
    yaml: false,
    /**
     * 是否启用 toml 规则
     * @default 默认值: false,
     * @example 可选: true |
     * {
     *   files?: string[]; // 自定义 glob 覆盖 “files” 选项
     *   stylistic: boolean; // 是否开启 stylistic
     * }
     */
    toml: false,
    /**
     * 是否启用 .gitignore 文件
     * @default 默认值: true,
     * @example 可选: false | { ignores?: string[] }
     */
    gitignore: false,
    /**
     * 是否启用 test 规则
     * @default 默认值: true,
     * @example 可选: false | { files?: string[] }
     */
    test: false,
    /**
     * 是否启用 markdown 规则
     * @default 默认值: true,
     * @example 可选: false | { files?: string[] }
     */
    markdown: false,
    /**
     * 是否启用 regexp 规则
     * @default 默认值: true,
     * @example 可选: false | { level?: 'error' | 'warn' }
     */
    regexp: true,
    /**
     * 是否启用 formatters 规则
     * @default 默认值: false,
     * @example 可选: true |
     * {
     *   css?: 'prettier' | boolean;
     *   html?: 'prettier' | boolean;
     *   graphql?: 'prettier' | boolean;
     *   markdown?: 'prettier' | 'dprint' | boolean
     * }
     */
    formatters: false,
    /**
     * 覆盖规则
     */
    overrides: {
        ignores: [
            // 忽略的路径/文件
        ],
        javascript: {
            // javascript 规则
        },
        typescript: {
            // typescript 规则
        },
        stylistic: {
            // stylistic 规则
        },
        test: {
            // test 规则
        },
        vue: {
            // vue 规则
        },
        react: {
            // react 规则
        },
        jsonc: {
            // jsonc 规则
        },
        yaml: {
            // yaml 规则
        },
        toml: {
            // toml 规则
        },
        markdown: {
            // markdown 规则
        },
        unocss: {
            // unocss 规则
        },
        comments: {
            // comments 规则
        },
        imports: {
            // imports 规则
        },
        jsdoc: {
            // jsdoc 规则
        },
        node: {
            // node 规则
        },
        perfectionist: {
            // perfectionist 规则
        },
        sort: {
            // sort 规则
        },
        unicorn: {
            // unicorn 规则
        },
        regexp: {
            // regexp 规则
        }
    },

    // 工厂函数第一个参数默认为各规则的开关, 但是也可以作为追加规则使用, 当包含以下键名将会自动整合到一个规则里
    languageOptions: {},
    linterOptions: {},
    processor: {},
    plugins: {},
    rules: [],
    settings: {}
})

lincy 工厂函数还接受任意数量的自定义配置覆盖 下面示例为添加auto-import生成的全局方法

// eslint.config.js
import { readFileSync } from 'node:fs'

import lincy from '@lincy/eslint-config'
import plugin from '@unocss/eslint-plugin'

const autoImport = JSON.parse(readFileSync(new URL('./.eslintrc-auto-import.json', import.meta.url)))

export default lincy(
    {
        // 配置, 参考上一个代码块
        // 启用 unocss
        unocss: true
    },
    // 启用 auto-import 生成的 .eslintrc-auto-import.json
    {
        languageOptions: {
            globals: {
                ...autoImport.globals,
                // 其他 globals
            },
        },
    },
    // 你还可以继续配置多个 ESLint Flat Configs
    {
        files: ['**/*.ts'],
        rules: {
            'perfectionist/sort-objects': 'error',
        },
    },
)

您还可以导入非常细粒度的配置并根据需要组合它们:

点击展开例子
// eslint.config.js
import {
    combine,
    comments,
    disables,
    formatters,
    ignores,
    imports,
    javascript,
    jsdoc,
    jsonc,
    jsx,
    markdown,
    node,
    perfectionist,
    react,
    regexp,
    sortPackageJson,
    sortTsconfig,
    stylistic,
    test,
    toml,
    typescript,
    unicorn,
    unocss,
    vue,
    yaml,
} from '@lincy/eslint-config'

export default combine(
    ignores(),
    javascript(/* Options */),
    comments(),
    disables(),
    formatters(),
    node(),
    jsdoc(),
    imports(),
    unicorn(),
    perfectionist(),
    typescript(/* Options */),
    stylistic(/* Options */),
    vue(),
    react(/* Options */),
    unocss(/* Options */),
    jsonc(),
    jsx(),
    yaml(),
    toml(),
    test(),
    markdown(),
    regexp(),
)

查看 configs 和 [factory](https://github.com/lincenying/eslint-config/blob/main/src/factory.ts)了解更多详细信息。

插件重命名

由于扁平化配置支持显式提供了插件名称,因此我们重命名了一些插件以使它们更加一致并隐藏实现细节。

New Prefix Original Prefix Source Plugin
import/* import-x/* eslint-plugin-import-x
node/* n/* eslint-plugin-n
yaml/* yml/* eslint-plugin-yml
ts/* @typescript-eslint/* @typescript-eslint/eslint-plugin
style/* @stylistic/* @stylistic/eslint-plugin

当您想要覆盖规则或内联禁用它们时,您需要更新到新的前缀:

-// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
+// eslint-disable-next-line ts/consistent-type-definitions
type foo = { bar: 2 }

规则覆盖

某些规则仅在特定文件中启用,例如,“ts/”规则仅在“.ts”文件中启用,“vue/”规则仅在“.vue”文件中启用。 如果要覆盖规则,则需要指定文件扩展名:

// eslint.config.js
import lincy from '@lincy/eslint-config'

export default lincy(
    {
        vue: true,
        jsx: true,
        react: true,
        typescript: true,
        stylistic: true,
        gitignore: true,
        test: true,
        jsonc: true,
        yaml: true,
        markdown: true,
        regexp: true,
        overrides: {}
    },
    {
        // 记得在这里指定文件 glob,否则可能会导致 vue 插件处理非 vue 文件
        files: ['**/*.vue'],
        rules: {
            'vue/operator-linebreak': ['error', 'before'],
        },
    },
    {
        // 如果没有 `files`,它们是所有文件的通用规则
        rules: {
            'style/semi': ['error', 'never'],
        },
    }
)

还可以使用“overrides”选项以使其更容易:

// eslint.config.js
import lincy from '@lincy/eslint-config'

export default lincy({
    stylistic: {
        indent: 4
    },
    overrides: {
        // 覆盖 vue 规则
        vue: {
            'vue/operator-linebreak': ['error', 'before'],
        },
        // 覆盖 react 规则
        react: {
            'react/forbid-component-props': 'error',
        },
        // 覆盖 ts 规则
        typescript: {
            'ts/consistent-type-definitions': ['error', 'interface'],
        },
        // 覆盖 js 规则
        javascript: {
            'no-undef': 'off',
        },
        // 覆盖 stylistic 规则
        stylistic: {
            'antfu/consistent-list-newline': 'error',
        },
        yaml: {},
        jsonc: {},
        markdown: {},
        test: {},
        regexp: {},

        // 追加自定义排除文件(夹)
        ignores: [
            '**/assets',
            '**/static',
        ]
        // ...
    }
})

可选配置

提供了一些可选配置,默认情况下不包含它们的依赖项

Formatters

使用外部格式化程序来格式化 ESLint 无法处理的文件(.css、.html 等)。 由 eslint-plugin-format 提供支持

// eslint.config.js
import lincy from '@lincy/eslint-config'

export default lincy({
    formatters: {
        /**
         * 格式化 CSS、LESS、SCSS 文件,以及 Vue 中的 `<style>` 模块
         * 默认使用 Prettier
         */
        css: true,
        /**
         * 格式化 graphql 文件
         * 默认使用 Prettier
         */
        graphql: true,
        /**
         * 格式化 HTML 文件
         * 默认使用 Prettier
         */
        html: true,
        /**
         * 格式化 Markdown 文件
         * 支持 Prettier 和 dprint
         * 默认使用 Prettier
         */
        markdown: 'prettier',
        /**
         * 格式化 svg 文件
         * 需要安装 @prettier/plugin-xml 插件
         * 默认使用 Prettier
         */
        svg: 'prettier',
        /**
         * 格式化 xml 文件
         * 需要安装 @prettier/plugin-xml 插件
         * 默认使用 Prettier
         */
        xml: 'prettier'
    }
})

运行“npx eslint”会提示您安装所需的依赖项,当然,也可以手动安装它们:

pnpm add eslint-plugin-format -D

React

当检测到依赖安装了react, 则默认开启

运行“npx eslint”会提示您安装所需的依赖项,当然,也可以手动安装它们:

pnpm i -D @eslint-react/eslint-plugin eslint-plugin-react-hooks eslint-plugin-react-refresh

UnoCSS

要启用 UnoCSS 支持,需要显式打开它

// eslint.config.js
import lincy from '@lincy/eslint-config'

export default lincy({
    unocss: true,
})

运行“npx eslint”会提示您安装所需的依赖项,当然,也可以手动安装它们:

pnpm i -D @unocss/eslint-plugin

可选规则

perfectionist (sorting)

这个插件 eslint-plugin-perfectionist 允许你排序对象键名,导入,自动修复等。

安装了插件,但默认情况下没有启用任何规则。

建议使用[configuration comments]单独选择每个文件。(https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1).

/* eslint perfectionist/sort-objects: "error" */
const objectWantedToSort = {
    a: 2,
    b: 1,
    c: 3,
}
/* e slint perfectionist/sort-objects: "off" */

类型感知规则

您可以选择通过将选项对象传递给“typescript”配置来启用类型感知规则

// eslint.config.js
import lincy from '@lincy/eslint-config'

export default lincy({
    typescript: {
        tsconfigPath: 'tsconfig.json',
        // tsconfigPath: ['tsconfig.json'], // 也可以是数组
    },
})

Lint Staged

如果你想在每次提交之前应用 lint 和自动修复,你可以将以下内容添加到你的 package.json 中:

{
  "simple-git-hooks": {
    "pre-commit": "pnpm lint-staged"
  },
  "lint-staged": {
    "*": "eslint --fix"
  }
}

然后

npm i -D lint-staged simple-git-hooks

License

[MIT]