TypeDoc 主题定制 #

主题概述 #

TypeDoc 支持灵活的主题定制,你可以通过多种方式自定义文档的外观和样式。

text
┌─────────────────────────────────────────────────────────────┐
│                    主题定制方式                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 配置选项                                                │
│     ├── lightHighlightTheme                                │
│     └── darkHighlightTheme                                 │
│                                                             │
│  2. 自定义 CSS                                              │
│     └── 覆盖默认样式                                        │
│                                                             │
│  3. 第三方主题                                              │
│     └── 安装社区主题包                                      │
│                                                             │
│  4. 自定义主题                                              │
│     ├── 继承默认主题                                        │
│     └── 完全自定义                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

内置主题配置 #

代码高亮主题 #

TypeDoc 使用 Shiki 进行代码高亮,支持多种主题:

json
{
  "lightHighlightTheme": "github-light",
  "darkHighlightTheme": "github-dark"
}

可用的高亮主题:

主题名称 说明
light-plus VS Code 浅色主题(默认)
dark-plus VS Code 深色主题(默认)
github-light GitHub 浅色主题
github-dark GitHub 深色主题
vitesse-light Vitesse 浅色主题
vitesse-dark Vitesse 深色主题
min-light 极简浅色主题
min-dark 极简深色主题
nord Nord 主题
slack-ochin Slack 浅色主题
slack-dark Slack 深色主题

自定义颜色 #

通过 CSS 变量自定义颜色:

css
/* custom.css */
:root {
  --color-background: #ffffff;
  --color-text: #1a1a1a;
  --color-accent: #4f6bed;
  --color-link: #4f6bed;
  --color-code-background: #f5f5f5;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-background: #1a1a1a;
    --color-text: #e5e5e5;
    --color-accent: #7c93f5;
    --color-link: #7c93f5;
    --color-code-background: #2a2a2a;
  }
}

在配置中引用:

json
{
  "customCss": "./custom.css"
}

使用第三方主题 #

typedoc-theme-hierarchy #

层级结构的主题,适合大型项目:

bash
npm install --save-dev typedoc-theme-hierarchy

配置:

json
{
  "plugin": ["typedoc-theme-hierarchy"],
  "theme": "hierarchy"
}

typedoc-theme-justdocs #

简洁现代的主题:

bash
npm install --save-dev typedoc-theme-justdocs

配置:

json
{
  "plugin": ["typedoc-theme-justdocs"],
  "theme": "justdocs"
}

typedoc-neo-theme #

功能丰富的现代主题:

bash
npm install --save-dev typedoc-neo-theme

配置:

json
{
  "plugin": ["typedoc-neo-theme"],
  "theme": "neo"
}

自定义 CSS 样式 #

基本样式覆盖 #

创建自定义 CSS 文件:

css
/* custom.css */

/* 全局字体 */
body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}

/* 标题样式 */
h1, h2, h3 {
  font-weight: 600;
  color: #1a1a1a;
}

/* 链接样式 */
a {
  color: #4f6bed;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

/* 代码块样式 */
pre {
  border-radius: 8px;
  padding: 16px;
  background-color: #f8f9fa;
}

/* 导航样式 */
.tsd-navigation {
  font-size: 14px;
}

/* 搜索框样式 */
#tsd-search {
  border-radius: 8px;
}

#tsd-search input {
  border-radius: 8px;
  padding: 8px 12px;
}

深色模式支持 #

css
/* custom.css */

/* 浅色模式 */
:root {
  --color-background: #ffffff;
  --color-text: #1a1a1a;
  --color-text-aside: #666666;
  --color-link: #4f6bed;
  --color-accent: #4f6bed;
  --color-panel: #f5f5f5;
  --color-panel-divider: #e5e5e5;
  --color-comment-tag: #4f6bed;
  --color-code: #d73a49;
  --color-code-background: #f5f5f5;
}

/* 深色模式 */
@media (prefers-color-scheme: dark) {
  :root {
    --color-background: #0d1117;
    --color-text: #c9d1d9;
    --color-text-aside: #8b949e;
    --color-link: #58a6ff;
    --color-accent: #58a6ff;
    --color-panel: #161b22;
    --color-panel-divider: #30363d;
    --color-comment-tag: #58a6ff;
    --color-code: #ff7b72;
    --color-code-background: #161b22;
  }
}

