Simple Typescript Documentation in README.md
Generator
The focus of this generator is single output file, low effort, low maintenance, high accuracy API documentation generation.
Many JSDoc tags are ignored as not relevant to this objective. Some custom tags have been added.
For a full featured, fine grain typescript documentation generator see TypeDoc
A good starting point in the API doc is the ts2md function and then the TypescriptToMarkDown class.
The following JSDoc tags are supported:
Tag | Description |
---|---|
@example | Adds example as code block or comments and embedded code block(s). |
@param | Adds comment for function or method parameter. |
@private | Hides an otherwise accessible documentation item. |
@privateinitializer | Hides property initializer from documentation typescript. |
@property | Adds comment for class or interface property parameter in parent's JSDoc comment. |
@publicbody | Overrides the normal hidding of method and function bodies. |
@returns | Adds comment for function or method return value. |
@throws | Adds thrown error comment to function or method. |
npm i -D ts2md
After installation, use the following command to run markdown generation:
npx ts2md
Which will also remind you to add merge anchors in your README.md
file:
<!--#region ts2md-api-merged-here-->
<!--#endregion ts2md-api-merged-here-->
The anchors must not be indented where you wish to merge the generated documentation.
You may also want to add a script to package.json
as a reminder and to support
automatically updating documentation before publishing your package:
"scripts": {
"build:readme": "npx ts2md",
"prepublish": "npm run build && npx ts2md",
}
A good starting point in the API doc is the ts2md function and then the Ts2Md class.
Links: API, Interfaces, Classes, Functions
DocGenSupportApi |
JSDocInfo |
Ts2MdOptions |
Links: API, Interfaces, Classes, Functions
export interface DocGenSupportApi {
printer: ts.Printer;
nothingPrivate: boolean;
headingLevelMd(relativeLevel: number): string;
}
Links: API, Interfaces, Classes, Functions
Parsed JSDoc info associated with a documentation item
export interface JSDocInfo {
isPrivate: boolean;
publicBody: boolean;
privateInitializer: boolean;
comments: string[];
params: ts.JSDocParameterTag[];
returns: ts.JSDocReturnTag[];
throws: ts.JSDocThrowsTag[];
examples: string[];
properties: Record<string, string>;
tags: ts.Node[];
other: ts.Node[];
}
Interface JSDocInfo Details
JSDoc nodes with ['comment'] strings not otherwise tagged with a recognized tag.
comments: string[]
The
examples: string[]
Example
tag comments. Comments without code blocks are assumed to be typescript codeblocks
true if has '@private' tag
isPrivate: boolean
JSDoc nodes not parsed into other properties
other: ts.Node[]
The
params: ts.JSDocParameterTag[]
true if has '@privateinitializer' tag
privateInitializer: boolean
The
properties: Record<string, string>
true if has '@publicbody' tag
publicBody: boolean
JSDoc nodes tagged with '@returns'
returns: ts.JSDocReturnTag[]
JSDoc tags not parsed into other properties
tags: ts.Node[]
JSDoc nodes tagged with '@throws'
throws: ts.JSDocThrowsTag[]
Links: API, Interfaces, Classes, Functions
Options for the Ts2Md
class which generates Typescript documentation.
export interface Ts2MdOptions {
inputFilename: string;
firstHeadingLevel: 1 | 2 | 3;
noTitle: boolean;
outputFilename?: string;
outputReplace: boolean;
readmeMerge: boolean;
nothingPrivate?: boolean;
filenameSubString?: string;
}
Interface Ts2MdOptions Details
If specified, only symbols defined in files with this value as a substring are included in generated markdown.
'/' must be used as the folder separator.
filenameSubString?: string
The heading level for the first generated heading.
firstHeadingLevel: 1 | 2 | 3
Primary typescript source file, default is ./src/index.ts
inputFilename: string
Set to true if generated markdown will be merged into a file that already includes a containing header.
noTitle: boolean
If true, overrides private typescript keywords and jsdoc tags.
CAUTION: This setting is inappropriate for published documentation ;-)
nothingPrivate?: boolean
If valid, a copy of the generated markdown documentation will be saved to this file.
outputFilename?: string
Set to true to attempt to delete an existing output file before writing new output.
outputReplace: boolean
Set to true if the generated output should be merged into README.md
Currently README.md must exist at ./README.md
and must contain the following merge start and merge end anchors:
<!--#region ts2md-api-merged-here-->
<!--#endregion ts2md-api-merged-here-->
The anchors must not be indented.
readmeMerge: boolean
Links: API, Interfaces, Classes, Functions
DocBase | DocMethod |
DocClass | DocMethodSignature |
DocConstructor | DocProperty |
DocEnum | DocPropertySignature |
DocEnumMember | DocType |
DocFunction | DocVariable |
DocInterface | TypescriptToMarkdown |
DocItem |
Links: API, Interfaces, Classes, Functions
export abstract class DocBase<T extends ts.Node> {
docItems: DocItem<T>[] = [];
constructor(public sup: DocGenSupportApi, public label: string, public labelPlural: string, public detailsLabel = "Details")
abstract getName(item: T, sf: ts.SourceFile): string;
abstract filterItem(s: ts.Node): T[];
tryAddItem(s: ts.Node, sf: ts.SourceFile, parent?: DocItem<ts.Node>)
extractMemberDocs(docItem: DocItem<ts.Node>): DocBase<ts.Node>[]
isNotPrivate(item: ts.Node): boolean
findTs(findInTs: string, targetTs: string): {
pos: number;
len: number;
}
removeTs(fromTs: string, removeTs: string, withSemi?: boolean): string
toSeeAlso(docItem: DocItem<T>, mdts: string, mdLinks: Record<string, string>, tight?: boolean): string
toTsMarkDown(docItem: DocItem<T>, mdLinks: Record<string, string>, tight?: boolean): string
toMarkDown(docItem: DocItem<T>, mdLinks: Record<string, string>): string
toMarkDownTs(docItem: DocItem<T>): string
toMarkDownDetails(docItem: DocItem<T>, mdLinks: Record<string, string>): string
toMarkDownRefLink(docItem: DocItem<T>): string
isExportedDeclaration(item: ts.Declaration): boolean
argumentsDetails(docItem: DocItem<T>): string
returnsDetails(docItem: DocItem<T>): string
throwsDetails(docItem: DocItem<T>): string
examplesDetails(docItem: DocItem<T>): string
commentsDetails(docItem: DocItem<T>): string
}
See also: DocGenSupportApi, DocItem
Class DocBase Details
Base class implementation of markdown generation for a top level typescript AST node (DocItem
).
Adds relative level 3 heading with label
and docItem.name
Adds the nodes simple (no @
tag) JSDoc nodes under relative level 4 'Description` heading
Calls the toMarkDownTs
override to add the typescript syntax code block for this node.
Calls the toMarkDownDtails
override to add any details markdown for this node.
toMarkDown(docItem: DocItem<T>, mdLinks: Record<string, string>): string
See also: DocItem
Returns
the generated markdown for this DocItem
Generate the 'Details' markdown (including ) for this node.
Base class implementation returns an empty string.
toMarkDownDetails(docItem: DocItem<T>, mdLinks: Record<string, string>): string
See also: DocItem
Generate the typescript syntax for this node to be inserted in a typescript syntax code block in generated markdown.
Base class implementation uses the typescript compiler printer on DocItem
AST node item
.
CAUTION: This adds ALL the source code for this item to the generated markdown. Override SHOULD implement appropriate ommission control policies.
toMarkDownTs(docItem: DocItem<T>): string
See also: DocItem
Returns
typescript syntax to be added within a typescript syntax code block for this DocItem
Links: API, Interfaces, Classes, Functions
export class DocClass extends DocBase<ts.ClassDeclaration> {
constructor(sup: DocGenSupportApi)
override getName(item: ts.ClassDeclaration): string
override filterItem(item: ts.Node): ts.ClassDeclaration[]
override extractMemberDocs(docItem: DocItem<ts.ClassDeclaration>): DocBase<ts.Node>[]
override toMarkDownTs(docItem: DocItem<ts.ClassDeclaration>): string
override toMarkDownDetails(docItem: DocItem<ts.ClassDeclaration>, mdLinks: Record<string, string>): string
}
See also: DocBase, DocGenSupportApi, DocItem
Links: API, Interfaces, Classes, Functions
export class DocConstructor extends DocBase<ts.ConstructorDeclaration> {
constructor(sup: DocGenSupportApi)
override getName(item: ts.ConstructorDeclaration): string
override filterItem(item: ts.Node): ts.ConstructorDeclaration[]
override toMarkDownTs(docItem: DocItem<ts.ConstructorDeclaration>): string
override toMarkDownDetails(docItem: DocItem<ts.ConstructorDeclaration>, mdLinks: Record<string, string>): string
}
See also: DocBase, DocGenSupportApi, DocItem
Links: API, Interfaces, Classes, Functions
export class DocEnum extends DocBase<ts.EnumDeclaration> {
constructor(sup: DocGenSupportApi)
override getName(item: ts.EnumDeclaration): string
override filterItem(item: ts.Node): ts.EnumDeclaration[]
override extractMemberDocs(docItem: DocItem<ts.EnumDeclaration>): DocBase<ts.Node>[]
override toMarkDownDetails(docItem: DocItem<ts.EnumDeclaration>, mdLinks: Record<string, string>): string
}
See also: DocBase, DocGenSupportApi, DocItem
Links: API, Interfaces, Classes, Functions
export class DocEnumMember extends DocBase<ts.EnumMember> {
constructor(sup: DocGenSupportApi)
override getName(item: ts.EnumMember): string
override filterItem(item: ts.Node): ts.EnumMember[]
override toMarkDownDetails(docItem: DocItem<ts.EnumMember>, mdLinks: Record<string, string>): string
}
See also: DocBase, DocGenSupportApi, DocItem
Links: API, Interfaces, Classes, Functions
export class DocFunction extends DocBase<ts.FunctionDeclaration> {
constructor(sup: DocGenSupportApi)
override getName(item: ts.FunctionDeclaration): string
override filterItem(item: ts.Node): ts.FunctionDeclaration[]
override toMarkDownTs(docItem: DocItem<ts.FunctionDeclaration>): string
override toMarkDownDetails(docItem: DocItem<ts.FunctionDeclaration>, mdLinks: Record<string, string>): string
}
See also: DocBase, DocGenSupportApi, DocItem
Links: API, Interfaces, Classes, Functions
export class DocInterface extends DocBase<ts.InterfaceDeclaration> {
constructor(sup: DocGenSupportApi)
override getName(item: ts.InterfaceDeclaration): string
override filterItem(item: ts.Node): ts.InterfaceDeclaration[]
override extractMemberDocs(docItem: DocItem<ts.InterfaceDeclaration>): DocBase<ts.Node>[]
override toMarkDownDetails(docItem: DocItem<ts.InterfaceDeclaration>, mdLinks: Record<string, string>): string
}
See also: DocBase, DocGenSupportApi, DocItem
Links: API, Interfaces, Classes, Functions
Wrapper for a Typescript Node
of a specific derived type,
which is of interest for documentation generation.
export class DocItem<T extends ts.Node> {
jsDoc: JSDocInfo;
memberDocs: DocBase<ts.Node>[] = [];
constructor(public item: T, public name: string, public sf: ts.SourceFile, public parent?: DocItem<ts.Node>)
}
Class DocItem Details
This is really here just for demonstration / testing purposes...
constructor(public item: T, public name: string, public sf: ts.SourceFile, public parent?: DocItem<ts.Node>)
See also: DocItem
Argument Details
-
item
- The typescript Node for this doc item.
-
name
- The name for this doc item.
-
sf
- The source file which defined this item.
Parsed JSDoc information for this item
jsDoc: JSDocInfo
See also: JSDocInfo
Subsidiary documentation nodes when the node has members which are themselves represented as documentation nodes.
memberDocs: DocBase<ts.Node>[] = []
See also: DocBase
Links: API, Interfaces, Classes, Functions
export class DocMethod extends DocBase<ts.MethodDeclaration> {
constructor(sup: DocGenSupportApi)
override getName(item: ts.MethodDeclaration): string
override filterItem(item: ts.Node): ts.MethodDeclaration[]
override toMarkDownTs(docItem: DocItem<ts.MethodDeclaration>): string
override toMarkDownDetails(docItem: DocItem<ts.MethodDeclaration>, mdLinks: Record<string, string>): string
}
See also: DocBase, DocGenSupportApi, DocItem
Links: API, Interfaces, Classes, Functions
export class DocMethodSignature extends DocBase<ts.MethodSignature> {
constructor(sup: DocGenSupportApi)
override getName(item: ts.MethodSignature): string
override filterItem(item: ts.Node): ts.MethodSignature[]
override toMarkDownTs(docItem: DocItem<ts.MethodSignature>): string
override toMarkDownDetails(docItem: DocItem<ts.MethodSignature>, mdLinks: Record<string, string>): string
}
See also: DocBase, DocGenSupportApi, DocItem
Links: API, Interfaces, Classes, Functions
export class DocProperty extends DocBase<ts.PropertyDeclaration> {
constructor(sup: DocGenSupportApi)
override getName(item: ts.PropertyDeclaration): string
override filterItem(item: ts.Node): ts.PropertyDeclaration[]
override toMarkDownDetails(docItem: DocItem<ts.PropertyDeclaration>, mdLinks: Record<string, string>): string
}
See also: DocBase, DocGenSupportApi, DocItem
Links: API, Interfaces, Classes, Functions
export class DocPropertySignature extends DocBase<ts.PropertySignature> {
constructor(sup: DocGenSupportApi)
override getName(item: ts.PropertySignature): string
override filterItem(item: ts.Node): ts.PropertySignature[]
override toMarkDownDetails(docItem: DocItem<ts.PropertySignature>, mdLinks: Record<string, string>): string
}
See also: DocBase, DocGenSupportApi, DocItem
Links: API, Interfaces, Classes, Functions
export class DocType extends DocBase<ts.TypeAliasDeclaration> {
constructor(sup: DocGenSupportApi)
override getName(item: ts.TypeAliasDeclaration): string
override filterItem(item: ts.Node): ts.TypeAliasDeclaration[]
}
See also: DocBase, DocGenSupportApi
Links: API, Interfaces, Classes, Functions
export class DocVariable extends DocBase<ts.VariableDeclaration> {
constructor(sup: DocGenSupportApi)
override getName(item: ts.VariableDeclaration, sf: ts.SourceFile): string
override filterItem(item: ts.Node): ts.VariableDeclaration[]
}
See also: DocBase, DocGenSupportApi
Links: API, Interfaces, Classes, Functions
Uses the Typescript compiler to parse source tree given a top level source file such as index.ts
.
Extract the exported API interfaces, classes, types, functions and variables.
Generate GitHub friendly MarkDown documentation for the extracted API leveraging TypeScript type information and merging JSDoc style documentation comments.
The following JSDoc tags are supported:
@example
Adds example as code block or comments and embedded code block(s).
@param
Adds comment for function or method parameter.
@private
Hides an otherwise accessible documentation item.
@privateinitializer
Hides property initializer from documentation typescript.
@property
Adds comment for class or interface property parameter in parent's JSDoc comment.
@publicbody
Overrides the normal hidding of method and function bodies.
@returns
Adds comment for function or method return value.
@throws
Adds thrown error comment to function or method.
export class TypescriptToMarkdown implements DocGenSupportApi {
filePath: string;
fileName: string;
markDown?: string;
outputPath?: string;
constructor(public options: Ts2MdOptions)
run(): void
}
See also: DocGenSupportApi, Ts2MdOptions
Class TypescriptToMarkdown Details
Construct a new instance configured for run
method to be called next.
constructor(public options: Ts2MdOptions)
See also: Ts2MdOptions
Argument Details
-
options
- Must be provided. inputFilename defaults to
./src/index.ts
- Must be provided. inputFilename defaults to
The top level input Typescript file's filename without path
fileName: string
The top level input Typescript file's filename with full path.
filePath: string
The generated documentation as markdown string
markDown?: string
The file path to which markDown
was written.
outputPath?: string
Generates the documentation markdown and write's it to output file and/or merges it to README.md
run(): void
Links: API, Interfaces, Classes, Functions
mdMerge |
ts2md |
Links: API, Interfaces, Classes, Functions
Quick and dirty README.md merge function.
The anchors must not be indented and must exactly match:
<!--#region ts2md-api-merged-here-->
<!--#endregion ts2md-api-merged-here-->
export function mdMerge(md: string)
Function mdMerge Details
Argument Details
-
md
- The markdown to insert between the start and end anchors.
Links: API, Interfaces, Classes, Functions
Generate Typescript documentation and merge into README.md
Attempts to validate options, constructs an instance of Ts2Md with those options, and runs the generation method.
-
Function argument is used if provided.
-
Looks for
./ts2md.json
-
Default options.
Default options are:
{
"inputFilename": "./src/index.ts",
"outputFilename": "./apiDoc.md",
"firstHeadingLevel": 2,
"noTitle": true,
"outputReplace": true,
"readmeMerge": true
}
- Finally examines command line arguments which are treated as overrides of the options determined by steps 1, 2, 3. Command line arguments can be provided as either:
--inputFilename ../index.ts
or
--inputFilename=../index.ts
export function ts2md(options?: Ts2MdOptions): void {
if (!options) {
try {
const configPath = path.resolve("./ts2md.json");
const json = fs.readFileSync(configPath, { encoding: "utf8" });
options = <Ts2MdOptions>JSON.parse(json);
}
catch { }
}
options ||= {
inputFilename: "./src/index.ts",
outputFilename: "",
firstHeadingLevel: 2,
noTitle: true,
outputReplace: true,
readmeMerge: true,
};
const args = process.argv;
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (!arg.startsWith("--"))
continue;
const e = arg.indexOf("=");
let a = "", v = "";
if (e > -1) {
a = arg.slice(2, e);
v = arg.slice(e + 1);
}
else {
a = arg.slice(2);
v = args[++i];
}
switch (a) {
case "inputFilename":
options.inputFilename = v;
break;
case "outputFilename":
options.outputFilename = v;
break;
case "firstHeadingLevel":
options.firstHeadingLevel = <1 | 2 | 3>Number(v);
break;
case "noTitle":
options.noTitle = (v === "true");
break;
case "outputReplace":
options.outputReplace = (v === "true");
break;
case "readmeMerge":
options.readmeMerge = (v === "true");
break;
case "nothingPrivate":
options.nothingPrivate = (v === "true");
break;
case "filenameSubString":
options.filenameSubString = v;
break;
default: break;
}
}
console.log("ts2md(", options, ")");
new TypescriptToMarkdown(options).run();
}
See also: Ts2MdOptions, TypescriptToMarkdown
Function ts2md Details
Argument Details
-
options
- Optional options to control markdown generation.
Links: API, Interfaces, Classes, Functions
The license for the code in this repository is the Open BSV License.