typedoc-better-json

Typedoc output transformer for generating docs for TypeScript libraries

TypeDoc's JSON output is extremely complex and hard to use for creating custom documentation websites. This library transforms it into a simpler, smaller, and organized JSON format that is easy to use for creating custom documentation websites

Simplified Types

TypeDoc outputs complex nested structures for TypeScript types. This library converts them into human-readable strings.

For example, TypeDoc output looks like this:

{
  "type": {
    "type": "reference",
    "target": { "qualifiedName": "RequiredParam" },
    "typeArguments": [{
      "type": "union",
      "types": [
        { "type": "literal", "value": null },
        { "type": "reference", "name": "NFTDrop" },
        { "type": "reference", "name": "SignatureDrop" },
        {
          "type": "reference",
          "name": "SmartContract",
          "typeArguments": [{
            "type": "reference",
            "name": "BaseContract"
          }]
        }
      ]
    }]
  }
}

Compare this with the output from typedoc-better-json:

{
  "type": "RequiredParam<null | NFTDrop | SignatureDrop | SmartContract<BaseContract>>"
}

Markdown Parsing

JSDoc comments are fully parsed into structured markdown AST, including code blocks, lists, headings, and inline formatting.

For Example, this JSDoc comment:

/**
 * Calculates the sum of two numbers
 *
 * @param a - First number
 * @param b - Second number
 * @returns The sum of both numbers
 *
 * @example
 * ```ts
 * import { sum } from "my-library";
 * sum(1, 2); // 3
 * ```
 *
 * @deprecated Use `fancySum` instead.
 */
export function sum(a: number, b: number) {
  return a + b;
}

Transforms into this JSON:

{
  "name": "sum",
  "signatures": [{
    "summary": [{
      "type": "paragraph",
      "children": [{ "type": "text", "value": "Calculates the sum of two numbers" }]
    }],
    "parameters": [
      { "name": "a", "type": "number", "summary": [{ "type": "text", "value": "First number" }] },
      { "name": "b", "type": "number", "summary": [{ "type": "text", "value": "Second number" }] }
    ],
    "returns": {
      "type": "number",
      "summary": [{ "type": "text", "value": "The sum of both numbers" }]
    },
    "blockTags": [
      {
        "tag": "@example",
        "summary": [{
          "type": "code",
          "lang": "ts",
          "value": "import { sum } from \"my-library\";\nsum(1, 2); // 3"
        }]
      },
      {
        "tag": "@deprecated",
        "summary": [{
          "type": "paragraph",
          "children": [
            { "type": "text", "value": "Use " },
            { "type": "inlineCode", "value": "fancySum" },
            { "type": "text", "value": " instead." }
          ]
        }]
      }
    ]
  }]
}

Organized Output

The output organizes your documentation by category - functions, hooks, components, types, variables, enums, and classes.

type TransformedDoc = {
  functions?: FunctionDoc[];
  hooks?: FunctionDoc[];
  components?: FunctionDoc[];
  types?: InterfaceDoc[];
  variables?: VariableDoc[];
  enums?: EnumDoc[];
  classes?: ClassDoc[];
};

Usage

import { transform } from "typedoc-better-json";
import { writeFile, readFile } from "node:fs/promises";

async function Example() {
  // read the JSON file generated by typedoc
  const fileContent = await readFile(
    "path/to/doc.json",
    "utf8",
  );

  // parse it
  const fileData = JSON.parse(fileContent);

  // transform it
  const transformedData = transform(fileData);

  // save it in file
  await writeFile(
    "path/to/transformed-doc.json",
    JSON.stringify(transformedData, null, 2),
  );
}