npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ts2md

v0.2.2

Published

Simple Typescript Documentation Generator to GitHub Compatible MarkDown

Downloads

278

Readme

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

| | | | --- | --- | | DocBase | DocMethod | | DocClass | DocMethodSignature | | DocConstructor | DocProperty | | DocEnum | DocPropertySignature | | DocEnumMember | DocType | | DocFunction | DocVariable | | DocInterface | TypescriptToMarkdown | | 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.