nkds

导航

 

MonkeyCode 开源项目的文档自动化:从代码到文档的全链路自动化实践

引言

在开源软件开发中,文档(Documentation) 是连接代码与用户的桥梁。然而,维护高质量文档往往成为开发团队的沉重负担。作为一款支持私有化部署的 AI 编程工具,MonkeyCode 通过构建完整的文档自动化体系,实现了"代码即文档、变更即更新"的高效模式。本文将全面分享 MonkeyCode 的文档自动化实践经验。

GitHub Issue 邀请:如果您在文档工程、API 文档生成或技术写作自动化方面有任何问题或建议,欢迎前往 MonkeyCode GitHub 仓库 提交 Issue 或参与讨论!


一、为什么需要文档自动化?

1.1 传统文档维护的痛点

┌─────────────────────────────────────────────────────────────┐
│           ❌ 传统文档维护的典型困境                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  开发者改了代码 → 忘记更新文档 → 文档与实现不一致              │
│       ↓                                                      │
│  新人看文档照做 → 发现行不通 → 浪费时间排查                    │
│       ↓                                                      │
│  用户按文档操作 → 遇到错误 → 信任度下降                        │
│       ↓                                                      │
│  维护者手动更新 → 繁琐易错 → 越来越不想写文档                  │
│                                                             │
│  💥 恶性循环:文档越旧 → 越没人用 → 越没人维护 → 更旧         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.2 文档自动化的核心价值

维度 手动维护 自动化
时效性 滞后数天到数周 实时/分钟级同步
准确性 容易遗漏和出错 与代码保持一致
维护成本 高(每次手动更新) 低(CI 自动触发)
覆盖率 核心功能有文档 全量 API + 示例
多语言 需要人工翻译 i18n 自动生成

二、MonkeyCode 文档体系架构

2.1 四层文档金字塔

                    ┌─────────────────────────────────┐
                    │    MonkeyCode 文档体系            │
                    └──────────────┬──────────────────┘
                                   │
        ┌──────────────────────────┼──────────────────────────┐
        ▼                          ▼                          ▼
┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐
│   📖 L1 用户文档  │    │   📚 L2 开发文档  │    │   🔧 L3 运维文档  │
│                │    │                │    │                │
│• 快速入门指南    │    │• API 参考文档    │    │• 部署指南        │
│• 使用教程        │    │• SDK 文档        │    │• 配置参考        │
│• 常见问题 FAQ   │    │• 架构设计文档    │    │• 运维手册        │
│• 最佳实践        │    │• 贡献指南        │    │• 故障排查        │
│• 视频教程        │    │• 代码示例库      │    │• 监控告警        │
└──────────────────┘    └──────────────────┘    └──────────────────┘
                                   │
                                   ▼
                         ┌──────────────────┐
                         │   🤖 L4 自动生成  │
                         │                │
                         │• API 文档自动生成 │
                         │• Changelog 自动  │
                         │• 类型定义导出    │
                         │• 代码注释→文档   │
                         └──────────────────┘

2.2 文档类型与工具映射

documentation_types:

  api_reference:
    name: "API 参考文档"
    source: "OpenAPI Spec / TypeScript 类型"
    tool: "Scalar / Swagger UI"
    auto_generate: true
    update_trigger: "PR 合并到 main 时自动更新"
    url: "https://docs.monkeyCode.dev/api"
    
  user_guide:
    name: "用户使用指南"
    source: "Markdown + MDX 组件"
    tool: "VitePress (Docusaurus)"
    auto_generate: false  # 人工编写为主
    review_process: "Technical Writer Review"
    url: "https://docs.monkeyCode.dev/guide"
    
  sdk_documentation:
    name: "SDK 文档"
    source: "TypeDoc / JSDoc 注释"
    tool: "TypeDoc + Storybook"
    auto_generate: true
    update_trigger: "包发布时同步更新"
    url: "https://docs.monkeyCode.dev/sdk"
    
  architecture_docs:
    name: "架构设计文档"
    source: "Markdown + Mermaid 图表"
    tool: "MkDocs Material"
    auto_generate: "partial"  # 部分自动
    update_trigger: "重大架构变更时更新"
    url: "https://docs.monkeyCode.dev/architecture"
    
  changelog:
    name: "变更日志"
    source: "Git Commit History + PR 信息"
    tool: "Release Drafter / Changesets"
    auto_generate: true
    update_trigger: "每次 Release 时自动生成"
    url: "https://github.com/monkeyCode/releases"

