@fohte/eslint-config

中文文档
0.5.3发布于 2026/10/18MITTypeScriptES Module构建来源已验证近 30 天下载 2718

Fohte 的 ESLint 配置

中文使用文档
文档目录15 节
  1. 安装
  2. 使用量
  3. 进口政策
  4. errorHandling 选项
  5. opentelemetry 选项
  6. tailwind 选项
  7. noRawFormElements 选项
  8. shadcn 选项
  9. 内部规则
  10. 发展
  11. 设置
  12. 脚本
  13. 项目结构
  14. 释放进程
  15. 承诺前虎克

@fohte/slint-配置

有TypeScript支持的个人ESLint配置包.

安装

npm install --save-dev @fohte/eslint-config

# Install peer dependencies
npm install --save-dev @eslint-community/eslint-plugin-eslint-comments @typescript-eslint/eslint-plugin @typescript-eslint/parser @vitest/eslint-plugin eslint eslint-config-prettier eslint-plugin-import-x eslint-plugin-simple-import-sort

# Optional: If using TypeScript
npm install --save-dev typescript

# Optional: If using the errorHandling option
npm install --save-dev @ninoseki/eslint-plugin-neverthrow
npm install neverthrow

# Optional: If using the tailwind option
npm install --save-dev eslint-plugin-tailwindcss
npm install tailwindcss

# Optional: If using the shadcn option
npm install --save-dev @shadcn/lint

使用量

eslint.config.js数字 :

import { config } from '@fohte/eslint-config'

// Basic (JS + TypeScript strict rules)
export default config()

// Alternatively, enable type-checked rules
// (strict-type-checked + strict-boolean-expressions):
// export default config({ typescript: { typeChecked: true } })

// Optionally, ban throw/try-catch and enforce neverthrow Result handling
// (requires typescript.typeChecked: true):
// export default config({
//   typescript: { typeChecked: true },
//   errorHandling: {},
// })

// Optionally, ban raw tracer.startSpan()/startActiveSpan() calls that skip context.with():
// export default config({ opentelemetry: { enabled: true } })

// Optionally, ban Tailwind CSS arbitrary values (e.g. `w-[600px]`),
// steering towards design tokens defined in `@theme` instead:
// export default config({
//   tailwind: { cssConfigPath: 'src/index.css' },
// })

// Optionally, enforce shared component styling rules in selected files:
// export default config({
//   shadcn: { files: ['src/**/*.{jsx,tsx}'] },
// })

// Optionally, ban raw form and button elements in selected files:
// export default config({
//   noRawFormElements: {
//     files: ['app/src/**/*.tsx'],
//     ignores: ['app/src/components/ui/**'],
//   },
// })

进口政策

