0.2.2 • Published 16 days ago

ts2md v0.2.2

Weekly downloads
-
License
Open BSV
Repository
github
Last release
16 days ago

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:

TagDescription
@exampleAdds example as code block or comments and embedded code block(s).
@paramAdds comment for function or method parameter.
@privateHides an otherwise accessible documentation item.
@privateinitializerHides property initializer from documentation typescript.
@propertyAdds comment for class or interface property parameter in parent's JSDoc comment.
@publicbodyOverrides the normal hidding of method and function bodies.
@returnsAdds comment for function or method return value.
@throwsAdds 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: 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;
}
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


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[];
}
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: DocGenSupportApi

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

Links: API, Interfaces, Classes, Functions


Classes

DocBaseDocMethod
DocClassDocMethodSignature
DocConstructorDocProperty
DocEnumDocPropertySignature
DocEnumMemberDocType
DocFunctionDocVariable
DocInterfaceTypescriptToMarkdown
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>) 
}
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>) 

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

Subsidiary documentation nodes when the node has members which are themselves represented as documentation nodes.

memberDocs: DocBase<ts.Node>[] = []

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 
    toMarkDown(docItem: DocItem<T>): string 
    toMarkDownTs(docItem: DocItem<T>): string 
    toMarkDownDetails(docItem: DocItem<T>): 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 
}
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>): string 

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>): string 
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 

Returns

typescript syntax to be added within a typescript syntax code block for this DocItem

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[] 
}

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[] 
}

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

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

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

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

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

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

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

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

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

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

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

Construct a new instance configured for run method to be called next.

constructor(public options: 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) 

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

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.

0.2.1

16 days ago

0.2.2

16 days ago

0.2.0

4 months ago

0.1.20

7 months ago

0.1.21

7 months ago

0.1.22

6 months ago

0.1.18

7 months ago

0.1.19

7 months ago

0.1.17

7 months ago

0.1.16

7 months ago

0.1.15

7 months ago

0.1.14

7 months ago

0.1.13

7 months ago

0.1.12

7 months ago

0.1.11

7 months ago

0.1.10

7 months ago

0.1.9

8 months ago

0.1.8

8 months ago

0.1.7

8 months ago

0.1.6

8 months ago

0.1.5

8 months ago

0.1.4

8 months ago

0.1.3

8 months ago

0.1.2

8 months ago

0.1.1

8 months ago

0.1.0

8 months ago