三、API 文档自动化

3.1 OpenAPI 规范驱动

// src/lib/openapi-generator.ts — MonkeyCode OpenAPI 文档生成器
import type { OpenAPI3 } from 'openapi-typescript';
import { generateTypeScriptTypes } from 'openapi-typescript';
import { writeFileSync, mkdirSync } from 'fs';
import { resolve } from 'path';

interface EndpointInfo {
  method: string;
  path: string;
  summary: string;
  description: string;
  tags: string[];
  parameters: Parameter[];
  requestBody?: RequestBody;
  responses: Record<string, Response>;
}

// 从路由定义自动提取 OpenAPI Spec
export async function generateOpenAPISpec(): Promise<OpenAPI3> {
  const routes = await import('@/api/routes');
  
  const spec: OpenAPI3 = {
    openapi: '3.1.0',
    info: {
      title: 'MonkeyCode API',
      version: process.env.npm_package_version ?? '0.0.0',
      description: 'MonkeyCode AI Programming Assistant RESTful API',
      contact: {
        name: 'MonkeyCode Team',
        email: 'api@monkeyCode.dev',
        url: 'https://monkeyCode.dev',
      },
      license: {
        name: 'Apache-2.0',
        url: 'https://www.apache.org/licenses/LICENSE-2.0',
      },
    },
    servers: [
      {
        url: 'https://api.monkeyCode.dev/v1',
        description: 'Production',
      },
      {
        url: 'https://staging-api.monkeyCode.dev/v1',
        description: 'Staging',
      },
    ],
    paths: {},
    components: {
      securitySchemes: {
        bearerAuth: {
          type: 'http' as const,
          scheme: 'bearer',
          bearerFormat: 'JWT',
          description: 'JWT Bearer Token authentication',
        },
        apiKey: {
          type: 'apiKey' as const,
          in: 'header' as const,
          name: 'X-API-Key',
          description: 'API Key for programmatic access',
        },
      },
      schemas: {},
    },
    tags: [
      { name: 'Auth', description: 'Authentication and authorization' },
      { name: 'AI', description: 'AI-powered code generation and analysis' },
      { name: 'Code', description: 'Code analysis and manipulation' },
      { name: 'Git', description: 'Git operations integration' },
      { name: 'User', description: 'User management' },
    ],
  };

  // 遍历所有路由,自动构建 paths
  for (const route of Object.values(routes)) {
    const endpoint: EndpointInfo = route.openapiMeta;
    
    if (!spec.paths[endpoint.path]) {
      spec.paths[endpoint.path] = {};
    }
    
    spec.paths[endpoint.path][endpoint.method.toLowerCase()] = {
      summary: endpoint.summary,
      description: endpoint.description,
      tags: endpoint.tags,
      parameters: endpoint.parameters,
      requestBody: endpoint.requestBody,
      responses: endpoint.responses,
      // 安全要求
      ...(endpoint.authRequired ? {
        security: [{ bearerAuth: [] }, { apiKey: [] }],
      } : {}),
    };
    
    // 收集 schema 定义
    if (endpoint.requestBody?.content?.['application/json']?.schema) {
      collectSchemas(spec, endpoint.requestBody.content['application/json'].schema);
    }
  }

  return spec;
}

// 生成 TypeScript 类型定义
export async function generateClientTypes(spec: OpenAPI3): Promise<void> {
  const output = await generateTypeScriptTypes(JSON.stringify(spec));
  
  mkdirSync(resolve(__dirname, '../generated'), { recursive: true });
  writeFileSync(
    resolve(__dirname, '../generated/api.types.ts'),
    `/**
 * 🤖 Auto-generated by MonkeyCode OpenAPI Generator
 * DO NOT EDIT MANUALLY - This file is regenerated on every build
 * Generated at: ${new Date().toISOString()}
 */
${output}`
  );
}

3.2 CI/CD 中自动部署文档站点

# .github/workflows/docs-deploy.yml — MonkeyCode 文档自动部署
name: 📚 Docs Auto Deploy

