zudo-doc
GitHub repository

Type to search...

to open search from anywhere

TOC Export

Created May 28, 2026Updated Jul 24, 2026Takeshi Takatsudo

Exports the page table-of-contents as an `export const toc` named export.

The tocExport feature walks a document's headings and injects an MDX named export — export const toc — at the top of each processed file, giving sidebar and floating-TOC components a structured table-of-contents.

Requires zfb 0.1.0-next.14 or newer

Enabling tocExport broke the build at zfb 0.1.0-next.13: the injected export const toc = [...] line was emitted at an indented column, so MDX parsed it as content rather than an ESM export, producing ~153 esbuild Expected "}" errors across the corpus (#1814). It is fixed in zfb 0.1.0-next.14 (upstream Takazudo/zudo-front-builder#599 — the export is now hoisted to column 0) and is enabled in zudo-doc's zfb.config.ts. Every page in this corpus, including this one, now carries a real export const toc.

Configuration

zudoDoc() includes tocExport: {} in the standard preset — no separate configuration field is necessary for the default maxDepth: 3. (It is an object-typed feature — the true shorthand is rejected — so the preset always passes {}, never true.)

zfb.config.ts
import { defineConfig } from "zfb/config";
import { zudoDoc } from "@takazudo/zudo-doc/config";

export default defineConfig(
  zudoDoc({
    siteName: "My Docs",
  }),
);

To limit the heading depth, spread the preset's markdown.features and override tocExport — a bare defineConfig({ markdown: { features } }) would discard the rest of the preset:

zfb.config.ts
const base = zudoDoc({
  // ...your project settings
});

export default defineConfig({
  ...base,
  markdown: {
    ...base.markdown,
    features: {
      ...base.markdown.features,
      tocExport: { maxDepth: 2 },
    },
  },
});

Options

OptionDefaultDescription
maxDepth3Maximum heading depth (absolute, 2–6). 2 = h2 only; 3 = h2 + h3.

Exported shape

The feature injects an export const toc whose entries follow this type:

type TocEntry = {
  depth: number; // absolute heading depth: 2 | 3 | 4 | 5 | 6
  id: string; // slug assigned by the heading-links pass
  text: string; // plain-text heading content (hash-link stripped)
  children: TocEntry[]; // nested sub-headings within maxDepth
};

Example output

For a document with h2 and h3 headings, the injected export looks like:

export const toc = [
  {
    depth: 2,
    id: "introduction",
    text: "Introduction",
    children: [{ depth: 3, id: "introduction-background", text: "Background", children: [] }],
  },
  { depth: 2, id: "conclusion", text: "Conclusion", children: [] },
];

The nested id: "introduction-background" reflects zudo-doc's hierarchical heading IDs: the h3 id is prefixed with its h2 ancestor.

Notes

  • The export runs after the heading-links pass, so the id slugs are final, deduplicated, and follow the hierarchical ID contract.

  • tocExport works independently of Heading Marker TOC — enabling one does not interfere with the other.

  • zudo-doc's existing TOC island is not driven by this export; the two are separate mechanisms.

Revision History

Takeshi TakatsudoCreated: 2026-05-29T01:44:41+09:00Updated: 2026-07-25T02:57:49+09:00

AI Assistant

Ask a question about the documentation.

Preview theme

Loading theme previews…