<p>VSCode 默认不渲染 JSDoc 中的 Markdown 是因 HoverProvider 仅返回纯文本,需语言服务返回 MarkupContent;TypeScript v4.9+ 支持,但要求使用 /* / 注释、启用 "noErrorTruncation": true,并在扩展中用 vscode.MarkupContent 指定 kind: 'markdown'。</p>

VSCode 默认不显示 Markdown 格式文本的悬停提示,所谓“悬停显示文档”不是指渲染整个 .md 文件,而是指在代码中引用或注释 Markdown 内容时(比如 JSDoc 里的 @example、@description 块),让鼠标悬停能解析并渲染其中的 Markdown 语法(加粗、列表、链接等)。
为什么 hover 不显示 Markdown 格式内容
VSCode 的原生悬停(HoverProvider)默认只返回纯文本,即使 JSDoc 注释里写了 **bold** 或 - item,也会原样输出,不解析。这不是 bug,是语言服务未启用 Markdown 渲染路径。
常见现象包括:
- 鼠标悬停看到
/** @param {string} name - **required**, must be non-empty */,但**required**没加粗 - TypeScript 接口字段注释含列表,悬停后变成一行乱码,无换行或缩进
- 使用
vscode-language-server自定义 LSP 时,Hover.contents直接传字符串,没包装成MarkedString或MarkupContent
开启 JSDoc/TS 注释的 Markdown 悬停渲染
关键不在 VSCode 设置,而在语言服务层是否返回带格式的 MarkupContent。TypeScript 官方语言服务自 v4.9 起已支持,但需满足两个条件:
-
js/tsconfig.json中启用"noErrorTruncation": true(非必需但推荐,避免截断长注释) - 注释块必须用
/** */(而非/* */或//),且符合 JSDoc 规范(如@param后紧跟空格和描述) - VSCode 设置中确保
editor.hover.enabled为true(默认就是)
示例有效注释:
/**
* Creates a user with validation.
*
* @param name - **required**, length > 2
* @param tags - list of categories, e.g.:
* - `admin`
* - `guest`
*/
function createUser(name: string, tags: string[]) {}
悬停时 **required** 会加粗,- `admin` 会渲染为带缩进的列表项。
自定义扩展中返回 Markdown 格式悬停
如果你在写 VSCode 扩展并实现 HoverProvider,别直接返回字符串,要用 vscode.MarkupContent 并指定 kind: 'markdown':
provideHover(
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken
): vscode.ProviderResult<vscode.Hover> {
return new vscode.Hover({
language: 'markdown',
value: '**Example**: `console.log("hello")`'
});
}
注意:value 字段必须是纯 Markdown 字符串,不能含 HTML;路径解析、图片加载等不受支持——悬停区域不执行网络请求,也不读取本地文件。
容易踩的坑:
- 传
{ language: 'plaintext', value: '...' }→ 渲染为纯文本,Markdown 语法失效 - 用
MarkedString(已废弃)→ 在新版本 VSCode 中可能被忽略或降级为文本 - 在
provideHover里异步加载外部 .md 文件再解析 → 悬停超时(默认 500ms),返回空或 fallback 文本
Markdown 文件本身的悬停预览 ≠ 代码注释悬停
别混淆这两个功能:
-
README.md里悬停图片路径(如)→ 这是Image Preview扩展或内置图像悬停能力,和 JSDoc 无关 -
index.ts里写/** @see [API docs](https://ex.com) */→ 这才是本文讨论的「代码注释中的 Markdown 悬停」 - 二者底层机制完全不同:前者是编辑器对特定文件类型 + 特定语法模式的静态识别;后者依赖语言服务器对 JSDoc AST 的解析与富文本封装
最常被忽略的是:TypeScript 用户以为开了 markdown.preview.enabled 就能影响代码悬停——其实完全无关。那个设置只控制 .md 文件的右侧预览窗,对 .ts 编辑器内的 hover 零影响。


