on:
  push:
    branches: [main]
    paths:
      - 'docs/**'
      - 'src/api/**'
      - 'package.json'  # 版本变化可能影响文档
  pull_request:
    branches: [main]
    paths:
      - 'docs/**'

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  # ════════════════════════════════════
  # Job 1: 生成 API 文档
  # ════════════════════════════════════
  generate-api-docs:
    name: 🔧 Generate API Docs
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: pnpm/action-setup@v4
        with: { version: 9 }
      
      - uses: actions/setup-node@v4
        with: { node-version: 20, cache: 'pnpm' }
      
      - run: pnpm install --frozen-lockfile
      
      - name: Build project (to extract types)
        run: pnpm build
      
      - name: Generate OpenAPI Spec
        run: pnpm docs:generate-api
      
      - name: Generate TypeDoc
        run: pnpm docs:generate-typedoc
      
      - name: Upload generated docs
        uses: actions/upload-artifact@v4
        with:
          name: api-docs
          path: |
            docs/.vitepress/dist/
            openapi.json
            typedoc/

  # ════════════════════════════════════
  # Job 2: 构建并部署 VitePress 文档站
  # ════════════════════════════════════
  deploy-docs:
    name: 🚀 Deploy Docs Site
    runs-on: ubuntu-latest
    needs: generate-api-docs
    if: github.ref == 'refs/heads/main'
    
    environment:
      name: github-pages
      url: ${{ steps.deploy.outputs.page_url }}
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: pnpm/action-setup@v4
        with: { version: 9 }
      
      - uses: actions/setup-node@v4
        with: { node-version: 20, cache: 'pnpm' }
      
      - run: pnpm install --frozen-lockfile
      
      - name: Download generated API docs
        uses: actions/download-artifact@v4
        with:
          name: api-docs
          path: docs/.vitepress/dist/
      
      - name: Build VitePress site
        working-directory: docs
        run: |
          pnpm install --frozen-lockfile
          pnpm docs:build
      
      - name: Deploy to GitHub Pages
        id: deploy
        uses: actions/deploy-pages@v4
        with:
          artifact_name: docs-site
          path: docs/.vitepress/dist/

  # ════════════════════════════════════
  # Job 3: PR 预览文档站
  # ════════════════════════════════════
  preview-docs:
    name: 👀 Preview Docs (PR)
    runs-on: ubuntu-latest
    needs: generate-api-docs
    if: github.event_name == 'pull_request'
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: pnpm/action-setup@v4
        with: { version: 9 }
      
      - uses: actions/setup-node@v4
        with: { node-version: 20, cache: 'pnpm' }
      
      - run: pnpm install --frozen-lockfile && pnpm build
      
      - name: Download generated API docs
        uses: actions/download-artifact@v4
        with:
          name: api-docs
          path: docs/.vitepress/dist/
      
      - name: Build preview
        working-directory: docs
        run: pnpm install --frozen-lockfile && pnpm docs:build
      
      - name: Deploy preview
        uses: rossjrw/action-preview-pages@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          source_dir: docs/.vitepress/dist

四、Changelog 自动生成

4.1 Changesets 工作流配置

// .changeset/config.json — MonkeyCode Changeset 配置
{
  "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
  "changelog": [
    "@changesets/changelog-github",
    {
      "repo": "monkeyCode/monkeyCode",
      "title": "🎉 MonkeyCode v${release.version} Release Notes",
      "header": "---\ndate: ${new Date().toISOString().split('T')[0]}\n---\n\n",
      "templates": {
        "fix": "### 🐛 Bug Fixes\n{{#each fixes}}\n- {{message}} ({{commit}})\n{{/each}}\n",
        "feat": "### ✨ Features\n{{#each features}}\n- {{message}} ({{commit}})\n{{/each}}\n",
        "perf": "### ⚡ Performance\n{{#each performanceChanges}}\n- {{message}} ({{commit}})\n{{/each}}\n",
        "docs": "### 📝 Documentation\n{{#each documentationChanges}}\n- {{message}} ({{commit}})\n{{/each}}\n",
        "deps": "### 🔧 Dependencies\n{{#each dependencyUpdates}}\n- Updated {{updateGroup}}{{#if withRange}} to {{withRange}}{{/if}}\n{{/each}}\n",
        "breaking": "### 💥 Breaking Changes\n{{#each breakingChanges}}\n- {{message}} ({{commit}})\n{{/each}}\n\n> ⚠️ Please review migration guide before upgrading.\n",
        "contributors": "### ❤️ Contributors\nThank you to all contributors!\n{{#each contributors}}\n- @{{username}}\n{{/each}}\n"
      }
    }
  ],
  "commit": false,
  "fixed": [],
  "linked": [],
  "access": "public",
  "baseBranch": "main",
  "updateInternalDependencies": "patch",
  "ignore": ["monkeyCode-website", "monkeyCode-docs"]
}