/* 强制深色模式 */
[data-theme="dark"] {
  --color-background: #0d1117;
  --color-text: #c9d1d9;
}

响应式设计 #

css
/* custom.css */

/* 移动端适配 */
@media (max-width: 768px) {
  .container {
    padding: 0 16px;
  }
  
  .tsd-navigation {
    padding: 16px;
  }
  
  pre {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

/* 平板适配 */
@media (min-width: 769px) and (max-width: 1024px) {
  .container {
    max-width: 90%;
  }
}

自定义组件样式 #

css
/* custom.css */

/* 成员列表样式 */
.tsd-member {
  padding: 16px;
  border-radius: 8px;
  margin-bottom: 8px;
  background-color: var(--color-panel);
}

/* 参数表格样式 */
.tsd-parameters-table {
  width: 100%;
  border-collapse: collapse;
}

.tsd-parameters-table th,
.tsd-parameters-table td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--color-panel-divider);
}

/* 类型签名样式 */
.tsd-signature {
  font-family: 'JetBrains Mono', monospace;
  font-size: 14px;
  padding: 12px 16px;
  border-radius: 6px;
  background-color: var(--color-code-background);
}

/* 徽章样式 */
.tsd-flag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
}

.tsd-flag.tsd-flag-private {
  background-color: #ff4757;
  color: white;
}

.tsd-flag.tsd-flag-protected {
  background-color: #ffa502;
  color: white;
}

.tsd-flag.tsd-flag-readonly {
  background-color: #2ed573;
  color: white;
}

.tsd-flag.tsd-flag-static {
  background-color: #3742fa;
  color: white;
}

创建自定义主题 #

主题项目结构 #

text
my-typedoc-theme/
├── src/
│   ├── index.ts           # 主题入口
│   ├── theme.ts           # 主题类
│   ├── templates/         # 模板文件
│   │   ├── index.hbs
│   │   ├── member.hbs
│   │   └── partials/
│   │       ├── header.hbs
│   │       ├── navigation.hbs
│   │       └── footer.hbs
│   └── assets/
│       └── style.css      # 样式文件
├── package.json
└── tsconfig.json

主题入口文件 #

typescript
// src/index.ts
import { Application, Theme } from 'typedoc';
import { MyTheme } from './theme';

export function load(app: Application) {
  app.renderer.defineTheme('my-theme', MyTheme);
}

export { MyTheme };

主题类 #

typescript
// src/theme.ts
import {
  DefaultTheme,
  DefaultThemeRenderContext,
  Reflection,
  PageEvent
} from 'typedoc';

export class MyTheme extends DefaultTheme {
  getRenderContext(pageEvent: PageEvent<Reflection>) {
    return new MyThemeRenderContext(
      this,
      pageEvent,
      this.application.options
    );
  }
}

class MyThemeRenderContext extends DefaultThemeRenderContext {
  // 覆盖默认方法
  override header = () => {
    return `
      <header class="custom-header">
        <div class="container">
          <a href="${this.relativeURL('index.html')}" class="logo">
            ${this.project?.name || 'Documentation'}
          </a>
          <nav class="nav-links">
            <a href="https://github.com">GitHub</a>
            <a href="https://npmjs.com">NPM</a>
          </nav>
        </div>
      </header>
    `;
  };

  override footer = () => {
    return `
      <footer class="custom-footer">
        <div class="container">
          <p>© ${new Date().getFullYear()} My Company. All rights reserved.</p>
        </div>
      </footer>
    `;
  };
}

模板文件 #

handlebars
{{! src/templates/index.hbs }}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{{project.name}}</title>
  <link rel="stylesheet" href="{{relativeURL 'assets/style.css'}}">
</head>
<body>
  {{> header}}
  
  <main class="container">
    <aside class="sidebar">
      {{> navigation}}
    </aside>
    
    <article class="content">
      {{{contents}}}
    </article>
  </main>
  
  {{> footer}}
  
  <script src="{{relativeURL 'assets/main.js'}}"></script>
</body>
</html>

部分模板 #

