
使用 effect/docgen 为 Effect 项目自动生成 API 文档安装配置、JSDoc 约定与源码实现解析【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3codeeffect/docgen 是 Effect 生态中一个固执己见opinionated的文档生成器它读取 TypeScript 源码中的 JSDoc 注释自动产出面向 GitHub Pages 的 Markdown API 文档站点并内置示例代码的类型检查与运行校验。本文以仓库中的 .repos/effect-smol/packages/tools/docgen/README.md 为主体结合 docgen 的源码实现完整讲解其安装、零配置使用、docgen.json配置、JSDoc 标签约定、CLI 参数以及解析—校验—生成的底层流水线帮助你在自己的 Effect 项目中一键生成高质量、可持续维护的 API 文档。项目定位为什么需要一个专门的文档生成器effect/docgen面向 Effect 项目设计核心思路是把写文档这件事沉淀为一套可强制的工程规范注释即文档通过标准的 JSDoc 标签category、example、since、deprecated、internal、ignore描述每个模块导出生成器负责排版输出示例即测试example中的代码片段会被tsc类型检查还能用tsx实际运行配合 Node.js 内置assert模块实现文档即测试规范可强制执行通过enforceDescriptions/enforceExamples/enforceVersion开关让 CI 在缺少描述、示例或版本标注时直接失败。它借鉴了 docs-ts 可以看到其自身就是 Effect 风格代码CLI 用effect/unstable/cli构建配置加载用 Effect 的Config/ConfigProvider整个程序跑在Effect运行时上。安装与快速上手环境要求[!WARNING] 使用effect/docgen需要Node.js v18 或以上。这一点在源码中有双重印证package.json 声明了engines: { node: 18.0.0 }且bin入口直接指向需要原生process与子进程能力的脚本bin.ts。安装以rc版本安装为开发依赖npm install -D effect/docgenrc作为 peer 依赖项目还需要 TypeScript 与 tsx用于运行示例typescript:5.8.2 7.0.0tsx:4.19.3 5.0.0三步完成接入可选创建docgen.json配置文件并让编辑器获得 JSON Schema 校验支持{ $schema: node_modules/effect/docgen/schema.json }在package.json中添加脚本{ scripts: { docgen: docgen } }运行npm run docgen零配置默认行为默认情况下 docgen 无需任何配置即可工作从src目录搜索 TypeScript 文件向docs目录输出生成的 Markdown 文档README 原文By default, docgen will search for files in thesrcdirectory and will output generated files into adocsdirectory。srcDir/outDir的默认值在 Configuration.ts 的ConfigurationSchema中有明确声明default: src与default: docs。生成的文档站点包含哪些文件从 Core.ts 的getMarkdown与writeMarkdown可以看到每次运行会生成/维护四类产物产物路径相对 outDir说明首页index.mdJekyll front mattertitle: Homenav_order: 1模块索引modules/index.mdtitle: Modules、has_children: trueGitHub Pages 配置_config.yml写入remote_theme、search_enabled与aux_links模块文档modules/路径.md每个源码模块一个文件含目录TOC与分类导出版块其中_config.yml是智能合并的若目标文件已存在resolveConfigYML 会保留用户已有内容只替换remote_theme:、search_enabled:和 Auxiliary Links 三处若不存在则生成完整默认文件。此外写入前会先删除 outDir 下所有旧的**/*.ts.md文件避免残留脏文档。支持的 JSDoc 标签docgen 通过doctrine解析 JSDoc见 Parser.ts 的parseComment支持的标签如下标签说明默认值category在生成的文档中为相关模块导出分组utilsexample为源码提供使用示例。所有示例都会用tsc做类型检查还可以用tsx实际运行并可用 Node.js 的assert模块做即时测试since标注某段源码最近一次更新的库版本deprecated标记弃用生成的文档中对应模块或函数名会显示为删除线falseinternal阻止 docgen 为标注的代码块生成文档若tsconfig.json中stripInternal为trueTypeScript 也不会为其输出声明ignore阻止 docgen 为标注的代码块生成文档标签行为背后的源码逻辑internal与ignore的处理在 Parser.ts 中shouldIgnore(doc)直接检查doc.tags中是否存在internal或ignore命中即跳过该导出。注意二者语义差异internal还附带 TypeScript 编译器stripInternal的配合README 明确说明而ignore纯粹是 docgen 层面的排除。deprecated的渲染Doc模型保存deprecated标签数组Domain.tsPrinter 据此在名称上渲染删除线。example的测试能力示例代码块会被抽取成独立.ts文件先tsc类型检查、再可选tsx执行执行环境中可直接import assert from node:assert做断言——即 README 所述on-the-fly testing。docgen.json 配置详解docgen默认是零配置 CLI 工具需要自定义行为时在项目根目录创建docgen.json。该文件由 Effect Schema 定义并校验Configuration.ts 的ConfigurationSchema对应的 JSON Schema 文件位于 schema.json注意其中additionalProperties: false多余的字段会被判定为非法配置。docgen.json遵循以下 TypeScript 接口README 原文interface Config { readonly projectHomepage?: string readonly srcLink?: string readonly srcDir?: string readonly outDir?: string readonly theme?: string readonly enableSearch?: boolean readonly enforceDescriptions?: boolean readonly enforceExamples?: boolean readonly enforceVersion?: boolean readonly tscExecutable?: string readonly exclude?: ReadonlyArraystring readonly parseCompilerOptions?: string | Recordstring, unknown readonly examplesCompilerOptions?: string | Recordstring, unknown }参数说明与默认值参数说明默认值projectHomepage在生成文档的 Auxiliary Links右上角导航区中链接到项目主页package.json中的homepage字段srcLink链接到项目源码{projectHomepage}/blob/main/src/srcDirdocgen 搜索待解析 TypeScript 文件的目录srcoutDirdocgen 输出 Markdown 文档的目录docstheme写入生成_config.yml的 GitHub Pages 主题mikearnaldi/just-the-docsenableSearch是否在生成_config.yml中开启搜索trueenforceDescriptions是否强制要求每个模块导出都有描述falseenforceExamples是否强制要求每个模块导出都有example注意模块级文档不强制falseenforceVersion是否强制要求每个模块导出都有sincetruetscExecutabledocgen 以编程方式调用编译器时使用的 TypeScript 编译器可执行文件路径tscexcludeglob 字符串数组指定排除在文档之外的源码文件[]parseCompilerOptions解析源码用的 tsconfig 选项或 tsconfig 文件路径{}examplesCompilerOptions示例代码用的 tsconfig 选项或 tsconfig 文件路径{}两个值得注意的细节enforceVersion默认开启也就是说除非显式设置enforceVersion: false所有导出的函数、类、常量、接口、类型别名、命名空间都必须带since标签否则 docgen 会报错终止。这与 Checker.ts 中checkEntry的逻辑一致since缺失即生成 Missingsincetag 错误并附带babel/code-frame定位的源码片段。parseCompilerOptions与examplesCompilerOptions可为字符串传入字符串时被视为 tsconfig 文件路径docgen 用tsconfck解析readTSConfig从中提取compilerOptions传入对象时直接作为编译选项使用Configuration.ts 的resolveCompilerOptions。配置优先级CLI 环境变量 docgen.json 默认值从 Configuration.ts 的configProviderLayer可以看出完整的取值链条CLI 标志优先loadConfiguration中先处理命令行参数其次读环境变量以DOCGEN_为前缀、常量大小写命名如DOCGEN_ENABLE_SEARCHfalse对应ConfigProvider.fromEnv({ env }).pipe(ConfigProvider.nested(DOCGEN), ConfigProvider.constantCase)再读docgen.json文件最后落到内置默认值enableSearch: true、enforceDescriptions: false、enforceExamples: false、enforceVersion: true等。其中projectName与projectHomepage必须来自package.jsonSchema 要求name与homepage均为字符串缺失会直接报错srcLink未配置时由 homepage 推导。官方示例配置{ exclude: [src/internal/**/*.ts], parseCompilerOptions: { noEmit: true, strict: true, skipLibCheck: true, moduleResolution: Bundler, target: ES2022, lib: [ES2022, DOM], paths: { effect/project-name: [./src/index.js], effect/project-name/test/*: [./test/*.js], effect/project-name/examples/*: [./examples/*.js], effect/project-name/*: [./src/*.js] } }, examplesCompilerOptions: { noEmit: true, strict: true, skipLibCheck: true, moduleResolution: Bundler, target: ES2022, lib: [ES2022, DOM], paths: { effect/project-name: [../../src/index.js], effect/project-name/test/*: [../../test/*.js], effect/project-name/examples/*: [../../examples/*.js], effect/project-name/*: [../../src/*.js] } } }对该配置的实操解读exclude: [src/internal/**/*.ts]与internal标签相互配合是 Effect 生态的标准做法——内部实现既不出现在文档中也不参与解析parseCompilerOptions.paths把effect/project-name映射到本地./src/*.js保证解析阶段能正确解析模块间引用examplesCompilerOptions.paths使用../../相对路径是因为示例代码会被抽取到outDir/examples/下执行见下文需要从该目录回指项目根部的src未显式设置的runExamples保持默认false即示例只做类型检查、不实际运行。CLI 命令行参数docgen 的 CLI 由effect/unstable/cli构建CLI.ts所有配置项都暴露为命令行标志用法形如docgen --src ./lib --out ./api-docs标志对应配置说明--homepage urlprojectHomepage项目主页链接显示在生成文档的 Auxiliary Links--srcLink urlsrcLink项目源码链接--src dirsrcDir搜索待解析 TS 文件的目录必须存在--out diroutDir输出 Markdown 的目录--theme themetheme生成文档使用的 Jekyll 主题--disable-search/--enable-searchenableSearch是否在生成文档中启用搜索--enforce-descriptionsenforceDescriptions强制要求每个模块导出有描述--enforce-examplesenforceExamples强制要求每个模块导出有example模块级文档不强制--no-enforce-version/--enforce-versionenforceVersion是否强制要求since标签--run-examplesrunExamples是否实际执行源码中发现的示例--exclude globexcludeglob 数组排除指定文件可多次传入--parse-tsconfig-file fileparseCompilerOptions解析源码使用的 tsconfig 文件路径--parse-compiler-options jsonparseCompilerOptions解析源码使用的编译器选项JSON 字符串--examples-tsconfig-file fileexamplesCompilerOptions示例使用的 tsconfig 文件路径--examples-compiler-options jsonexamplesCompilerOptions示例使用的编译器选项JSON 字符串需要注意的约束CLI.ts 的loadConfiguration中明确校验--parse-tsconfig-file与--parse-compiler-options不能同时使用否则抛出InvalidValue错误--examples-tsconfig-file与--examples-compiler-options同理内联 JSON 选项会先经Schema.decodeUnknownEffect校验必须是合法的 JSON 对象否则报错并提示expected: a JSON record。示例代码的类型检查与运行文档即测试example与描述文本中的代码围栏code fence会被 docgen 抽取、类型检查并可选运行这是它区别于普通文档工具的核心能力。完整流水线位于 Core.ts 的typeCheckAndRunExamples抽取extractFencedCode用正则匹配与~~~两种围栏只有语言标记以ts/typescript开头、且不包含skip-type-checking元数据的代码块才会被抽取支持ts title...这类带元数据的围栏。若发现未闭合的围栏会输出警告。落盘示例写入outDir/examples/文件命名规则为模块路径-kind-导出名-序号.tskind 包括module、class、interface、typealias、constant、function、namespace、export以及类的method/staticmethod同时生成一个聚合入口index.ts逐行import所有示例和examples/tsconfig.json内容来自examplesCompilerOptions。类型检查用tsc --noEmit --project outDir/examples/tsconfig.json检查全部示例非零退出码即报错错误信息中会携带tsc的 stdout。运行仅当runExamples为true配置或--run-examples时用tsx --tsconfig ... index.ts执行所有示例执行失败同样导致 docgen 失败。清理每次运行前后都会删除outDir/examples目录保证示例永远从最新源码重新生成目录中的文件标记为可覆写isOverwriteable: true。在 Windows 上工具会自动改用.cmd变体tsc.cmd/tsx.cmd并以 shell 模式执行。如果想跳过某段代码的类型检查可在围栏元数据中加入skip-type-checkingts skip-type-checking // 这段代码不会被 docgen 抽取与类型检查 工作原理解析解析 → 校验 → 生成的流水线docgen 的入口程序定义在 Core.ts 的program中整体分为两个并发 Fiber最后Fiber.joinAll汇合读取源码文件glob src/**/*.ts exclude │ ▼ 解析为模块模型Parserts-morph AST doctrine JSDoc │ ┌────┴─────────────────────────────┐ ▼ ▼ 校验模块Checker 生成 MarkdownPrinter │ ├─ 强制 since ├─ 每个模块一个 .md │ ├─ 强制描述可选 ├─ 首页 / 模块索引 / _config.yml │ └─ 强制示例可选 └─ 清理旧 *.ts.md ▼ 类型检查并可选运行示例解析层Parser.ts基于ts-morph的Projectdoctrine的 JSDoc 解析构建出 Domain.ts 中的Module模型。每个模块模型包含classes、interfaces、functions、typeAliases、constants、exports、namespaces七类成员解析规则值得了解函数既支持export function声明也支持export const fn () ...箭头函数形式的导出变量签名统一渲染为declare const name: 类型常量导出的、非函数类型的变量声明如export const x 1类导出类的实例方法、静态方法均取第一个重载的 JSDoc与实例属性属性签名保留readonly与可选标记命名空间支持嵌套命名空间文档中通过前缀-命名空间名的方式区分配平后的重名导出extractPrefixedNestedNamespaces显式导出包括命名导出export { x } from ...支持前置 JSDoc 注释与export * from .../export * as ns from ...后者会被自动注入一段描述Re-exports all named exports from the ... module模块级文档取源码文件第一个语句前的/** ... */注释作为模块描述解析选项createProject会把parseCompilerOptions合并进默认的{ strict: true, moduleResolution: node }再交给 ts-morph 建立工程。校验层Checker.tscheckModules遍历所有模块对每个导出调用checkEntry按配置检查enforceDescriptions→ 缺少描述报错enforceExamples→doc.examples.length 0报错enforceVersion默认开启→ 缺少since报错。错误信息使用babel/code-frame输出带行列定位的源码片段。类的方法、静态方法、属性以及嵌套命名空间中的成员会递归校验但方法/属性级不强制sinceenforceVersion: false。生成层Printer.ts markdown-toc每个模块生成docs/modules/路径.mdfront matter 中写入nav_order用effect/markdown-toc生成 TOC插入到!-- toc --占位符处产出Exports Grouped by Category目录最终内容经prettier格式化后写盘。常见问题Q重载函数能否分别记录每个重载的文档A不能。docgen 在生成输出时只使用函数第一个重载的文档。这一行为在 Parser.ts 的getFunctionDeclarationJSDocs中得到印证fd.getOverloads()非空时直接取第一个重载的 JSDoc。因此请把完整的用法说明写在第一个重载上或在实现上补充模块级文档。更多参考配置 Schemaschema.json配置加载与默认值Configuration.ts主流水线Core.tsJSDoc 解析Parser.ts规范校验Checker.ts数据模型Domain.ts命令行入口CLI.ts许可证MIT License。【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考