Prettier 编程式 API 详解:从 format 到插件化的完整实践指南

发布时间:2026/11/12 23:14:36

Prettier 编程式 API 详解:从 format 到插件化的完整实践指南 Prettier 编程式 API 详解从 format 到插件化的完整实践指南【免费下载链接】prettierPrettier is an opinionated code formatter.项目地址: https://gitcode.com/gh_mirrors/pr/prettierPrettier 除了命令行之外还暴露了一套完整的编程式 API供编辑器插件、CI 工具、自定义格式引擎直接调用。本文基于仓库文档 docs/api.md 展开完整覆盖format、check、formatWithCursor、resolveConfig等全部公开接口的用法与返回约定并结合 src/index.js、src/main/core.js、src/config/resolve-config.js 等源码实现解释每个 API 底层的执行路径帮助你在自研工具链中正确、高效地集成 Prettier。一、引入方式与 API 的整体形态文档开头给出的标准引入方式import * as prettier from prettier;所有公开 API 均为异步函数返回Promise。这是 Prettier v3 的重要约定如果必须使用同步版本文档推荐借助第三方包装层如prettier/sync包来桥接而不是在核心 API 中提供同步入口。从 package.json 的exports字段可以确认模块解析关系{ exports: { .: { types: ./src/index.d.ts, require: ./src/index.cjs, default: ./src/index.js }, ./standalone: ./src/standalone.js, ./plugins/*: ./src/plugins/*.js, ./*: ./* }, engines: { node: 22 } }import prettier对应 src/index.jsESM或 src/index.cjsCJS完整功能入口prettier/standalone对应 src/standalone.js面向浏览器/独立运行的裁剪版prettier/plugins/*对应 src/plugins/ 下按语言切分出的内置插件供外部以插件形式显式加载当前开发版本为3.10.0-dev运行时要求 Node.js22。standalone 入口的 API 子集对比 src/standalone.js 的导出列表export { debugApis as __debug, check, format, formatWithCursor, getSupportInfo, }; export * as doc from ./document/public.js; export { default as version } from ./main/version.evaluate.js; export * as util from ./utilities/public.js;可以看到 standalone 版只导出check、format、formatWithCursor、getSupportInfo外加doc、util、version并不包含resolveConfig、getFileInfo等依赖文件系统搜索的 API——这与其面向浏览器、无法自由搜索配置目录的定位一致。如果你的运行环境是 Node.js则应使用主入口获取完整 API。二、prettier.format(source, options)format是最核心的接口用于把一段文本格式化为 Prettier 风格。使用约定options.parser必须按照目标语言显式设置可用解析器列表见 docs/options.md或者改用options.filepath让 Prettier 根据文件扩展名推断解析器其余 options 均可传入以覆盖默认值。文档示例await prettier.format(foo ( );, { semi: false, parser: babel }); // - foo()\n源码实现src/index.js 中format并不是独立实现而是formatWithCursor的薄封装——内部强制把cursorOffset置为-1表示不追踪光标取出结果中的formatted字段返回const formatWithCursor withPlugins(core.formatWithCursor); async function format(text, options) { const { formatted } await formatWithCursor(text, { ...options, cursorOffset: -1, }); return formatted; }值得注意的是withPlugins包装器src/index.js它会在调用真正格式化逻辑之前把options.plugins中的字符串/URL 路径通过loadBuiltinPlugins()和loadPlugins()加载为插件对象并注入选项。也就是说plugins选项接受插件对象、文件路径或 URLAPI 层会自动完成加载。三、prettier.check(source, options)check用于判断文件是否已经是 Prettier 格式化后的产物返回Promiseboolean。它与 CLI 的--check/--list-different参数语义一致非常适合在 CI 中做格式校验格式化失败即阻断流水线。从源码看src/index.js它的实现极其简洁——直接执行一次format并与原文全等比较async function check(text, options) { return (await format(text, options)) text; }这意味着check与format对配置的解读完全一致若options中缺少parser同样需要依赖filepath推断。四、prettier.formatWithCursor(source, options)编辑器集成的关键formatWithCursor在格式化代码的同时把未格式化代码中的光标位置映射到格式化后的对应位置。这是编辑器集成的刚需格式化后光标不能跳走。使用它时必须通过cursorOffset选项指明光标所在的字符偏移await prettier.formatWithCursor( 1, { cursorOffset: 2, parser: babel }); // - { formatted: 1;\n, cursorOffset: 1 }光标迁移算法底层实现在 src/main/core.js 的formatWithCursor中注释里完整描述了三步策略格式化前基于 AST 找出包含光标的最小区域叶子节点、两节点之间的空隙、或文档首尾格式化中记录该区域被写到了新文本的什么位置格式化后把光标当作一个特殊字符Symbol(cursor)插入旧区域文本对新旧区域做仅含插入/删除的 diffsrc/main/core.js 使用diff库的diffArrays从 diff 结果中反推出光标在新文本中的偏移const oldCursorNodeCharArray oldCursorRegionText.split(); oldCursorNodeCharArray.splice(cursorOffsetRelativeToOldCursorRegionStart, 0, CURSOR); const cursorNodeDiff diffArrays(oldCursorNodeCharArray, newCursorNodeCharArray); let cursorOffset newCursorRegionStart; for (const entry of cursorNodeDiff) { if (entry.removed) { if (entry.value.includes(CURSOR)) break; } else { cursorOffset entry.count; } }此外还有几个值得了解的行为细节见 src/main/core.jsBOM 处理输入若以 BOM 开头会先剥离、格式化后再补回光标偏移相应调整换行归一endOfLine: auto时按内容猜测换行符CRLF输入会先归一为LF参与计算输出时再转回Range 格式化设置了rangeStart/rangeEnd时走formatRange分支src/main/core.js只格式化片段并恢复原始缩进光标在范围外时保持不动PragmasrequirePragma、insertPragma、checkIgnorePragma均在此层统一裁决不满足条件时原样返回输入。五、prettier.resolveConfig(fileUrlOrPath, options)resolveConfig为某个源文件解析 Prettier 配置从文件所在目录开始向上搜索配置文件也可以直接把配置文件路径作为options.config传入以跳过搜索。返回 Promise找到配置时resolve 为一个选项对象未找到时resolve 为null配置文件解析出错时Promise 被 reject。文档给出的典型用法读取文件 → 解析配置 → 格式化const text await fs.readFile(filePath, utf8); const options await prettier.resolveConfig(filePath); const formatted await prettier.format(text, { ...options, filepath: filePath, });参数与底层行为options.useCache默认true缓存目录结构以加速重复查询设为false时完全绕过缓存见 src/config/resolve-config.js 中options { useCache: true, ...options }。options.editorconfig设为true且项目存在.editorconfig时Prettier 会解析它并转换为对应配置但优先级低于.prettierrc等 Prettier 配置文件。目前支持的 EditorConfig 属性end_of_lineindent_styleindent_size/tab_widthmax_line_length实现上resolveConfig会并行加载 Prettier 配置与 EditorConfigsrc/config/resolve-config.js 中的Promise.all([loadPrettierConfig(...), loadEditorconfig(...)])再合并const merged { ...editorConfigured, // EditorConfig 垫底 ...mergeOverrides(result, filePath), // .prettierrc含 overrides覆盖 };其中mergeOverridessrc/config/resolve-config.js会用micromatch匹配overrides[].files/excludeFiles基于配置文件所在目录的相对路径命中则用override.options覆盖基础选项。另外配置里声明的plugins若为相对路径以.开头会被解析为相对于配置文件目录的绝对路径。六、prettier.resolveConfigFile([fileUrlOrPath])resolveConfigFile只回答一个问题最终会使用哪个配置文件。返回 Promise找到时 resolve 为配置文件的路径字符串未找到时 resolve 为null解析出错时 reject。搜索起点是process.cwd()若提供了fileUrlOrPath参数则从该文件所在目录开始。对应实现见 src/config/resolve-config.js——它始终用shouldCache: false调用searchPrettierConfig即本 API 自身不参与缓存复用。const configFile await prettier.resolveConfigFile(filePath); // you got the path of the configuration file它与resolveConfig是配套关系resolveConfigFile给出路径resolveConfig给出解析后的选项。七、prettier.clearConfigCache()当 Prettier 反复读取配置文件与插件时会为性能缓存文件系统结构resolveConfig系列默认启用缓存。clearConfigCache用于主动清空该缓存——典型场景是编辑器集成方已知文件系统在两次格式化之间发生了变化新增了.prettierrc、改动忽略规则等。从主入口的实现看src/index.js它实际清空的不仅是配置缓存async function clearCache() { clearConfigCache(); // 清 .prettierrc / .editorconfig 的缓存 clearPluginCache(); // 同时清插件加载缓存 }八、prettier.getFileInfo(fileUrlOrPath, options)getFileInfo面向编辑器扩展在真正格式化之前先判断某个文件要不要格式化、用哪个解析器。它返回一个 Promiseresolve 为{ ignored: boolean; inferredParser: string | null; }约束与选项第一个参数必须是string或URL否则 Promise 被 reject见 src/common/get-file-info.js 的TypeError抛出options.ignorePathstring | URL | (string | URL)[]指定.prettierignore之类的忽略文件options.withNodeModulesboolean是否把node_modules也视为可忽略对象二者共同影响ignored的取值若文件被忽略inferredParser恒为nulloptions.plugins(string | URL | Plugin)[]提供插件路径有助于为 Prettier 核心不直接支持的文件类型推断出inferredParseroptions.resolveConfigboolean默认true设为false时跳过配置文件搜索适合只关心是否被忽略的低成本调用。从源码看src/common/get-file-info.js推断解析器的优先级是显式options.parser→ 配置文件中声明的parser→ 根据插件的语言描述与文件扩展名推断inferParser。另外源码注释特别提到本 API 的plugins期望是路径数组与format等接口的插件加载方式有意区分涉及 VS Code 扩展的兼容历史。九、prettier.getSupportInfo()getSupportInfo()返回一个 Promiseresolve 为描述 Prettier 当前支持范围的SupportInfo对象{ languages: Array{ name: string; parsers: string[]; group?: string; tmScope?: string; aceMode?: string; codemirrorMode?: string; codemirrorMimeType?: string; aliases?: string[]; extensions?: string[]; filenames?: string[]; linguistLanguageId?: number; vscodeLanguageIds?: string[]; isSupported?(options: { filepath: string }): boolean; }; options: SupportOption[]; }options部分的结构定义见 src/index.d.ts 的SupportInfo。它的典型用途是给编辑器补全 Prettier 选项、为语言动态推荐parser。实现位于 src/main/support.js从所有插件聚合languages合并插件options与核心选项定义并可通过showDeprecated参数决定是否保留已废弃的选项与选项值。一个来自文档的注意点Prettier 无法保证filepath在磁盘上真实存在若通过 API如prettier.format()使用连路径是否有效都无法保证——因此依赖isSupported(options: { filepath })这类回调时调用方需自行兜底。十、Custom Parser API已移除与插件迁移文档明确标记Custom Parser API 已在 v3.0.0 中移除被 Plugin API 取代。在插件出现之前parser选项可以直接传一个函数// ❌ Custom parser API (removed) import { format } from prettier; format(lodash ( ), { parser(text, { babel }) { const ast babel(text); ast.program.body[0].expression.callee.name _; return ast; }, }); // - _();\n等价迁移到 Plugin API 后需要定义一个含parsers的插件对象并在选项里通过plugins显式传入// ✔️ Plugin API import { format } from prettier; import * as prettierPluginBabel from prettier/plugins/babel; const myCustomPlugin { parsers: { my-custom-parser: { async parse(text) { const ast await prettierPluginBabel.parsers.babel.parse(text); ast.program.body[0].expression.callee.name _; return ast; }, astFormat: estree, }, }, }; await format(lodash ( ), { parser: my-custom-parser, plugins: [myCustomPlugin], }); // - _();\n迁移要点解析器变成具名函数通过parser: my-custom-parser引用astFormat声明产物 AST 的格式此处复用内置的estree打印器parse可以是asyncparse的入参是(text, options)插件对象可内联传入plugins数组也可通过文件路径加载prettier/plugins/*导出见 package.json 的exports各语言内置插件见 src/plugins/。文档同时警告用这种方式做 codemod 并不推荐。Prettier 依赖 AST 节点上的位置信息locStart/locEnd来保留空行、挂载注释等在解析后再修改 AST位置信息很容易与新结构失配导致不可预测的输出。文档建议需要 codemod 请考虑专用工具如 jscodeshift而不是借道 Prettier 的自定义解析器。此外旧的--parser选项允许传入导出parse函数的模块路径现已统一改为用--pluginCLI 选项或 API 的plugins选项来加载插件详见 docs/plugins.md。十一、API 速查与选型建议API返回典型场景实现入口format(source, options)Promisestring任何给我格式化结果的调用src/index.jscheck(source, options)PromisebooleanCI 格式校验等价--checksrc/index.jsformatWithCursor(source, options)Promise{formatted, cursorOffset}编辑器 LSP/扩展集成src/main/core.jsresolveConfig(file, options)PromiseOptions \| null按文件解析配置含 overrides / EditorConfigsrc/config/resolve-config.jsresolveConfigFile([file])Promisestring \| null只查配置文件路径src/config/resolve-config.jsclearConfigCache()Promisevoid文件系统变化后清理缓存src/index.jsgetFileInfo(file, options)Promise{ignored, inferredParser}编辑器决定是否格式化src/common/get-file-info.jsgetSupportInfo([options])PromiseSupportInfo选项/语言元数据、自动补全src/main/support.js选型建议依据上文源码行为归纳纯格式化用format需要保持光标则换成formatWithCursor并传cursorOffsetCI 校验用check失败即非零退出需要尊重项目配置先resolveConfig再与filepath一起传给format配置文件会热更新时记得在合适时机clearConfigCache编辑器要不要管这个文件先getFileInfo可设resolveConfig: false提速ignored为false且inferredParser非空才进入格式化浏览器/无文件系统环境只能用standalone入口暴露的format/check/formatWithCursor/getSupportInfo子集配置需要由宿主自行解析后作为options传入。配套的完整选项定义RequiredOptions、Plugin、SupportInfo等类型可参阅仓库自带的 src/index.d.ts各选项的取值与默认值说明见 docs/options.md配置文件的搜索与overrides规则见 docs/configuration.md。【免费下载链接】prettierPrettier is an opinionated code formatter.项目地址: https://gitcode.com/gh_mirrors/pr/prettier创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/12 10:50:57

