Simple Typescript Documentation Generator to GitHub Compatible MarkDown


Keywords
Typescript, Documentation, Markdown
License
BSD-3-Clause-Open-MPI
Install
npm install ts2md@0.1.22

Documentation

ts2md

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.

Supported JSDoc Tags

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.

Installation

npm i -D ts2md

Setup

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.

API

Links: API, Interfaces, Classes, Functions

Interfaces

DocGenSupportApi
JSDocInfo
Ts2MdOptions

Links: API, Interfaces, Classes, Functions


Interface: DocGenSupportApi

export interface DocGenSupportApi {
    printer: ts.Printer;
    nothingPrivate: boolean;
    headingLevelMd(relativeLevel: number): string;
}

Links: API, Interfaces, Classes, Functions


Interface: JSDocInfo

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
Property comments

JSDoc nodes with ['comment'] strings not otherwise tagged with a recognized tag.

comments: string[]
Property examples

The

examples: string[]

Example

tag comments. Comments without code blocks are assumed to be typescript codeblocks
Property isPrivate

true if has '@private' tag

isPrivate: boolean
Property other

JSDoc nodes not parsed into other properties

other: ts.Node[]
Property params

The

params: ts.JSDocParameterTag[]
Property privateInitializer

true if has '@privateinitializer' tag

privateInitializer: boolean
Property properties

The

properties: Record<string, string>
Property publicBody

true if has '@publicbody' tag

publicBody: boolean
Property returns

JSDoc nodes tagged with '@returns'

returns: ts.JSDocReturnTag[]
Property tags

JSDoc tags not parsed into other properties

tags: ts.Node[]
Property throws

JSDoc nodes tagged with '@throws'

throws: ts.JSDocThrowsTag[]

Links: API, Interfaces, Classes, Functions


Interface: Ts2MdOptions

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
Property filenameSubString

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
Property firstHeadingLevel

The heading level for the first generated heading.

firstHeadingLevel: 1 | 2 | 3
Property inputFilename

Primary typescript source file, default is ./src/index.ts

inputFilename: string
Property noTitle

Set to true if generated markdown will be merged into a file that already includes a containing header.

noTitle: boolean
Property nothingPrivate

If true, overrides private typescript keywords and jsdoc tags.

CAUTION: This setting is inappropriate for published documentation ;-)

nothingPrivate?: boolean
Property outputFilename

If valid, a copy of the generated markdown documentation will be saved to this file.

outputFilename?: string
Property outputReplace

Set to true to attempt to delete an existing output file before writing new output.

outputReplace: boolean
Property readmeMerge

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


Classes

DocBase DocMethod
DocClass DocMethodSignature
DocConstructor DocProperty
DocEnum DocPropertySignature
DocEnumMember DocType
DocFunction DocVariable
DocInterface TypescriptToMarkdown
DocItem

Links: API, Interfaces, Classes, Functions


Class: DocBase

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
Method toMarkDown

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

Method toMarkDownDetails

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

Method toMarkDownTs

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


Class: DocClass

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


Class: DocConstructor

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


Class: DocEnum

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


Class: DocEnumMember

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


Class: DocFunction

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


Class: DocInterface

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


Class: DocItem

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>) 
}

See also: DocBase, JSDocInfo

Class DocItem Details
Constructor

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.
Property jsDoc

Parsed JSDoc information for this item

jsDoc: JSDocInfo

See also: JSDocInfo

Property memberDocs

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


Class: DocMethod

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


Class: DocMethodSignature

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


Class: DocProperty

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


Class: DocPropertySignature

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


Class: DocType

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


Class: DocVariable

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


Class: TypescriptToMarkdown

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
Constructor

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
Property fileName

The top level input Typescript file's filename without path

fileName: string
Property filePath

The top level input Typescript file's filename with full path.

filePath: string
Property markDown

The generated documentation as markdown string

markDown?: string
Property outputPath

The file path to which markDown was written.

outputPath?: string
Method run

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


Functions

mdMerge
ts2md

Links: API, Interfaces, Classes, Functions


Function: mdMerge

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


Function: ts2md

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.

  1. Function argument is used if provided.

  2. Looks for ./ts2md.json

  3. Default options.

Default options are:

{
  "inputFilename": "./src/index.ts",
  "outputFilename": "./apiDoc.md",
  "firstHeadingLevel": 2,
  "noTitle": true,
  "outputReplace": true,
  "readmeMerge": true
}
  1. 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


License

The license for the code in this repository is the Open BSV License.