theme: scrolls-light
大家好,long time no see!这次聊一聊「注释」。写「注释」的好处众所周知,但有时在实现一些「公共代码」后,需要编写「文档」,其中「注释」和「文档」的内容是大致相同的,比如
param
和returns
等(相信有不少同学试过把「注释」copy到「文档」中吧🌝)。So,有没有一种可能,直接把「注释」直接转化为「文档」呢?
背景
👨💼:一会抽空优化下JsBridge,写好注释!写好文档!
JsBridge:用于「Hybrid」开发模式下,「Native 原生」和「Web H5」之间通信。
🧑💻:JsBridge里面几十个方法,写完注释还要写文档,得花不少时间。
👨💼:你傻啊,不会用TypeDoc吗?
🧑💻:就是那个根据「代码」直接生成「文档」的工具吗?我这就去试试!
TypeDoc
TypeScript的「文档生成器」,通过读取TypeScript源文件,解析其中包含的注释,并为代码生成包含文档的「静态站点」。
安装
$ npm install typedoc --save-dev
安装时,要注意对应项目的typescript版本。
TypeDoc Version | TypeScript Version(s) |
---|---|
0.23 | 4.6 through 4.8 |
0.22 | 4.0 through 4.7 |
0.21 | 4.0 through 4.4 |
0.20 | 3.9 through 4.2 |
0.19 | 3.9 through 4.0 |
使用方式
TypeDoc提供两种了运行方式:
- Cli
- Node Module
Cli
使用「命令行」运行时,有三种配置方式:
- 把所有参数添加在「命令」中:
$ typedoc --out docs src/index.ts
- 使用typedoc.json(推荐):
在项目的「根路径」下创建typedoc.json。
./typedoc.json
{
"entryPoints": ["src/index.ts"],
"out": "docs"
}
- 在tsconfig.json中配置:
在tsconfig.json中的typedocOptions
字段定义参数。
{
// ...
"typedocOptions": {
"entryPoints": ["src/index.ts"],
"out": "docs"
}
}
Node Module
如果想要「动态配置」或者不使用Cli来运行typedoc,可以require("typedoc")
进行文档构建。
const TypeDoc = require("typedoc")
// 初始化
const app = new TypeDoc.Application()
// 读取 tsconfig.json
app.options.addReader(new TypeDoc.TSConfigReader())
// or 读取 typedoc.json
app.options.addReader(new TypeDoc.TypeDocReader())
// or 直接配置
app.bootstrap({
entryPoints: ["src/index.ts"],
});
const project = app.convert()
if (project) {
const outputDir = "docs"
// 生成文档
await app.generateDocs(project, outputDir)
// 生成json
await app.generateJson(project, outputDir + "/documentation.json")
}
具体的参数配置,👉 传送门
插件
使用
plugin
字段扩展TypeDoc的能力。
{
// ...
plugin: ['typedoc-plugin-markdown'],
}
默认情况下,TypeDoc只生成html的静态站点文档,如需Markdown格式,可添加typedoc-plugin-markdown,生成对应的Markdown文档。
更多的官方插件,👉 传送门
Tips: 在npm的typedoc-plugin关键字下可以找到更多插件。
主题
使用
theme
字段配置生成文档的主题。
{
// ...
"plugin": ["typedoc-theme-hierarchy"],
"theme": "hierarchy",
}
使用主题时,要先添加进plugin
中,再添加到theme
中。
更多主题,👉 传送门
Tips: 在npm的typedoc-theme关键字下可以找到更多主题。
TSDoc
TypeDoc不是万能的,“龙飞凤舞”的「注释」生成不了「文档」,或者生成后的「文档」阅读性很差。
因此,这就要求我们✍️「注释」时要符合“规范”!
没错,用别人的工具,就要遵守别人的规则,这个“规范”就是TSDoc。
TSDoc是标准化TypeScript代码中使用的文档注释,这样不同的工具就可以提取内容,而不会被彼此的标记混淆。
通俗来说,TSDoc就是「微软」的一套「注释规范」,主要用于统一某些工具(除了TypeDoc外还有DocFX、API Extractor等)对「注释」的识别,避免每个工具都搞一套自己的注释规范。
Tags(重点)
正确使用Tags是写好注释的基础。
标签名以 @ 开头,后面跟着使用「驼峰大小写的ASCII字母」。
kind
Tags根据「类型」来区分,分三种:
- Block tags
- Modifier tags
- Inline tags
Block tags
「块级」标签:
- 该tags作为一行中「第一个」出现的元素;
- 一行中仅允许该tags存在(很多Block tag都没遵守该约定);
- 直至遇到下个Block tags前,都是该tags的内容;
- 第一个Block tags前面的内容为“摘要”;
Modifier tags
「修饰」标签:
- 内容为空的Block tags;
- 出现在注释底部;
Inline tags
「行内」标签:
- 与Markdown表达式一起作为内容元素出现;
- 被 { } 字符包围;
Standardization
Tags根据「兼容性」来区分,分三组:
- Core
- Extended
- Discretionary
Core
每个「文档工具」都支持。
Extended
「文档工具」可能支持,也可能不支持,需要查阅该工具的文档。
Discretionary
针对某个/些「文档工具」而自身定制的tags。
常用的Tags
@alpha
表示该Api的发布阶段为alpha。
Standardization | kind |
---|---|
Discretionary | Modifier |
export class Book {
/**
* The title of the book.
* @alpha
*/
public get title(): string;
};
@beta @experimental
beta与experimental同义
表示该Api的发布阶段为beta/experimental。
Standardization | kind |
---|---|
Discretionary | Modifier |
export class Book {
/**
* The title of the book.
* @beta
*/
public get title(): string;
};
@internal
表示该Api不计划供第三方使用。
Standardization | kind |
---|---|
Discretionary | Modifier |
export class Book {
/**
* The title of the book.
* @internal
*/
public get _title(): string;
};
@public
表示该Api的发布阶段为public,代表已正式发布且稳定的(可省略)。
Standardization | kind |
---|---|
Discretionary | Modifier |
export class Book {
public get title(): string;
};
@decorator
由于TypeScript编译器并不能识别.d.ts
中的「装饰器」,所以使用该tag在文档注释中引用decorator表达式。
Standardization | kind |
---|---|
Extended | Block |
class Book {
/**
* The title of the book.
* @decorator `@jsonSerialized`
* @decorator `@jsonFormat(JsonFormats.Url)`
*/
@jsonSerialized
@jsonFormat(JsonFormats.Url)
public website: string;
}
@deprecated
表示该Api不再被支持,未来可能会被删除,其后面是替代方案。
Standardization | kind |
---|---|
Core | Block |
/**
* The base class for controls that can be rendered.
*
* @deprecated Use the new {@link Control} base class instead.
*/
export class VisualControl {
. . .
}
@defaultValue
如果未显式分配值,则用于记录字段或属性的默认值。
⚠️:该标记只能用于作为类或接口成员的字段或属性。
Standardization | kind |
---|---|
Extended | Block |
enum WarningStyle {
DialogBox,
StatusMessage,
LogOnly
}
interface IWarningOptions {
/**
* Determines how the warning will be displayed.
*
* @defaultValue `WarningStyle.DialogBox`
*/
warningStyle: WarningStyle;
}
@eventProperty
应用于「类」或者「接口属性」时,表示其返回的「事件处理程序」可以附加到事件对象上(通常具备addHandler()
和removeHandler()
)。
⚠️:「文档工具」会把该类/属性归纳到「事件」内。
Standardization | kind |
---|---|
Extended | Modifier |
class MyClass {
/**
* This event is fired whenever the application navigates to a new page.
* @eventProperty
*/
public readonly navigatedEvent: FrameworkEvent<NavigatedEventArgs>;
}
@example
演示如何使用该Api,可能包含一个代码示例。
与该tag出现在同一行上的后续文本为示例的标题。
Standardization | kind |
---|---|
Extended | Block |
/**
* Adds two numbers together.
* @example
* Here's a simple example:
* ```
* // Prints "2":
* console.log(add(1,1));
* ```
*/
export function add(x: number, y: number): number {
}
@inheritDoc
用于复制另一个Api的tag,甚至可以从一个不相关的package中进行复制。
⚠️:并不是所有的tags都能被复制,只有remarks、params、typeParam、returns能被复制。
Standardization | kind |
---|---|
Extended | Inline |
import { Serializer } from 'example-library';
export interface IWidget {
/**
* Draws the widget on the display surface.
* @param x - the X position of the widget
* @param y - the Y position of the widget
*/
public draw(x: number, y: number): void;
}
export class Button implements IWidget {
/** {@inheritDoc IWidget.draw} */
public draw(x: number, y: number): void {
. . .
}
/**
* {@inheritDoc example-library#Serializer.writeFile}
*/
public save(): void {
. . .
}
}
@label
表示一个声明,可在TSDoc中使用「选择器」引用它。
⚠️:该tag还没有最终确定。👉 GitHub issue #9
Standardization | kind |
---|---|
Core | Inline |
export interface Interface {
/**
* Shortest name: {@link InterfaceL1.(:STRING_INDEXER)}
* Full name: {@link (InterfaceL1:interface).(:STRING_INDEXER)}
*
* {@label STRING_INDEXER}
*/
[key: string]: number;
/**
* Shortest name: {@link InterfaceL1.(:CONSTRUCTOR)}
* Full name: {@link (InterfaceL1:interface).(:CONSTRUCTOR)}
*
* {@label CONSTRUCTOR}
*/
new (hour: number, minute: number);
}
@link
表示用于创建到文档系统中其他页面或一般的url超链接。
⚠️:该tag还没有最终确定。👉 GitHub issue #9
Standardization | kind |
---|---|
Core | Inline |
/**
* Links can point to a URL: {@link https://github.com/microsoft/tsdoc}
*/
@override @sealed @virtual
- @override: 表示此定义覆盖父类的定义;
- @sealed: 表示该定义不能被继承,且不得被重写;
- @virtual:表示该定义能被继承,能被重写;
⚠️:「文档工具」强制要求virtual、override或sealed同时使用。
Standardization | kind |
---|---|
Extended | Modifier |
class Base {
/** @virtual */
public render(): void {
}
/** @sealed */
public initialize(): void {
}
}
class Child extends Base {
/** @override */
public render(): void;
}
@packageDocumentation
表示描述整个package的文档注释。
⚠️:注释在
.d.ts
文件中,且不得用于描述单项Api。
Standardization | kind |
---|---|
Core | Modifier |
// Copyright (c) Example Company. All rights reserved. Licensed under the MIT license.
/**
* A library for building widgets.
*
* @remarks
* The `widget-lib` defines the {@link IWidget} interface and {@link Widget} class,
* which are used to build widgets.
*
* @packageDocumentation
*/
/**
* Interface implemented by all widgets.
* @public
*/
export interface IWidget {
/**
* Draws the widget on the screen.
*/
render(): void;
}
@param
用于记录函数参数,后面是一个参数名,后面是一个连字符,最后是一个描述。
Standardization | kind |
---|---|
Core | Block |
/**
* @param x - The first input number
* @param y - The second input number
*/
function getAverage(x: number, y: number): number {
return (x + y) / 2.0;
}
@returns
用于记录函数的返回值。
Standardization | kind |
---|---|
Core | Block |
/**
* @returns The arithmetic mean of `x` and `y`
*/
function getAverage(x: number, y: number): number {
return (x + y) / 2.0;
}
@remarks @privateRemarks
- @remarks:表示一个简短的公开的“摘要”;
- @privateRemarks:表示一个简短的非公开的“摘要”;
Standardization | kind |
---|---|
Core | Block |
/**
* @remarks
*
* The main documentation for an API item is separated into a brief
* "summary" section optionally followed by an `@remarks` block containing
* additional details.
*
* @privateRemarks
*
* The `@privateRemarks` tag starts a block of additional commentary that is not meant
* for an external audience. A documentation tool must omit this content from an
* API reference web site. It should also be omitted when generating a normalized
* *.d.ts file.
*/
@readonly
表示「只读」属性。
Standardization | kind |
---|---|
Extended | Modifier |
export class Book {
/**
* Technically property has a setter, but for documentation purposes it should
* be presented as readonly.
* @readonly
*/
public get title(): string {
return this._title;
}
public set title(value: string) {
throw new Error('This property is read-only!');
}
}
@see
表示与当前Api相关的其他资源的引用列表。
⚠️:JSDoc在see之后立即生成超链接文本。但TSDoc需要显式的link来生成超链接。
Standardization | kind |
---|---|
Extended | Block |
/**
* Parses a string containing a Uniform Resource Locator (URL).
* @see {@link ParsedUrl} for the returned data structure
* @see {@link https://tools.ietf.org/html/rfc1738|RFC 1738}
* for syntax
* @see your developer SDK for code samples
* @param url - the string to be parsed
* @returns the parsed result
*/
function parseURL(url: string): ParsedUrl;
@throws
表示可能由「函数」或「属性」引发的异常类型。
⚠️:每种异常类型都应该单独使用一个throw进行描述。
Standardization | kind |
---|---|
Extended | Block |
/**
* Retrieves metadata about a book from the catalog.
*
* @param isbnCode - the ISBN number for the book
* @returns the retrieved book object
*
* @throws {@link IsbnSyntaxError}
* This exception is thrown if the input is not a valid ISBN number.
*
* @throws {@link book-lib#BookNotFoundError}
* Thrown if the ISBN number is valid, but no such book exists in the catalog.
*
* @public
*/
function fetchBookByIsbn(isbnCode: string): Book;
@typeParam
用于记录通用参数,后面是一个参数名,后面是一个连字符,最后是一个描述。
Standardization | kind |
---|---|
Core | Block |
/**
* Alias for array
*
* @typeParam T - Type of objects the list contains
*/
type List<T> = Array<T>;
/**
* Wrapper for an HTTP Response
* @typeParam B - Response body
* @param <H> - Headers
*/
interface HttpResponse<B, H> {
body: B;
headers: H;
statusCode: number;
}
最后
👨💼:不错不错,文档写的很好!顺便把以前的文档都重写一遍吧!
🧑💻:卒。
参考文章:
祝大家生活愉快,工作顺利!
「 ———- The end ———- 」
暂无评论内容