Rush Stack商店博客活动
跳到主要内容

@microsoft/tsdoc

NPM 包
CHANGELOG.md

@microsoft/tsdoc 包是 TSDoc 语法解析器的参考实现。您不能直接使用它。它是一个引擎组件,旨在集成到其他文档工具中。

如果您正在实现一个需要从 TypeScript 代码注释中提取信息的工具,@microsoft/tsdoc 提供了一个简单的解决方案,可以正确地实现 TSDoc。

我不能只使用 RegExp 吗?

假设我们正在分析一个 TypeScript 代码注释,例如这个

输入示例 1

/**
* This API calculates the average of a list of numbers.
*
* @param list - the array of input numbers
* @returns the arithmetic mean, or 0 if `list` is an empty array
*
* @internal
*/

假设我们正在制作一个文档工具,并且我们想要分析此注释是否被标记为 @internal。我们可以忘记花哨的解析器,并进行一个简单的测试,如下所示

function isApiInternal(docComment: string): boolean {
return docComment.indexOf('@internal') >= 0;
}

但是我们很快会注意到一些潜在的边缘情况无法被正确检测到

输入示例 2

/**
* @internalDefault
*/

输入示例 3

/**
* For more information, please contact support@internalwebsite.com.
*/

没问题!正则表达式可以区分 @internal 和包含它的单词

function isApiInternal(docComment: string): boolean {
return /(^|\s)@internal(\s|$)/.test(docComment);
}

但是 TypeScript 文档注释支持许多其他语法,这些语法不容易处理。直接跳到一个高级案例,想想我们自己的 isApiInternal() 函数的文档注释可能是什么样子。(如果我们的文档工具还不错,那么它肯定应该能够记录它自己的 API!)

输入示例 4

/**
* Returns `true` if a comment string contains the
* {@link https://tsdoc.typescript.net.cn/pages/tags/internal | @internal tag}.
*
* @example
* ```ts
* // Prints "true" if comment contains "@internal"
* console.log(isApiInternal(input));
* ```
*/

@internal 子字符串在示例 4 中出现了两次,但是这些用法都不是为了将 isApiInternal() 本身指定为内部 API。第一种情况是在 {@link} 标签内,第二种情况是在示例代码块内。如果您尝试扩展 RegExp,您会发现边缘情况很快变得难以克服。(正则表达式不起作用,因为 Markdown 不是正则语言。它甚至不是上下文无关文法。)

这引出了几个见解

  • 为了正确分析文档注释,您需要一个合适的解析器
  • 不同的解析器可能会对一个基本问题产生分歧,例如“这个 API 是否被标记为 @internal?” 例如,如果一个解析器不支持 ``` 代码块,那么它会误解上面的输入。

调用 TSDoc 解析器

以下是我们如何使用 @microsoft/tsdoc 引擎实现 isApiInternal() 的方法

import { TSDocParser, ParserContext } from '@microsoft/tsdoc';

function isApiInternal(docComment: string): boolean {
const tsdocParser: TSDocParser = new TSDocParser();

// Analyze the input doc comment
const parserContext: ParserContext = tsdocParser.parseString(docComment);

// Check for any syntax errors
if (parserContext.log.messages.length > 0) {
throw new Error('Syntax error: ' + parserContext.log.messages[0].text);
}

// Since "@internal" is a standardized tag and a "modifier", it is automatically
// added to the modifierTagSet:
return parserContext.docComment.modifierTagSet.isInternal();
}

const input: string = [
'/**',
' * @ Returns `true` if a comment string contains the',
' * {@link https://tsdoc.typescript.net.cn/pages/tags/internal | @internal tag}.',
' *',
' * @example',
' * ```ts',
' * // Prints "true" if comment contains "@internal"',
' * console.log(isApiInternal(input));',
' * ```',
' */'
].join('\n');

// Prints "false" because the two "@internal" usages in our example are embedded
// in other constructs, and thus should not be interpreted as tags.
console.log(isApiInternal(input));

该库提供了许多其他不错的功能

  • 它跟踪每个输入令牌的源代码坐标。这为每个令牌提供了精确的错误消息,并且可以用于实现语法高亮

  • 它提供了一个抽象语法树,可以轻松地以其他格式(例如 HTML)渲染富文本

  • 该解析器支持自定义标签

  • 解析器返回的错误消息可以被过滤,例如,如果您想忽略与您的场景无关的警告

调用 TSDoc 解析器

api-demo 文件夹提供了一个更完整的示例。它还包含一个“高级”示例,说明了如何将 TSDoc 与 TypeScript 编译器引擎返回的解析树接口。