Hannikainen's blog

Snippet: Render TypeDoc module members on same page

TypeDoc by default renders all functions, variables etc. on different pages. This custom theme renders module and namespace members on the same page.


// filename: ./typedoc-theme/index.ts
// compile with:
// npx tsc --target esnext --module commonjs --moduleresolution node --esmoduleinterop index.ts
import { Application, DeclarationReflection, DefaultTheme, ReflectionKind, UrlMapping } from 'typedoc';

export class Theme extends DefaultTheme {
    buildUrls(reflection: DeclarationReflection, urls: UrlMapping[]): UrlMapping[] {
        if (reflection.kind === ReflectionKind.Project) return super.buildUrls(reflection, urls);
        if (reflection.kind === ReflectionKind.Namespace || reflection.kind === ReflectionKind.Module) {
            const mapping = super['getMapping'](reflection);
            if (!reflection.url || !DefaultTheme.URL_PREFIX.test(reflection.url)) {
                const url = [mapping.directory, DefaultTheme.getUrl(reflection) + '.html'].join('/');
                urls.push(new UrlMapping(url, reflection, mapping.template));

                reflection.url = url;
                reflection.hasOwnDocument = true;
            reflection.traverse((child) => {
                DefaultTheme.applyAnchorUrl(child, reflection);
            return super.buildUrls(reflection, urls);

        return urls;

export function load(app: Application) {
    app.renderer.defineTheme('mydefault', Theme);


    "entryPoints": ["src"],
    "entryPointStrategy": "expand",
    "out": "docs",
    "plugin": ["./typedoc-theme/index.js"],
    "theme": "mydefault"

The buildUrls function is mostly equivalent to https://github.com/TypeStrong/typedoc/blob/30e614cd9e7b5a154afa6a78f2e54f16550bfb4f/src/lib/output/themes/default/DefaultTheme.tsx#L222

The original function is licensed under Apache 2. Any modifications done are under CC0 https://creativecommons.org/public-domain/cc0/ – feel free to use as you see fit.

Copyright (c) 2024 Jaakko Hannikainen