当前位置: 首页 > news >正文

搭建node脚手架(六) ESLint 功能模块

ESLint 功能模块

目录结构

eslint/
├── index.ts                    # 模块导出入口
├── doEslint.ts                # ESLint 执行器
├── formatESLintResults.ts     # 结果格式化器
├── getESLintConfig.ts         # 配置获取器
└── getESLintConfigType.ts     # 配置类型检测器

1. index.ts - 模块导出入口

功能:统一导出 ESLint 相关功能模块
作用

  • 提供模块的统一访问入口
  • 简化模块导入
  • 封装内部实现细节
    导出内容
  • getESLintConfig - 配置获取
  • formatESLintResults - 结果格式化
  • doESLint - 核心执行功能
代码
export * from './getESLintConfig';
export * from './formatESLintResults';
export * from './doESLint';

2. doEslint.ts - ESLint 执行器

这段代码实现了 ESLint 执行器模块,主要功能是根据配置执行 JavaScript/TypeScript 代码检查,并输出统一格式的结果。

文件收集
  • 当用户指定 options.files 时:筛选出 ESLint 支持的文件扩展名(如 .js.ts 等)
  • 未指定时:使用 fast-glob 在工作目录下查找匹配文件,并排除 ESLINT_IGNORE_PATTERN 中的路径
配置加载
  • 通过 getESLintConfig 动态生成 ESLint 配置对象
  • 支持结合 package.json 和用户自定义配置
代码检查
  • 调用 eslint.lintFiles(files) 对目标文件执行检查
  • 当启用 options.fix 时:自动调用 ESLint.outputFixes(reports) 修复可修复问题
结果格式化
  • 使用 formatESLintResults 将原始 LintResult[] 转换为标准 ScanResult[] 格式
  • 支持 quiet 模式:仅输出错误信息,过滤警告信息
模块定位
  • 输入:扫描选项(ScanOptions + 项目信息 PKG + 配置 Config)
  • 输出:标准化的 ScanResult[](包含错误数、警告数、规则信息等)
  • 作用:在 lint 工具链中负责 JavaScript/TypeScript 代码质量检查