config() 禁止相对进口./foo, (中文(简体) ), ../foo)和 @/* 别名通过 no-restricted-imports,并引导两者走向 节点子路径导入 (单位:千美元)#foo,在 imports 输入 package.json) (中文(简体) ). 这个 @/* 化名只解析 TypeScript/ bundler 级别,所以一个平地节点/tsx 不分享分辨率步骤的运行时间在运行时间失败; # 进口由Node自己的模块解析器自行解决,因此这种失败模式不可能发生.

选择退出(例如,不使用 src/ ,在后缀中覆盖规则 userConfigs 引用到 config()数字 :

export default config(
  {},
  {
    rules: {
      'no-restricted-imports': 'off',
    },
  },
)

errorHandling 选项

要求数 typescript.typeChecked: true,因为 neverthrow/must-use-result 需要类型信息以检测未使用 Result 数值.

启用时, 它对所有人适用两个规则 .ts{,x} 除测试文件外的文件 :

  • no-restricted-syntax: 禁令 throw 财务报告和审定财务报表 try编号 :catch返回 a Result 通过 err()编号 :errAsync() 相反,或使用 ResultAsync.fromPromise() 与丢弃的 API 互通,而无需本地 throw如果外部SDK的以抛出为基础的合同真的不能这样包起来,则添加一个 eslint-disable-next-line 解释为什么:

    // eslint-disable-next-line no-restricted-syntax -- interops with an external SDK's throw-based contract
    try {
      return externalSdkCall()
    } catch (error) {
      return err(error)
    }
    
  • neverthrow/must-use-result: 禁止抛弃a neverthrow Result编号 :ResultAsync 不处理它.

opentelemetry 选项

当启用时, no-restricted-syntax 禁止直接呼叫 tracer.startSpan()编号 :tracer.startActiveSpan() 总计 .ts{,x} 文件,因为两者都能够默默地产生一个无法在孩子执行过程中创建的父跨:

  • startSpan() 绝不单独进入主动语境——孩子的间距(例如在这个间距内发射的HTTP呼叫)将不会被嵌入其中,除非呼叫者明确将周围的代码包裹在其中 context.with(trace.setSpan(context.active(), span), ...)。 。 。 .
  • startActiveSpan()'回调在活动上下文中自动运行,但只用于回调的自身持续时间——将跨度存储到 end() 它后来(例如开始和结束在单独的回调中分拆)从活性上下文中从后期代码运行之前放弃.

这只显示为微量后端中错误的出错跨度,而不是运行时出错. 如果两者都不匹配,则添加一个 eslint-disable-next-line 解释原因.

与 errorHandling,两个选项都配置 no-restricted-syntax ——ESLint的平面配置完全取代了规则的设置(而不是将其合并),当两个配置对象为同一个文件设置了相同的规则时,所以 startSpan编号 :startActiveSpan 选择器合并为 errorHandling是因为 no-restricted-syntax 输入而不是他们自己的配置。 这意味着 opentelemetry 禁用然后共享 errorHandling对测试文件的豁免.

tailwind 选项

cssConfigPath (Tailwind的 CSS 文件路径) @theme (a) 需要指示牌); files 默认为全部 .ts{,x} 文件,但可以缩小(例如单列波中的单个软件包):

export default config({
  tailwind: {
    files: ['web/**/*.ts', 'web/**/*.tsx'], // optional, defaults to all .ts{,x} files
    cssConfigPath: 'web/src/index.css',
  },
})

启用时, 它对给定的规则 files (测试文件除外):

  • tailwindcss/no-arbitrary-value:禁止任意值(例如:. w-[600px](单位:千美元) className编号 :class 属性和类名称函数( c)clsx, (中文(简体) ), cn(见E/CN.4/Sub.2/2002/L.48等)。 向 @theme 在您的 CSS 配置中 :

    @theme {
      --width-panel: 600px;
    }
    
    - <div className="w-[600px]" />
    + <div className="w-panel" />
    
  • no-restricted-syntax数字 : no-arbitrary-value 只检查类属性/功能,所以隐藏在空字符串常数中的括号值(然后插入) className)否则会滑出未被发现. 这个规则也抓住了那个案子.

喜欢 opentelemetry,这个共享其 no-restricted-syntax 条目 errorHandling (和 opentelemetry)而不是悄悄地压倒它,因此所有这三项禁令都在内部共同适用 tailwind.files。自 tailwind.files 范围可以小于 errorHandling编号 :opentelemetry默认( 全部) .ts{,x} 文件,合并发生于 tailwind.files范围: 它外的文件只保留 errorHandling编号 :opentelemetry 禁止 里面的档案可以完全结合.

noRawFormElements 选项

设定 files 以禁止原始 JSX 格式和按钮元素的文档。 测试文件被自动排除; 使用 ignores 用于额外排除,例如共享的UI组件:

export default config({
  noRawFormElements: {
    files: ['app/src/**/*.tsx'],
    ignores: ['app/src/components/ui/**'],
  },
})

这样可以 fohte/no-raw-form-elements,哪个标记小写 <button>, (中文(简体) ), <input>, (中文(简体) ), <select>,以及 <textarea> 元素,并要求您使用共享的 UI 组件. <a> 组件和资本化组件不受影响.