4.2 自动 Changelog 生成脚本

// scripts/generate-changelog.ts — MonkeyCode Changelog 生成器
import { execSync } from 'child_process';
import * as fs from 'fs';

interface ChangelogEntry {
  type: 'feat' | 'fix' | 'docs' | 'perf' | 'refactor' | 'chore' | 'break';
  scope: string;
  message: string;
  pr: number;
  author: string;
  breaking?: boolean;
}

function getCommitsSinceTag(tag: string): ChangelogEntry[] {
  const log = execSync(
    `git log ${tag}..HEAD --pretty=format:"%H|%s|%an|%b"`,
    { encoding: 'utf-8' }
  );
  
  return log.split('\n')
    .filter(Boolean)
    .map(line => {
      const [hash, subject, author, body] = line.split('|');
      const prMatch = subject.match(/\(#(\d+)\)/);
      const pr = prMatch ? parseInt(prMatch[1]) : 0;
      
      // 解析 conventional commit
      const typeMatch = subject.match(/^(feat|fix|docs|perf|refactor|chore)(\(.+\))?(.*)?$/);
      if (!typeMatch) return null;
      
      const [, type, rawScope, message] = typeMatch;
      const scope = rawScope ? rawScope.slice(1, -1) : 'core';
      const breaking = body.includes('BREAKING CHANGE') || subject.includes('!');
      
      return { 
        type: type as ChangelogEntry['type'], 
        scope, 
        message: message.trim(), 
        pr, 
        author,
        breaking 
      };
    })
    .filter(Boolean) as ChangelogEntry[];
}

function formatChangelog(entries: ChangelogEntry[], version: string): string {
  const grouped = entries.reduce((acc, entry) => {
    const key = entry.breaking ? 'break' : entry.type;
    if (!acc[key]) acc[key] = [];
    acc[key].push(entry);
    return acc;
  }, {} as Record<string, ChangelogEntry[]>);

  let md = `# 🎉 MonkeyCode ${version} Release Notes\n\n`;
  md += `> Released on ${new Date().toLocaleDateString('zh-CN')}\n\n`;
  
  const sectionOrder = ['break', 'feat', 'fix', 'perf', 'refactor', 'docs', 'chore'];
  const sectionTitles: Record<string, string> = {
    break: '💥 Breaking Changes',
    feat: '✨ New Features',
    fix: '🐛 Bug Fixes',
    perf: '⚡ Performance Improvements',
    refactor: '♻️ Refactoring',
    docs: '📝 Documentation',
    chore: '🔧 Maintenance',
  };

  for (const section of sectionOrder) {
    const items = grouped[section];
    if (!items || items.length === 0) continue;

    md += `## ${sectionTitles[section]}\n\n`;
    for (const item of items) {
      const icon = item.breaking ? '⚠️ ' : '';
      md += `- ${icon}**[${item.scope}]** ${item.message} ([#${item.pr}](https://github.com/monkeyCode/pull/${item.pr})) by @${item.author}\n`;
    }
    md += '\n';
  }

  // 贡献者列表
  const contributors = [...new Set(entries.map(e => e.author))];
  md += `## ❤️ Contributors\n\n`;
  md += `Thanks to all ${contributors.length} contributors!\n`;
  for (const c of contributors) {
    md += `- @${c}\n`;
  }

  return md;
}

// 主函数
const version = process.argv[2] || '0.0.0';
const lastTag = execSync('git describe --tags --abbrev=0', { encoding: 'utf-8' }).trim();
const entries = getCommitsSinceTag(lastTag);
const changelog = formatChangelog(entries, version);

fs.writeFileSync('CHANGELOG.md', changelog + '\n' + (fs.existsSync('CHANGELOG.md') ? fs.readFileSync('CHANGELOG.md', 'utf-8') : ''));
console.log(`✅ CHANGELOG.md updated with ${entries.length} entries`);

五、代码注释自动转文档

5.1 JSDoc/TSDoc 规范与自动提取

/**
 * 📝 MonkeyCode AI 服务 — 代码分析接口
 * 
 * 此模块提供代码分析的核心能力,包括:
 * - 语法分析和 AST 构建
 * - 复杂度计算
 * - 代码质量评分
 * - 安全漏洞检测
 * 
 * @module CodeAnalyzer
 * @example
 * ```ts
 * import { analyzeCode } from '@/services/analyzer';
 * 
 * const result = await analyzeCode({
 *   language: 'typescript',
 *   code: 'function hello() {}',
 *   options: { complexity: true }
 * });
 * console.log(result.complexity); // 1
 * ```
 * 
 * @see {@link https://docs.monkeyCode.dev/api/analyzer} API 文档
 * @since 2.0.0
 */

/**
 * 分析代码并返回结构化结果
 * 
 * 支持多种编程语言的静态分析,返回包括复杂度、
 * 安全问题、代码风格建议等在内的完整分析报告。
 * 
 * @param params - 分析参数
 * @param params.language - 目标编程语言
 * @param params.code - 待分析的源代码
 * @param params.options - 分析选项配置
 * @param params.options.complexity - 是否计算圈复杂度(默认 true)
 * @param params.options.security - 是否进行安全扫描(默认 true)
 * @param params.options.suggestions - 是否生成改进建议(默认 true)
 * @returns 分析结果对象
 * @throws {@link UnsupportedLanguageError} 当语言不支持时抛出
 * @throws {@link AnalysisTimeoutError} 当分析超时时抛出
 * 
 * @example
 * // 基础用法
 * const result = await analyzeCode({
 *   language: 'javascript',
 *   code: 'const x = 1;',
 * });
 * 
 * @example
 * // 自定义选项
 * const result = await analyzeCode({
 *   language: 'python',
 *   code: 'def foo(): pass',
 *   options: { complexity: false, suggestions: true }
 * });
 * 
 * @public
 */
export async function analyzeCode(
  params: AnalyzeCodeParams
): Promise<AnalyzeCodeResult> {
  // ... implementation
}

5.2 TypeDoc 配置

// typedoc.config.js — MonkeyCode TypeDoc 配置
import { defineConfig } from 'typedoc';

export default defineConfig({
  entryPoints: ['./src/index.ts'],
  out: './docs/api/typedoc',
  
  // 基本设置
  name: 'MonkeyCode SDK API Reference',
  readme: './docs/api-sdk-intro.md',
  includeVersion: true,
  
  // 输出格式
  plugin: ['typedoc-plugin-markdown', 'typedoc-plugin-missing-exports'],
  
  // 分类策略
  categorizeByGroup: true,
  defaultCategory: 'Core',
  categoryOrder: [
    'Core',
    'AI Services',
    'Code Analysis',
    'Git Integration',
    'Utilities',
    'Types',
    '*',
  ],
  
  // 过滤规则
  excludePrivate: true,
  excludeProtected: false,
  excludeInternal: true,
  excludeExternals: true,
  
  // 主题定制
  theme: {
    customCss: './docs/assets/typedoc-custom.css',
  },
  
  // 导航设置
  navigation: {
    includeCategories: true,
    includeGroups: true,
    includeFolders: false,
  },
  
  // 搜索配置
  searchInComments: true,
});

六、文档质量保障

6.1 文档 lint 规则

# .markdownlint-cli2.yaml — MonkeyCode Markdown 文档规范
config:
  # 行长度限制(代码块除外)
  MD013:
    line_length: 120
    code_blocks: false
    tables: false
  
  # 标题层级:必须从 h1 开始且递增
  MD001: true
  MD003:
    style: atx
  
  # 链接规范
  MD034: false  # 允许裸 URL
  MD039: true   # 链接文本不能为空
  
  # 图片必须有 alt 文本
  MD037: true
  MD045: true   # 图片后必须有空行
  
  # 列表规范
  MD004:
    style: consistent
  MD030: false  # 列表序号后的空格(兼容中文)
  
  # 代码块必须指定语言
  MD046:
    allowed_languages:
      - typescript
      - javascript
      - python
      - go
      - rust
      - yaml
      - json
      - markdown
      - bash
      - sql
      - dockerfile
      - text
  
  # HTML 内容检查
  MD033:
    allowed_elements:
      - a
      - img
      - br
      - sup
      - sub
      - details
      - summary
      - kbd
  
  # 首行一致性
  MD041: false  # 不强制首行必须是 h1(VitePress 有自己的 frontmatter)
  
  # Emoji 使用
  MD055: false  # 允许使用 emoji(MonkeyCode 风格)
  
  # 中文文档特殊规则
  MD026: false  # 允许中文标点结尾
  MD032: false  # 列表缩进

6.2 文档链接有效性检查

# .github/workflows/docs-link-check.yml — MonkeyCode 文档链接检查
name: 🔗 Documentation Link Check

on:
  push:
    branches: [main]
    paths: ['docs/**/*.md']
  pull_request:
    paths: ['docs/**/*.md']

jobs:
  link-check:
    name: Check Links
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Link Checker
        uses: lycheeverse/lychee-action@v1
        with:
          args: |
            ./docs
            --exclude-mail
            --exclude "https://example.com"
            --exclude "localhost"
            --exclude "127.0.0.1"
            --max-retries 3
            --retry-wait-timeout 10000
            --timeout 30
            --verbose
            --no-progress
          fail: true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  dead-links:
    name: Dead Link Report
    runs-on: ubuntu-latest
    if: always()
    needs: link-check
    
    steps:
      - name: Upload report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: link-check-report
          path: lychee/out.md

七、多语言文档国际化

7.1 i18n 文档架构

docs/
├── .vitepress/
│   ├── config.ts           # VitePress 配置
│   ├── theme/              # 自定义主题
│   └── i18n/               # 国际化配置
│       ├── zh.json         # 中文翻译
│       └── en.json         # 英文翻译
├── zh/                     # 中文文档
│   ├── index.md            # 首页
│   ├── guide/
│   │   ├── getting-started.md
│   │   ├── ai-chat.md
│   │   └── code-analysis.md
│   ├── api/
│   │   └── reference.md
│   └── faq.md
├── en/                     # 英文文档
│   ├── index.md
│   ├── guide/
│   │   ├── getting-started.md
│   │   ├── ai-chat.md
│   │   └── code-analysis.md
│   ├── api/
│   │   └── reference.md
│   └── faq.md
└── shared/                 # 共享资源
    └── images/

7.2 自动翻译工作流

# scripts/i18n-sync.py — MonkeyCode 文档国际同步工具
"""
MonkeyCode 文档 i18n 同步工具:
1. 检测新增/修改的中文文档
2. 自动翻译为英文(AI 辅助)
3. 对比差异供人工审核
"""

import os
import re
from pathlib import Path
from datetime import datetime


def find_new_or_modified_zh_docs(zh_dir: str, en_dir: str) -> list[str]:
    """找出中文目录中新增或修改但英文未同步的文档"""
    zh_files = {}
    en_files = {}
    
    for f in Path(zh_dir).rglob("*.md"):
        mtime = os.stat(f).st_mtime
        zh_files[f.relative_to(zh_dir)] = mtime
    
    for f in Path(en_dir).rglob("*.md"):
        mtime = os.stat(f).st_mtime
        en_files[f.relative_to(en_dir)] = mtime
    
    # 找出需要翻译的文件
    need_translate = []
    for rel_path, zh_mtime in zh_files.items():
        en_mtime = en_files.get(rel_path, 0)
        if zh_mtime > en_mtime:
            need_translate.append(str(Path(zh_dir) / rel_path))
    
    return need_translate


def extract_translatable_content(md_text: str) -> dict:
    """从 Markdown 中提取可翻译的内容"""
    result = {
        "title": "",
        "sections": [],
        "code_blocks": [],  # 不翻译
    }
    
    lines = md_text.split('\n')
    current_section = None
    in_code_block = False
    
    for line in lines:
        # 代码块跳过
        if line.strip().startswith('```'):
            in_code_block = not in_code_block
            if in_code_block:
                current_code_lang = line.strip()[3:]
            continue
        
        if in_code_block:
            continue
        
        # 标题
        if line.startswith('#'):
            title_match = re.match(r'^#{1,6}\s+(.+)', line)
            if title_match:
                if current_section:
                    result["sections"].append(current_section)
                current_section = {"heading": title_match.group(1), "content": []}
        
        # 正文内容
        elif current_section and line.strip():
            current_section["content"].append(line)
    
    if current_section:
        result["sections"].append(current_section)
    
    # 提取第一个 h1 作为标题
    first_h1 = re.search(r'^#\s+(.+)$', md_text, re.MULTILINE)
    if first_h1:
        result["title"] = first_h1.group(1)
    
    return result


def generate_i18n_report(new_files: list[str], output_path: str):
    """生成 i18n 同步报告"""
    report = f"""# 📋 MonkeyCode i18n Sync Report

Generated: {datetime.now().isoformat()}

## Files Needing Translation ({len(new_files)} files)

"""
    for f in new_files:
        rel = Path(f).relative_to("docs/zh")
        report += f"- `{rel}`\n"
    
    report += """
## Next Steps

1. Review the files listed above
2. Run translation script: `python scripts/i18n-translate.py`
3. Review machine translations
4. Commit translated files to `docs/en/`
"""
    
    Path(output_path).write_text(report, encoding='utf-8')
    print(f"Report saved to {output_path}")


if __name__ == "__main__":
    new_docs = find_new_or_modified_zh_docs("docs/zh", "docs/en")
    print(f"Found {len(new_docs)} documents needing translation")
    
    for doc in new_docs:
        print(f"  - {doc}")
    
    if new_docs:
        generate_i18n_report(new_docs, "docs/i18n-report.md")

八、常见问题与最佳实践

FAQ

## ❓ 文档自动化常见问题

### Q1: 自动生成的文档质量不够怎么办?
**A**:
1. **模板优化**:精心设计 JSDoc/TSDoc 注释模板
2. **后处理脚本**:对生成结果进行二次加工
3. **人工审核关键页面**:核心文档仍需人工润色
4. **用户反馈闭环**:在每页添加"此页有帮助吗?"反馈按钮

### Q2: 如何平衡自动化和人工编写?
**A**:
- **全自动**:API 参考、Changelog、类型定义
- **半自动**:用户指南(框架自动+内容人工)、架构图(Mermaid 代码→图)
- **纯手工**:博客文章、教程视频脚本、社区故事

### Q3: 多语言文档如何保持同步?
**A**:
1. 以一种语言为 Source of Truth(MonkeyCode 用中文)
2. 变更检测脚本定期扫描
3. AI 辅助初翻 + 人工审核
4. 版本化管理,支持回滚对比

### Q4: 文档版本如何跟随代码版本?
**A**:
1. 文档站支持版本切换(如 docs.v1.monkeyCode.dev)
2. 每个 Release 自动归档对应版本的文档
3. 最新版文档始终指向 main 分支
4. 废弃 API 文档保留但标记 deprecated

九、总结与行动号召

9.1 核心要点回顾

╔═══════════════════════════════════════════════════════════╗
║                                                           ║
║  📚 MonkeyCode 文档自动化六大原则                          ║
║                                                           ║
║  1️⃣ 单一来源 — 代码是文档的唯一真相来源                     ║
║  2️⃣ 自动生成 — 能自动化的绝不手动编写                       ║
║  3️⃣ CI 驱动 — 文档更新随代码提交自动触发                    ║
║  4️⃣ 质量门禁 — 链接有效性和格式规范自动检查                  ║
║  5️⃣ 多语言优先 — 国际化从第一天就纳入规划                    ║
║  6️⃣ 用户视角 — 始终以用户体验为中心组织内容                   ║
║                                                           ║
╚═══════════════════════════════════════════════════════════╝

9.2 如何参与?

  • ✍️ 贡献文档:帮我们完善各语言的文档翻译
  • 🐛 报告文档问题:在 GitHub Issue 中标注 [docs] 前缀
  • 💡 提出改进建议:关于文档结构和内容的想法
  • 🔧 贡献工具链:帮我们完善文档自动化脚本

现在就访问 MonkeyCode GitHub,查看我们的文档站,提出你的改进建议吧!


本文最后更新于 2026 年 7 月 1 日。好的文档是最好的开发者体验。

相关文章推荐:


© 2026 MonkeyCode Open Source Project. Licensed under Apache License 2.0.
文档站点: https://docs.monkeyCode.dev | API 文档: https://api.monkeyCode.dev/docs

posted on 2026-07-01 13:02  MonkeyCode  阅读(50)  评论(0)    收藏  举报