handlebars
{{! src/templates/partials/navigation.hbs }}
<nav class="tsd-navigation">
  <ul>
    {{#each navigation.children}}
      <li>
        <a href="{{relativeURL url}}">{{title}}</a>
        {{#if children}}
          <ul>
            {{#each children}}
              <li>
                <a href="{{relativeURL url}}">{{title}}</a>
              </li>
            {{/each}}
          </ul>
        {{/if}}
      </li>
    {{/each}}
  </ul>
</nav>

发布主题包 #

json
// package.json
{
  "name": "typedoc-theme-my",
  "version": "1.0.0",
  "description": "Custom TypeDoc theme",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "keywords": ["typedoc", "theme"],
  "peerDependencies": {
    "typedoc": ">=0.25.0"
  },
  "files": [
    "dist"
  ],
  "scripts": {
    "build": "tsc",
    "prepublishOnly": "npm run build"
  }
}

高级定制 #

自定义渲染器 #

typescript
// custom-renderer.ts
import {
  Application,
  Renderer,
  Theme,
  PageEvent,
  Reflection,
  ProjectReflection
} from 'typedoc';

class CustomRenderer extends Renderer {
  constructor(app: Application) {
    super(app);
    
    // 监听渲染事件
    this.on(PageEvent.BEGIN, this.onPageBegin);
    this.on(PageEvent.END, this.onPageEnd);
  }

  private onPageBegin(page: PageEvent<Reflection>) {
    // 在页面渲染前执行
    console.log(`Rendering: ${page.url}`);
  }

  private onPageEnd(page: PageEvent<Reflection>) {
    // 在页面渲染后执行
    // 可以修改生成的 HTML
    page.contents = this.processHtml(page.contents || '');
  }

  private processHtml(html: string): string {
    // 自定义 HTML 处理
    return html.replace(
      /<pre>/g,
      '<pre class="custom-code-block">'
    );
  }
}

自定义输出 #

typescript
// custom-output.ts
import {
  Application,
  Reflection,
  ProjectReflection,
  Serializer
} from 'typedoc';

export function generateCustomOutput(
  app: Application,
  project: ProjectReflection
) {
  // 自定义 JSON 输出
  const serializer = new Serializer();
  const data = serializer.projectToObject(project);
  
  // 添加自定义字段
  const customData = {
    ...data,
    generatedAt: new Date().toISOString(),
    version: app.options.getValue('version'),
    customField: 'custom value'
  };
  
  // 写入文件
  const fs = require('fs');
  fs.writeFileSync(
    'docs/custom-api.json',
    JSON.stringify(customData, null, 2)
  );
}

Markdown 输出 #

使用 typedoc-plugin-markdown 插件:

bash
npm install --save-dev typedoc-plugin-markdown

配置:

json
{
  "plugin": ["typedoc-plugin-markdown"],
  "theme": "markdown",
  "out": "docs/markdown"
}

自定义 Markdown 输出:

json
{
  "plugin": ["typedoc-plugin-markdown"],
  "theme": "markdown",
  "out": "docs/markdown",
  "entryDocument": "README.md",
  "hideInPageTOC": true,
  "hideBreadcrumbs": true,
  "hidePageHeader": true,
  "indexFormat": "table",
  "memberFormat": "table"
}

样式最佳实践 #

使用 CSS 变量 #

css
/* variables.css */
:root {
  /* 颜色 */
  --color-primary: #4f6bed;
  --color-secondary: #6c757d;
  --color-success: #28a745;
  --color-warning: #ffc107;
  --color-danger: #dc3545;
  
  /* 字体 */
  --font-sans: 'Inter', sans-serif;
  --font-mono: 'JetBrains Mono', monospace;
  
  /* 间距 */
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;
  
  /* 圆角 */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  
  /* 阴影 */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
}

响应式设计 #

css
/* responsive.css */

/* 移动优先 */
.container {
  width: 100%;
  padding: 0 var(--spacing-md);
}

/* 平板 */
@media (min-width: 768px) {
  .container {
    max-width: 720px;
    margin: 0 auto;
  }
}

/* 桌面 */
@media (min-width: 1024px) {
  .container {
    max-width: 960px;
  }
}

/* 大屏 */
@media (min-width: 1280px) {
  .container {
    max-width: 1200px;
  }
}

无障碍支持 #

css
/* accessibility.css */

/* 焦点样式 */
:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* 跳转链接 */
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  padding: var(--spacing-sm) var(--spacing-md);
  background: var(--color-primary);
  color: white;
  z-index: 100;
}

.skip-link:focus {
  top: 0;
}

/* 减少动画 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

下一步 #

现在你已经掌握了 TypeDoc 的主题定制方法,接下来学习 插件扩展,了解如何使用和开发 TypeDoc 插件!

最后更新:2026-03-29