shadcn 选项

安装 @shadcn/lint 0.1.2或以后选择加入。 选择所支持的源文件 files; 测试文件自动排除,以及 ignores 还可增加更多的除外情形:

export default config({
  shadcn: { files: ['src/**/*.{jsx,tsx}'] },
})

这样可以 shadcn/no-restyle, (中文(简体) ), shadcn/no-inline-styles, (中文(简体) ), shadcn/require-static-classes, (中文(简体) ), shadcn/no-unknown-classes,以及 shadcn/no-raw-colors 作为错误. no-restyle 确认从 @fohte/ui 及其子路径,同时允许布局类。 添加线索 userConfigs 条目以覆盖或禁用单个规则。 例如, 禁用 no-restyle 在保存其他规则的同时,允许:

export default config(
  { shadcn: { files: ['src/**/*.{jsx,tsx}'] } },
  {
    files: ['src/components/ui/**'],
    rules: { 'shadcn/no-restyle': 'off' },
  },
)

内部规则

除了上游预设外,这个配置船还装有本地插件(fohte) 用于测试文件和故事书故事文件,并选择用于选择由 noRawFormElements。由内建预设启用的规则设定为 error;需要明确选项或用户配置的规则如下文所记载.

fohte/require-story-name 被注册为 Storybook 故事文件,但默认关闭。 启用后缀 userConfigs 条目 :