YOLO选型实战指南:v5到v10的工程落地决策逻辑

1. 这不是版本迭代,是目标检测范式的十年演进现场 YOLO v5→v11?先说清楚:目前官方并不存在“YOLO v11”这个正式版本。截至2024年中,Ultralytics官方维护的最新稳定版是YOLOv8,而YOLOv9(2024年3月发布&am…

2026/11/11 21:45:57

别找临时中转:用 TaoToken 做 Continue 的兼容通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/12 23:10:48

从化哪里报名考电工证内部消息:电工证不考真找不到工作

从化哪里报名考电工证内部消息:电工证不考真找不到工作 你是不是正盯着手机屏幕发愁,眼看着同龄人一个个找到工作,自己却因为没特种作业证卡在门口?特别是从化这边的电工证,不是随便去哪都能考的,今天就给你透个 内部消息…

2026/11/12 23:10:48

从化电工证可以考吗保姆级教程:外省证怎么转过来全知道

从化电工证可以考吗保姆级教程:外省证怎么转过来全知道 之前考的证在外省能不能转过来?这是很多在从化打工的电工朋友最关心的问题。其实从化电工证可以考,而且流程并不复杂,但关键是你得知道怎么操作,尤其是如果你已经在外地考了证,想在当地转过来,那…

2026/11/12 23:10:48

本地电工证在哪里复审 低压电工证全国通用怎么操作

本地电工证在哪里复审 低压电工证全国通用怎么操作 学历不高怕报不上名,其实电工证报考门槛并没有你想象的那么高。特别是低压电工证这类操作性、技术性都很强的证书,很多初中毕业甚至没上过高中的人,都能通过培训和考试拿到证。而且这个证是 全国通用…

2026/11/12 23:10:48

本科要考低压电工证吗 通过率揭秘

本科要考低压电工证吗 通过率揭秘 之前考的证在外省能不能转过来?这个困扰了很多人,尤其是像你这样从外地过来的从业者,可能手里拿着一个外地的低压电工证,却因为地区差异、政策调整,导致证不能用了,甚至无法报考新的岗位。今天咱们就来聊聊【本科要考…

2026/11/12 23:10:48

江西低压电工证科目一报名入口与办理流程良心建议

江西低压电工证科目一报名入口与办理流程良心建议 工地太忙根本没时间复习考试,这事儿我懂,咱们天天在工地上扛着设备、赶工期,哪还有心思去背那些电工证的教材?但你可别小看这个【江西低压电工证科目一】,这证不光是干活的“通行证”,更是咱们在工地上…

2026/11/12 23:05:45

考电工证菏泽哪里报名实操考试考什么

工地太忙根本没时间复习考试,考电工证菏泽在哪考 工地太忙根本没时间复习考试,这几乎是每个在工地干活的电工、焊工、高处作业人员的真实写照。尤其是像你这样在菏泽本地做劳务班组的负责人,不仅要带人,还要处理各种手续,报考电工证的时间、流程、实操考…

2026/11/12 20:35:13

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/12 0:04:01

工地太忙根本没时间复习考试?学习电工证到哪里学通过率揭秘

工地太忙根本没时间复习考试?学习电工证到哪里学通过率揭秘 工地太忙根本没时间复习考试?你不是一个人。作为一名在南阳卧龙区干了七八年市政公用工程的电工,我深知这个问题的现实性。电工证不仅是工作的“入场券”,更是职业发展的“通行证”,但备考过程…

2026/11/12 0:04:01

双流电工证考别怕挂科!郑州报考避坑指南全攻略

双流电工证考别怕挂科!郑州报考避坑指南全攻略 实操考试心里没底怕挂科?双流电工证考在郑州报名,很多人因为不了解流程、准备不充分,白白浪费时间和金钱。作为三门峡应届工程类毕业生,我也曾经历过这样的焦虑。今天就从零开始,手把手教你如何避开郑州报…

2026/11/12 0:04:01

之前考的证在外省能不能转过来 怎么报名考电工证培训价格多少

之前考的证在外省能不能转过来 怎么报名考电工证培训价格多少 之前考的证在外省能不能转过来?这个问题确实让不少准备换城市工作的朋友犯了难,尤其像电工证这种实操性很强的证书,很多人担心跨省后证书能不能继续用。其实,只要符合相关流程,是可以顺利转…

2026/11/12 22:10:13

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/12 9:51:42

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