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