export default config(
  {},
  {
    files: ['**/*.stories.tsx'],
    rules: { 'fohte/require-story-name': 'error' },
  },
)
  • fohte/no-inline-object-in-expect (测试文件):旗帜 expect(<object/array literal>).toEqual(...) (和 toStrictEqual 编号 : toMatchObject,包括: await … .resolves 编号 : .rejects 编号 : .not 链条,以及 as const 编号 : satisfies 编号 : ! 被包裹的文字)。 并标出同一字面别名,通过一个在 expect() 电话 直接传递测试中的值, 或将断言分为多个 expect() 打电话.

    // bad
    expect({ result, calls: spy.mock.calls.length }).toEqual({
      result: 'ok',
      calls: 0,
    })
    
    // bad: aliasing the literal through a variable doesn't escape the rule
    const actual = { result, calls: spy.mock.calls.length }
    expect(actual).toEqual({ result: 'ok', calls: 0 })
    
    // good
    expect(result).toBe('ok')
    expect(spy).not.toHaveBeenCalled()
    
  • fohte/no-raw-form-elements (当 noRawFormElements 已配置 : 标记小写 JSX <button>, (中文(简体) ), <input>, (中文(简体) ), <select>,以及 <textarea> 要素。 使用共享的 UI 组件代替 .

  • fohte/no-play-in-stories (故事文件):旗帜 a play 函数和 parameters: { screenshot: { skip: true } } 用于描述一个故事或其元a(默认导出)。 故事应该通过 args编号 :render ; 移动行为断言(单击、输入、, expect 电话) .test.tsx ,使状态成为 play 函数用于通过道具设置(例如打开菜单)取而代之(例如. defaultOpen) (中文(简体) ). 这也针对一个"故事书"VRT设置,在同一个文件中标出两个故事,其截图为字节-同义(通常是一个未被检测到的视觉错误,例如两个状态进行相同的渲染):一个被跳过的故事没有显示截图,这样检查就永远看不到. 由于故事不能定义 play每一个故事的唯一说法就是它的外表 所以 screenshot.skip 总是隐藏着这个发现——解决潜在的视觉重复而不是跳过.

    // bad: play belongs in a .test.tsx file, not the story
    export const Disabled: Story = {
      args: { disabled: true },
      play: async ({ canvasElement }) => {
        await expect(within(canvasElement).getByRole('checkbox')).toBeDisabled()
      },
    }
    
    // good: the state play used to set up is driven by a prop instead
    export const Disabled: Story = {
      args: { disabled: true },
    }
    
  • fohte/require-story-name (故事文件,默认关闭):需要每个导出的对象故事定义自己的 name 属性。 它尊重文字字符串和正则表达式过滤器 includeStories 财务报告和审定财务报表 excludeStories。如果任一过滤器是动态的,则规则会跳过该文件,因为它无法确定导出什么故事本.

发展

设置

# Install dependencies
npm install

# Build TypeScript
npm run build

# Watch mode
npm run watch

脚本

  • npm run build - 编译类型脚本文件
  • npm run watch - 发展观察模式
  • npm run lint - 在源文件中运行 ESLint
  • npm run test - 运行建设和涂抹

项目结构

src/
├── index.ts           # Main export
├── main.ts            # Base ESLint configuration
├── typescript.ts      # TypeScript-specific configuration
├── error-handling.ts  # errorHandling option (throw/try-catch ban, neverthrow enforcement)
├── opentelemetry.ts   # opentelemetry option (startSpan/startActiveSpan ban)
├── no-raw-form-elements.ts # noRawFormElements option (raw JSX element ban)
├── tailwind.ts        # tailwind option (Tailwind arbitrary-value ban)
├── shadcn.ts          # shadcn option (shared component style rules)
└── types/             # Type definitions for untyped packages

释放进程

这个项目使用 请放行 自动发布.

1. 创建特征分支并作出修改

  • 从 master
  • 更改( 承诺信件不需要遵循任何特定格式)

2. 创建 PR并合并为主

  • 推动您的分支并创建 PR
  • 公关标题必须遵循 常规武器委员会数字 :
    • fix: 用于错误修正( patch 释放)
    • feat: 新特性(小于发布)
    • feat!: 或者说 fix!: 用于分解更改(主要发布)
  • 审查后, 合并 PR( 只有平面合并)

3. 自动释放程序

当更改合并为 master,请自动释放:

  • 创建/更新释放 PR
  • 更新软件包中的版本。 json
  • 更新变换
  • 当发布 PR 合并时 :
    • 创建 GitHub 发布和 git 标签
    • 发布到 npm

承诺前虎克

这个项目使用承诺前钩来保证代码质量. 当您执行更改时, 钩会自动运行 .

版本与发布记录

@fohte/eslint-config 共发布 27 个版本,首次发布于 2023/12/24;过去 12 个月发布了 21 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.5.3latest2026/10/1829 天前
0.5.22026/10/041 个月前
0.5.12026/09/251 个月前
0.5.02026/09/152 个月前
0.4.42026/09/072 个月前
0.4.32026/08/302 个月前

关于 @fohte/eslint-config 的常见问题

@fohte/eslint-config 是什么?

Fohte 的 ESLint 配置

如何安装 @fohte/eslint-config?

在项目目录运行 npm install @fohte/eslint-config,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:eslint(^9.0.0 || ^10.0.0)、@vitest/eslint-plugin(^1.0.0)、eslint-config-prettier(^10.0.0)、eslint-plugin-import-x(^4.0.0)、@typescript-eslint/parser(^8.60.0)、@typescript-eslint/eslint-plugin(^8.60.0)、eslint-plugin-simple-import-sort(^13.0.0)、@eslint-community/eslint-plugin-eslint-comments(^4.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@fohte/eslint-config 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@fohte/eslint-config 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@fohte/eslint-config 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.19.0 || >=22.13.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@fohte/eslint-config 可以商用吗?

@fohte/eslint-config 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@fohte/eslint-config 的下载量有多少?

根据 npm 官方下载统计,@fohte/eslint-config 在 2026/10/15 – 2026/11/13 这 30 天内被下载 2,718 次,日均约 91 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@fohte/eslint-config 还在维护吗?

最新版本 0.5.3 发布于 2026/10/18(29 天前);至今共发布 27 个版本,其中过去 12 个月发布了 21 个;首次发布于 2023/12/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。