Fixing typedoc's generated TOC if your code is using ES6 modules

My one policy about blogging is “write the blog post you wanted to find in the search results”. I spent an inordinate amount of time yesterday trying to get typedoc to only show the docs for the files I’m actually exporting in my library, and didn’t find anything on the internet to help me, so here is the blog post I wanted to read.

The problem

You are working on a JS library. You author your source in TypeScript. You have an index.ts file that exports only some of your source files. You would like your generated docs from typedoc to only have docs for those files (Why? So that people don’t open issues along the lines of “I see the docs for function foo, but I can’t see how to call it, pls export it”. Sweet child, if that function was meant to be public it probably would’ve been. That function is actually 3 spiders in a trench coat).

That is, you would like your Table of Contents to show this: toc only shows 5 entries

and not this: toc shows every file under the sun

Things that aren’t solutions

In the order that I’ve tried them:

My “solution”

I’m less bothered that the docs for the private files get generated at all, and more bothered that they’re linked in the main page TOC and thus discoverable. So my “solution” that “fixes” it is: inject some JavaScript that hides all the files that aren’t exported in the top level index.ts. It’s gross, but it’s good enough (Also: the title of my autobiography).

Disclaimer: This works for for my library (here’s the PR I’m blessing our code with this horror), but for your particular setup it might need some changes. I speak very broken bash, so I probably can’t help you with those changes.

# Variables I have:
# Where your source is. We call the script from a different
# place than the index.ts but maybe you don't.
srcDir="..."

# Where you generate the docs. This could be a /docs folder, or a temp one
# because you're going to push to the GitHub gh-pages branch.
# I don't know what you do, I only know what we do (the latter).
docsDir="..."

# The root index.ts file has a bunch of "export * from './foo';" lines.
# Parse those lines into a space separated list of names. It's ok that
# they're space separated, we'll split them in JS,
# this is all a horror anyway. You might have to touch these regexes, sry.
exports=`sed -n "s/export \* from '.\/\(.*\)';/\1/p" $srcDir/src/index.ts`

# If your theme uses a different td class name than the one below,
# inspecting it and update it in the selector. Also my names had
# a bunch of extra quotes, hence the replacing, yours might not.
# This is why I don't want to maintain this.
scriptToFixTheToc="<script> \
const toc = \"$exports\".split(' '); \
const links = document.querySelectorAll('.tsd-kind-external-module'); \
for (let i = 0; i < links.length; i++) { \
  const name = links[i].textContent.trim().replace(/\"/g, ''); \
  if (toc.indexOf(name) === -1) { \
    links[i].parentNode.removeChild(links[i]); \
  } \
} \
</script>"

# Inject that script in the index.html.
echo $scriptToFixTheToc >> $docsDir/index.html

# Pray.



Like sands through the hourglass so are the hacks of our lives.