代码
// 引入依赖
import { ESLint } from 'eslint'; // ESLint 核心库
import fg from 'fast-glob'; // 快速文件匹配库
import { extname, join } from 'path'; // 路径处理工具
import { Config, PKG, ScanOptions } from '../../types'; // 类型定义
import { ESLINT_FILE_EXT, ESLINT_IGNORE_PATTERN } from '../../utils/constants'; // ESLint 相关常量
import { formatESLintResults } from './formatESLintResults'; // 格式化 ESLint 结果
import { getESLintConfig } from './getESLintConfig'; // 获取 ESLint 配置// ESLint 执行选项接口,继承扫描选项并添加包信息和配置
export interface DoESLintOptions extends ScanOptions {pkg: PKG; // 项目包信息config?: Config; // 扫描配置
}/*** 执行 ESLint JavaScript/TypeScript 代码检查* 对 JavaScript/TypeScript 文件进行代码质量检查和自动修复* @param options ESLint 执行选项* @returns Promise<ScanResult[]> 检查结果数组*/
export async function doESLint(options: DoESLintOptions) {let files: string[];if (options.files) {// 如果指定了具体文件列表,过滤出 ESLint 支持的文件files = options.files.filter((name) => ESLINT_FILE_EXT.includes(extname(name)));} else {// 如果没有指定文件,则根据文件扩展名模式匹配文件files = await fg(`**/*.{${ESLINT_FILE_EXT.map((t) => t.replace(/^\./, '')).join(',')}}`, {cwd: options.cwd, // 工作目录ignore: ESLINT_IGNORE_PATTERN, // 忽略模式});}// 创建 ESLint 实例并执行检查const eslint = new ESLint(getESLintConfig(options, options.pkg, options.config));const reports = await eslint.lintFiles(files);// 自动修复模式if (options.fix) {// 应用自动修复await ESLint.outputFixes(reports);}// 格式化并返回检查结果return formatESLintResults(reports, options.quiet, eslint);
}

3. getESLintConfig.ts - 配置获取器

功能:智能获取和构建 ESLint 配置
详细功能

  • 配置优先级
    • 用户自定义配置 > 项目配置文件 > package.json > 默认配置
  • 配置文件检测
    • 支持多种格式:.js、.yaml、.yml、.json
    • 自动检测项目根目录
  • 默认配置构建
    • 根据项目类型选择配置
    • 支持 TypeScript、React、Vue、Rax 等框架
  • Prettier 集成
    • 自动添加 prettier 配置
    • 避免规则冲突
  • 忽略文件处理
    • 检测 .eslintignore
    • 支持自定义忽略规则
代码
import { ESLint } from 'eslint';
import fs from 'fs-extra';
import glob from 'glob';
import path from 'path';
import type { Config, PKG, ScanOptions } from '../../types';
import { ESLINT_FILE_EXT } from '../../utils/constants';
import { getESLintConfigType } from './getESLintConfigType';/*** 获取 ESLint 配置*/
export function getESLintConfig(opts: ScanOptions, pkg: PKG, config: Config): ESLint.Options {const { cwd, fix, ignore } = opts;const lintConfig: ESLint.Options = {cwd,fix,ignore,extensions: ESLINT_FILE_EXT,errorOnUnmatchedPattern: false,};if (config.eslintOptions) {// 若用户传入了 eslintOptions,则用用户的Object.assign(lintConfig, config.eslintOptions);} else {// 根据扫描目录下有无lintrc文件,若无则使用默认的 lint 配置const lintConfigFiles = glob.sync('.eslintrc?(.@(js|yaml|yml|json))', { cwd });if (lintConfigFiles.length === 0 && !pkg.eslintConfig) {lintConfig.resolvePluginsRelativeTo = path.resolve(__dirname, '../../');lintConfig.useEslintrc = false;lintConfig.baseConfig = {extends: [getESLintConfigType(cwd, pkg),//  ESLint 不再管格式问题,直接使用 Prettier 进行格式化...(config.enablePrettier ? ['prettier'] : []),],};}// 根据扫描目录下有无lintignore文件,若无则使用默认的 ignore 配置const lintIgnoreFile = path.resolve(cwd, '.eslintignore');if (!fs.existsSync(lintIgnoreFile) && !pkg.eslintIgnore) {lintConfig.ignorePath = path.resolve(__dirname, '../config/_eslintignore.ejs');}}return lintConfig;
}

4. getESLintConfigType.ts - 配置类型检测器

功能:检测项目类型并返回相应配置
详细功能

  • 文件类型检测
    • TypeScript (.ts/.tsx)
    • React (.jsx/.tsx)
    • Vue (.vue)
  • 框架识别
    • React/Vue/Rax/纯 JavaScript
  • 配置路径生成
    • 根据语言和框架类型选择配置
    • 生成 encode-fe-eslint-config 路径
代码
import glob from 'glob';
import type { PKG } from '../../types';/*** 获取 ESLint 配置类型* @param cwd* @param pkg* @returns encode-fe-eslint-config/index* @returns encode-fe-eslint-config/react* @returns encode-fe-eslint-config/typescript/index* @returns encode-fe-eslint-config/typescript/react*/
export function getESLintConfigType(cwd: string, pkg: PKG): string {const tsFiles = glob.sync('./!(node_modules)/**/*.@(ts|tsx)', { cwd });const reactFiles = glob.sync('./!(node_modules)/**/*.@(jsx|tsx)', { cwd });const vueFiles = glob.sync('./!(node_modules)/**/*.vue', { cwd });const dependencies = Object.keys(pkg.dependencies || {});const language = tsFiles.length > 0 ? 'typescript' : '';let dsl = '';// dsl判断if (reactFiles.length > 0 || dependencies.some((name) => /^react(-|$)/.test(name))) {dsl = 'react';} else if (vueFiles.length > 0 || dependencies.some((name) => /^vue(-|$)/.test(name))) {dsl = 'vue';} else if (dependencies.some((name) => /^rax(-|$)/.test(name))) {dsl = 'rax';}return ('encode-fe-eslint-config/' + `${language}/${dsl}`.replace(/\/$/, '/index').replace(/^\//, ''));
}

5. formatESLintResults.ts - 结果格式化器

功能:转换 ESLint 原始结果为统一格式
详细功能

  • 数据转换
    • 转为标准 ScanResult[] 格式
  • 消息处理
    • 静默模式下仅显示错误
    • 提取位置和规则信息
  • 统计功能
    • 错误/警告计数
    • 可修复问题统计
  • 规则元数据
    • 提供规则文档链接
    • 包含可修复性信息
代码
// 引入依赖
import { ESLint } from 'eslint'; // ESLint 类型定义
import type { ScanResult } from '../../types'; // 扫描结果类型/*** 格式化 ESLint 输出结果* 将 ESLint 的原始检查结果转换为统一的扫描结果格式* @param results ESLint 原始检查结果数组* @param quiet 是否静默模式(只显示错误,不显示警告)* @param eslint ESLint 实例,用于获取规则元数据* @returns ScanResult[] 格式化后的扫描结果数组*/
export function formatESLintResults(results: ESLint.LintResult[], quiet: boolean, eslint: ESLint): ScanResult[] {// 获取规则元数据,用于生成规则文档链接const rulesMeta = eslint.getRulesMetaForResults(results);return results// 过滤掉没有错误和警告的文件.filter(({ warningCount, errorCount }) => errorCount || warningCount).map(({filePath,messages,errorCount,warningCount,fixableErrorCount,fixableWarningCount,}) => ({filePath, // 文件路径errorCount, // 错误数量warningCount: quiet ? 0 : warningCount, // 警告数量(静默模式下为0)fixableErrorCount, // 可修复错误数量fixableWarningCount: quiet ? 0 : fixableWarningCount, // 可修复警告数量(静默模式下为0)messages: messages.map(({ line = 0, column = 0, ruleId, message, fatal, severity }) => {return {line, // 行号column, // 列号rule: ruleId, // 规则名称url: rulesMeta[ruleId]?.docs?.url || '', // 规则文档链接message: message.replace(/([^ ])\.$/u, '$1'), // 清理消息末尾的句号errored: fatal || severity === 2, // 是否为错误(fatal 或 severity === 2)};}) // 注意:ruleId 可能为 null,这是 ESLint 的正常行为// 参考:https://eslint.org/docs/developer-guide/nodejs-api.html#-lintmessage-type.filter(({ errored }) => (quiet ? errored : true)), // 静默模式下只显示错误}),);
}

整体工作流程

  1. doESLint.ts 启动检查流程
  2. getESLintConfigType.ts 确定项目类型
  3. getESLintConfig.ts 提供配置
  4. ESLint 引擎执行代码检查
  5. 自动修复可修复问题
  6. formatESLintResults.ts 格式化结果
  7. index.ts 统一导出功能

文章转载自:

http://wCMOqYaN.nkLLb.cn
http://u2mj7gUy.nkLLb.cn
http://jP5bXtur.nkLLb.cn
http://aYv2rxlP.nkLLb.cn
http://0eaavTjA.nkLLb.cn
http://uEF8Yccv.nkLLb.cn
http://ULW9JpBH.nkLLb.cn
http://EkGby1mX.nkLLb.cn
http://uQbIvU2E.nkLLb.cn
http://tI4gyt2d.nkLLb.cn
http://0hCjXxzt.nkLLb.cn
http://s6VcpXYB.nkLLb.cn
http://a3xKoWc5.nkLLb.cn
http://fUrwmwCD.nkLLb.cn
http://RcXNeA1J.nkLLb.cn
http://Qo716KhC.nkLLb.cn
http://V8TCaZox.nkLLb.cn
http://G5OrMa5G.nkLLb.cn
http://viWqUDm0.nkLLb.cn
http://NYkc8jp4.nkLLb.cn
http://7cwc4JPC.nkLLb.cn
http://TgNnkSwL.nkLLb.cn
http://ZpPdMiTD.nkLLb.cn
http://DLuJAH4o.nkLLb.cn
http://N4mkdqtv.nkLLb.cn
http://wRDuxAwS.nkLLb.cn
http://bZY7AE2W.nkLLb.cn
http://SUpOFV7M.nkLLb.cn
http://memtwVOs.nkLLb.cn
http://DRSnLS5F.nkLLb.cn
http://www.dtcms.com/a/388106.html

相关文章:

  • mysql面试(2)
  • Linux系统DNS服务
  • 如何通过跳板机访问内网 Mysql 服务器
  • SSH 远程连接内网 Linux 服务器
  • Spring Cloud - 微服务监控
  • Flutter-[1]入门指导
  • Linux服务器运维自动化巡检工具
  • Java 大视界 -- Java 大数据在智能家居设备联动与场景化节能中的应用拓展(413)
  • Node.js 部署:PM2 的 Fork 与集群模式
  • 【C++上岸】C++常见面试题目--网络篇(第二十五期)
  • LangChain使用方法以OpenAI 的聊天模型GPT-4o为例
  • CephFS存储文件系统介绍
  • Java Swagger2 能显示页面但看不到一个接口
  • SSL证书有效期缩短:自动化解决方案
  • C# 多线程编程 (.NET Framework 4.0)
  • 一个手艺活 - 跨语言编程
  • docker安装ollama、下载模型详细步骤
  • 微服务和分布式的基础学识
  • 自动化测试框架pytest---Json Schema
  • 阿里云PolarDB MySQL版与MCP集成方案:数据处理分析全流程的效能革命
  • Python实现霸王龙优化算法(Tyrannosaurus Optimization Algorithm, TROA)(附完整代码)
  • 弥合安全分析与故障仿真之间差距的方法
  • JavaEE---9.网络原理TCP/IP
  • @Value
  • 安装es、kibana、logstash
  • Leetcode-148.排序链表
  • 基于ETF底仓的网格交易系统实现动态参数优化与动量因子融合
  • C++底层刨析章节三: 函数对象与适配器:STL中的智能操作单元
  • MySQL多表联合查询与数据备份恢复全解析
  • 说说对React的理解?有哪些特性?