DEV Community

Cover image for And so, I wrote my own Typescript Documentation Generator...
Zuri Klaschka (they/them) for fliegwerk

Posted on

And so, I wrote my own Typescript Documentation Generator...

TL;DR: For a project fussel178 and I (pklaschka) were working on, we needed a documentation generator for a Typescript Monorepo.

The "Status Quo"

While the existing solution, TypeDoc, is a great tool, it didn't really fit our needs, and documentation on how to customize the output isn't easy to come by. Don't get me wrong: It's a great project that does a lot more than my own solution, but it simply didn't fit our project's needs. Still, for many projects, it works great, and I can highly recommend checking it out:

GitHub logo TypeStrong / typedoc

Documentation generator for TypeScript projects.

So... let's build it ourselves 😜

After spending a day searching for alternatives (unsuccessfully), I decided to "just" build my own solution. And thus, fliegdoc found its beginning πŸ˜‰

GitHub logo fliegwerk / fliegdoc

A documentation generator for Typescript-based libraries with good support for monorepos

Welcome to fliegdoc πŸ‘‹

Version Prerequisite Documentation Maintenance License: MIT Twitter: pklaschka2000

A documentation generator for Typescript-based libraries with good support for monorepos

🏠 Homepage, Demo & Docs

Prerequisites

  • node >12.0.0

Install

npm install --global fliegdoc
Enter fullscreen mode Exit fullscreen mode

Usage

CLI

$ fliegdoc --help
Usage: fliegdoc [command] [options]

Commands:
  fliegdoc build [options]  Build the documentation       [default] [aliases: b]
  fliegdoc serve [options]  Preview the documentation in the browser[aliases: s]
  fliegdoc completion       generate completion script

Options:
      --help     Show help                                             [boolean]
  -s, --serve    Serve the static files after build   [boolean] [default: false]
  -p, --port     The port on which the documentation gets hosted        [number]
  -v, --version  Show version number                                   [boolean]

Get help for individual commands by running fliegdoc <command> --help
Enter fullscreen mode Exit fullscreen mode

The CLI searches for a fliegdoc.config.js file and applies its options on top of the default options.

Example fliegdoc.config.js with default options

// fliegdoc.config.js
const { HTMLTheme } = require('fliegdoc');
module.exports = {
    baseUrl: '/'
…
Enter fullscreen mode Exit fullscreen mode

What fliegdoc is

fliegdoc documents only the exported members (!) of a TypeScript library, i.e., one or more (in the case of a monorepo) npm packages.

It first converts the source file's AST to a kind of "documentation-ready" AST, which then gets passed to a theme, converting it to HTML (but, if the theme gets adjusted, also any other format).

The generated web page then includes the project's root README.md, and the API References for the project's modules, i.e., packages.

Therefore, it can very easily be used to document mono-repo structures, including more than one package.

Demo

Since the project's exposed APIs themselves are documented using the project itself, you can visit the project documentation to see the generated results.

How to use it

Let's consider a Lerna-based monorepo with (for simplicity) two packages, resulting in a folder structure that looks something like this:

.
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ package-1/
β”‚   β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”‚   └── main.ts
β”‚   β”‚   β”œβ”€β”€ package.json
β”‚   β”‚   └── tsconfig.json
β”‚   └── package-2/
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   └── main.ts
β”‚       β”œβ”€β”€ package.json
β”‚       └── tsconfig.json
β”œβ”€β”€ package.json
β”œβ”€β”€ lerna.json
β”œβ”€β”€ README.md
└── tsconfig.json
Enter fullscreen mode Exit fullscreen mode

Since fliegdoc generates the documentation for the entire repository, we add fliegdoc as a devDependency of the root package.json:

$ npm i -D fliegdoc
Enter fullscreen mode Exit fullscreen mode

Next, we add two scripts in our root package.json:

{
  "scripts": {
    "docs:build": "fliegdoc build",
    "docs:serve": "fliegdoc serve"
  }
}
Enter fullscreen mode Exit fullscreen mode

If our repository followed an easy structure, with just one root tsconfig.json, package.json, README.md, and a main.ts in a root src folder, that all we'd need to do. However, we are within a monorepo that ... makes things a bit more complicated.

"Things should be made as simple as possible but not any simpler" (Albert Einstein)

To configure fliegdoc to work with this repo structure, we create a fliegdoc.config.js:

module.exports = {
  modules: [
    {
      package: "./packages/package-1/package.json",
      tsconfig: "./packages/package-1/tsconfig.json",
      mainFile: "main.ts",
    },
    {
      package: "./packages/package-2/package.json",
      tsconfig: "./packages/package-2/tsconfig.json",
      mainFile: "main.ts",
    },
  ]
};
Enter fullscreen mode Exit fullscreen mode

While we could configure many other parameters, we can already successfully generate the documentation for the repo with this config.

Further configuration options
Among others, see https://fliegwerk.github.io/fliegdoc/fliegdoc/#FliegdocConfig for a full reference:
  • readme = './README.md': The path to the repo's README.md
  • outDir = './docs': The directory into which the docs get generated
  • baseUrl = '/': the root URL of the documentation. Useful when you want to deploy your projects to subdirectories on your server, e.g., on GitHub pages (where /[repo-name]/ gets prefixed to the URL, compared to /).

We can now run

$ npm run docs:serve
Enter fullscreen mode Exit fullscreen mode

fliegdoc, when running fliegdoc serve, does a few things:

  1. Read the config and apply its overrides to the default configuration
  2. Go through the modules specified in the config and parse the exported members of their mainFile
  3. Build a "documentation-ready syntax tree", consisting only of abstracted elements interesting for the docs, from the parsed AST
  4. Serve a site that consists of pages for
    • the project's README.md
    • API references for the modules

When instead of docs:serve, we run the docs:build script, the only difference will be that in step (4.), the site won't just be served on an HTTP server, but instead, the HTML files get built and outputted to a folder ./docs, which then can get deployed to, e.g., GitHub Pages, Netlify, or a "classic" web server.

What fliegdoc isn't

It isn't an "all-around" documentation generator for Typescript. It specializes heavily (!) in documenting package modules and has a focus on being easy to understand (the "basic" project was developed in only one day).

Conclusion

While the project is still in a rather early stage of development, and documentation is, right now, WIP (the irony 🀣), it already serves its purpose in multiple of my own projects, without problems.

Perhaps, its use-case also fits your project, in which case, please feel free to share any feature requests should you decide to use it.

It was certainly interesting to dive a bit deeper into the ASTs and other "lower-level" Typescript things apart from everything else.

Author

Pablo Klaschka is the first chairman and co-founder of fliegwerk, a group of students developing Open-Source projects.

Top comments (1)

Collapse
 
rxliuli profile image
rxliuli • Edited

Very monorepo friendly, but still has some issues

  • Only supports > nodejs 15 (which is quite unreasonable, as it is unlikely that anyone in a production environment will be using the latest non-long term support version)
  • Themes are rather rudimentary, and there is no detailed guide to creating them
  • No link to unit tests (which is rather bad for providing some test cases)

Overall though, it's still much easier than typedoc monorepo, and if I have time, I'll make some contributions