docs-as-code
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDocs-as-Code Skill
Docs-as-Code Skill
When to Use This Skill
何时使用该Skill
Use this skill when:
- Docs As Code tasks - Working on documentation pipeline automation and docs-as-code workflows
- Planning or design - Need guidance on Docs As Code approaches
- Best practices - Want to follow established patterns and standards
在以下场景使用该Skill:
- Docs As Code 任务 - 处理文档流水线自动化与 Docs-as-Code 工作流相关工作
- 规划或设计阶段 - 需要 Docs As Code 方法的指导
- 最佳实践参考 - 希望遵循已确立的模式和标准
Overview
概述
Implement documentation-as-code workflows with automated pipelines, version control, and CI/CD integration.
通过自动化流水线、版本控制和CI/CD集成,实现文档即代码工作流。
MANDATORY: Documentation-First Approach
强制要求:文档优先方法
Before implementing docs-as-code:
- Invoke skill for documentation patterns
docs-management - Verify tooling versions via MCP servers (context7 for docusaurus/mkdocs)
- Base guidance on current best practices
在实施Docs-as-Code之前:
- 调用skill 获取文档模式指导
docs-management - 通过MCP服务器验证工具版本(context7用于docusaurus/mkdocs)
- 基于当前最佳实践制定指导方案
Docs-as-Code Philosophy
Docs-as-Code 理念
text
Docs-as-Code Principles:
┌─────────────────────────────────────────────────────────────────────────────┐
│ 1. Version Control │
│ - Docs live alongside code in the same repository │
│ - Changes tracked with meaningful commit messages │
│ - Branch-based workflow for documentation updates │
├─────────────────────────────────────────────────────────────────────────────┤
│ 2. Review Process │
│ - Pull requests for documentation changes │
│ - Technical review by subject matter experts │
│ - Style review by technical writers │
├─────────────────────────────────────────────────────────────────────────────┤
│ 3. Automated Testing │
│ - Linting for style and grammar │
│ - Link validation │
│ - Build verification │
├─────────────────────────────────────────────────────────────────────────────┤
│ 4. Continuous Deployment │
│ - Automatic publishing on merge │
│ - Preview deployments for PRs │
│ - Versioned documentation releases │
└─────────────────────────────────────────────────────────────────────────────┘text
Docs-as-Code Principles:
┌─────────────────────────────────────────────────────────────────────────────┐
│ 1. Version Control │
│ - Docs live alongside code in the same repository │
│ - Changes tracked with meaningful commit messages │
│ - Branch-based workflow for documentation updates │
├─────────────────────────────────────────────────────────────────────────────┤
│ 2. Review Process │
│ - Pull requests for documentation changes │
│ - Technical review by subject matter experts │
│ - Style review by technical writers │
├─────────────────────────────────────────────────────────────────────────────┤
│ 3. Automated Testing │
│ - Linting for style and grammar │
│ - Link validation │
│ - Build verification │
├─────────────────────────────────────────────────────────────────────────────┤
│ 4. Continuous Deployment │
│ - Automatic publishing on merge │
│ - Preview deployments for PRs │
│ - Versioned documentation releases │
└─────────────────────────────────────────────────────────────────────────────┘Documentation Tooling Comparison
文档工具对比
| Tool | Language | Best For | Build Speed |
|---|---|---|---|
| Docusaurus | JS/React | Product docs, versioning | Fast |
| MkDocs | Python | Technical docs, Material theme | Fast |
| Sphinx | Python | API docs, reStructuredText | Medium |
| Hugo | Go | Large sites, speed | Very Fast |
| Astro | JS | Modern sites, MDX | Fast |
| VitePress | JS/Vue | Vue ecosystem | Very Fast |
| Jekyll | Ruby | GitHub Pages native | Medium |
| 工具 | 语言 | 适用场景 | 构建速度 |
|---|---|---|---|
| Docusaurus | JS/React | 产品文档、版本管理 | 快速 |
| MkDocs | Python | 技术文档、Material主题 | 快速 |
| Sphinx | Python | API文档、reStructuredText | 中等 |
| Hugo | Go | 大型站点、追求速度 | 极快 |
| Astro | JS | 现代站点、MDX | 快速 |
| VitePress | JS/Vue | Vue生态 | 极快 |
| Jekyll | Ruby | GitHub Pages原生支持 | 中等 |
Project Structure
项目结构
Docusaurus Structure
Docusaurus 结构
text
docs/
├── docusaurus.config.js # Main configuration
├── sidebars.js # Navigation structure
├── package.json # Dependencies
├── docs/ # Documentation content
│ ├── intro.md
│ ├── getting-started/
│ │ ├── installation.md
│ │ └── configuration.md
│ ├── guides/
│ │ ├── quick-start.md
│ │ └── advanced.md
│ └── api/
│ └── reference.md
├── blog/ # Blog posts (optional)
├── src/
│ ├── components/ # React components
│ ├── css/ # Custom styles
│ └── pages/ # Custom pages
├── static/ # Static assets
│ └── img/
└── versioned_docs/ # Version snapshots
├── version-1.0/
└── version-2.0/text
docs/
├── docusaurus.config.js # Main configuration
├── sidebars.js # Navigation structure
├── package.json # Dependencies
├── docs/ # Documentation content
│ ├── intro.md
│ ├── getting-started/
│ │ ├── installation.md
│ │ └── configuration.md
│ ├── guides/
│ │ ├── quick-start.md
│ │ └── advanced.md
│ └── api/
│ └── reference.md
├── blog/ # Blog posts (optional)
├── src/
│ ├── components/ # React components
│ ├── css/ # Custom styles
│ └── pages/ # Custom pages
├── static/ # Static assets
│ └── img/
└── versioned_docs/ # Version snapshots
├── version-1.0/
└── version-2.0/MkDocs Structure
MkDocs 结构
text
docs/
├── mkdocs.yml # Configuration
├── docs/
│ ├── index.md
│ ├── getting-started/
│ │ ├── installation.md
│ │ └── configuration.md
│ ├── user-guide/
│ │ └── features.md
│ ├── reference/
│ │ └── api.md
│ └── about/
│ └── changelog.md
├── overrides/ # Theme customization
│ ├── main.html
│ └── partials/
└── requirements.txt # Python dependenciestext
docs/
├── mkdocs.yml # Configuration
├── docs/
│ ├── index.md
│ ├── getting-started/
│ │ ├── installation.md
│ │ └── configuration.md
│ ├── user-guide/
│ │ └── features.md
│ ├── reference/
│ │ └── api.md
│ └── about/
│ └── changelog.md
├── overrides/ # Theme customization
│ ├── main.html
│ └── partials/
└── requirements.txt # Python dependenciesConfiguration Templates
配置模板
Docusaurus Configuration
Docusaurus 配置
javascript
// docusaurus.config.js
const config = {
title: 'Project Name',
tagline: 'Project tagline',
url: 'https://docs.example.com',
baseUrl: '/',
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
favicon: 'img/favicon.ico',
organizationName: 'organization',
projectName: 'project',
i18n: {
defaultLocale: 'en',
locales: ['en'],
},
presets: [
[
'classic',
{
docs: {
sidebarPath: require.resolve('./sidebars.js'),
editUrl: 'https://github.com/org/project/edit/main/docs/',
showLastUpdateAuthor: true,
showLastUpdateTime: true,
versions: {
current: {
label: 'Next',
path: 'next',
},
},
},
blog: {
showReadingTime: true,
editUrl: 'https://github.com/org/project/edit/main/docs/',
},
theme: {
customCss: require.resolve('./src/css/custom.css'),
},
},
],
],
themeConfig: {
navbar: {
title: 'Project',
logo: {
alt: 'Project Logo',
src: 'img/logo.svg',
},
items: [
{ type: 'doc', docId: 'intro', position: 'left', label: 'Docs' },
{ to: '/blog', label: 'Blog', position: 'left' },
{ type: 'docsVersionDropdown', position: 'right' },
{ href: 'https://github.com/org/project', label: 'GitHub', position: 'right' },
],
},
footer: {
style: 'dark',
links: [
{
title: 'Docs',
items: [{ label: 'Getting Started', to: '/docs/intro' }],
},
{
title: 'Community',
items: [{ label: 'Discord', href: 'https://discord.gg/xxx' }],
},
],
copyright: `Copyright © ${new Date().getFullYear()} Organization.`,
},
prism: {
theme: require('prism-react-renderer/themes/github'),
darkTheme: require('prism-react-renderer/themes/dracula'),
additionalLanguages: ['csharp', 'powershell', 'bash'],
},
algolia: {
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_SEARCH_API_KEY',
indexName: 'project',
},
},
};
module.exports = config;javascript
// docusaurus.config.js
const config = {
title: 'Project Name',
tagline: 'Project tagline',
url: 'https://docs.example.com',
baseUrl: '/',
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
favicon: 'img/favicon.ico',
organizationName: 'organization',
projectName: 'project',
i18n: {
defaultLocale: 'en',
locales: ['en'],
},
presets: [
[
'classic',
{
docs: {
sidebarPath: require.resolve('./sidebars.js'),
editUrl: 'https://github.com/org/project/edit/main/docs/',
showLastUpdateAuthor: true,
showLastUpdateTime: true,
versions: {
current: {
label: 'Next',
path: 'next',
},
},
},
blog: {
showReadingTime: true,
editUrl: 'https://github.com/org/project/edit/main/docs/',
},
theme: {
customCss: require.resolve('./src/css/custom.css'),
},
},
],
],
themeConfig: {
navbar: {
title: 'Project',
logo: {
alt: 'Project Logo',
src: 'img/logo.svg',
},
items: [
{ type: 'doc', docId: 'intro', position: 'left', label: 'Docs' },
{ to: '/blog', label: 'Blog', position: 'left' },
{ type: 'docsVersionDropdown', position: 'right' },
{ href: 'https://github.com/org/project', label: 'GitHub', position: 'right' },
],
},
footer: {
style: 'dark',
links: [
{
title: 'Docs',
items: [{ label: 'Getting Started', to: '/docs/intro' }],
},
{
title: 'Community',
items: [{ label: 'Discord', href: 'https://discord.gg/xxx' }],
},
],
copyright: `Copyright © ${new Date().getFullYear()} Organization.`,
},
prism: {
theme: require('prism-react-renderer/themes/github'),
darkTheme: require('prism-react-renderer/themes/dracula'),
additionalLanguages: ['csharp', 'powershell', 'bash'],
},
algolia: {
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_SEARCH_API_KEY',
indexName: 'project',
},
},
};
module.exports = config;MkDocs Configuration
MkDocs 配置
yaml
undefinedyaml
undefinedmkdocs.yml
mkdocs.yml
site_name: Project Documentation
site_url: https://docs.example.com
repo_url: https://github.com/org/project
repo_name: org/project
edit_uri: edit/main/docs/
theme:
name: material
palette:
- scheme: default
primary: indigo
accent: indigo
toggle:
icon: material/brightness-7
name: Switch to dark mode
- scheme: slate
primary: indigo
accent: indigo
toggle:
icon: material/brightness-4
name: Switch to light mode
features:
- navigation.instant
- navigation.tracking
- navigation.tabs
- navigation.sections
- navigation.expand
- navigation.indexes
- toc.follow
- content.code.copy
- content.code.annotate
- search.suggest
- search.highlight
plugins:
- search
- git-revision-date-localized: enable_creation_date: true
- minify: minify_html: true
- mike: version_selector: true css_dir: css javascript_dir: js
markdown_extensions:
- pymdownx.highlight: anchor_linenums: true
- pymdownx.superfences: custom_fences: - name: mermaid class: mermaid format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.tabbed: alternate_style: true
- admonition
- pymdownx.details
- attr_list
- md_in_html
- toc: permalink: true
nav:
- Home: index.md
- Getting Started:
- Installation: getting-started/installation.md
- Configuration: getting-started/configuration.md
- User Guide:
- Features: user-guide/features.md
- Reference:
- API: reference/api.md
- About:
- Changelog: about/changelog.md
extra:
version:
provider: mike
social:
- icon: fontawesome/brands/github
link: https://github.com/org/project
undefinedsite_name: Project Documentation
site_url: https://docs.example.com
repo_url: https://github.com/org/project
repo_name: org/project
edit_uri: edit/main/docs/
theme:
name: material
palette:
- scheme: default
primary: indigo
accent: indigo
toggle:
icon: material/brightness-7
name: Switch to dark mode
- scheme: slate
primary: indigo
accent: indigo
toggle:
icon: material/brightness-4
name: Switch to light mode
features:
- navigation.instant
- navigation.tracking
- navigation.tabs
- navigation.sections
- navigation.expand
- navigation.indexes
- toc.follow
- content.code.copy
- content.code.annotate
- search.suggest
- search.highlight
plugins:
- search
- git-revision-date-localized: enable_creation_date: true
- minify: minify_html: true
- mike: version_selector: true css_dir: css javascript_dir: js
markdown_extensions:
- pymdownx.highlight: anchor_linenums: true
- pymdownx.superfences: custom_fences: - name: mermaid class: mermaid format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.tabbed: alternate_style: true
- admonition
- pymdownx.details
- attr_list
- md_in_html
- toc: permalink: true
nav:
- Home: index.md
- Getting Started:
- Installation: getting-started/installation.md
- Configuration: getting-started/configuration.md
- User Guide:
- Features: user-guide/features.md
- Reference:
- API: reference/api.md
- About:
- Changelog: about/changelog.md
extra:
version:
provider: mike
social:
- icon: fontawesome/brands/github
link: https://github.com/org/project
undefinedCI/CD Pipeline Templates
CI/CD 流水线模板
GitHub Actions for Docusaurus
GitHub Actions 用于 Docusaurus
yaml
undefinedyaml
undefined.github/workflows/docs.yml
.github/workflows/docs.yml
name: Documentation
on:
push:
branches: [main]
paths:
- 'docs/'
- '.github/workflows/docs.yml'
pull_request:
branches: [main]
paths:
- 'docs/'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: docs/package-lock.json
- name: Install dependencies
working-directory: docs
run: npm ci
- name: Lint Markdown
run: npx markdownlint-cli2 "docs/**/*.md"
- name: Check links
working-directory: docs
run: npm run check-linksbuild:
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v5
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: docs/package-lock.json
- name: Install dependencies
working-directory: docs
run: npm ci
- name: Build
working-directory: docs
run: npm run build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/builddeploy:
if: github.ref == 'refs/heads/main'
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
preview:
if: github.event_name == 'pull_request'
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy preview
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/build
destination_dir: pr-preview/${{ github.event.number }}
- name: Comment preview URL
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '📚 Documentation preview: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr-preview/${{ github.event.number }}/'
})undefinedname: Documentation
on:
push:
branches: [main]
paths:
- 'docs/'
- '.github/workflows/docs.yml'
pull_request:
branches: [main]
paths:
- 'docs/'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: docs/package-lock.json
- name: Install dependencies
working-directory: docs
run: npm ci
- name: Lint Markdown
run: npx markdownlint-cli2 "docs/**/*.md"
- name: Check links
working-directory: docs
run: npm run check-linksbuild:
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v5
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: docs/package-lock.json
- name: Install dependencies
working-directory: docs
run: npm ci
- name: Build
working-directory: docs
run: npm run build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/builddeploy:
if: github.ref == 'refs/heads/main'
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
preview:
if: github.event_name == 'pull_request'
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy preview
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/build
destination_dir: pr-preview/${{ github.event.number }}
- name: Comment preview URL
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '📚 Documentation preview: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr-preview/${{ github.event.number }}/'
})undefinedAzure DevOps for MkDocs
Azure DevOps 用于 MkDocs
yaml
undefinedyaml
undefinedazure-pipelines.yml
azure-pipelines.yml
trigger:
branches:
include:
- main
paths:
include:
- docs/**
pool:
vmImage: 'ubuntu-latest'
variables:
pythonVersion: '3.11'
stages:
-
stage: Validate jobs:
- job: Lint
steps:
-
task: UsePythonVersion@0 inputs: versionSpec: '$(pythonVersion)'
-
script: | pip install -r docs/requirements.txt pip install markdownlint-cli2 displayName: 'Install dependencies'
-
script: markdownlint-cli2 "docs/**/*.md" displayName: 'Lint Markdown'
-
- job: Lint
steps:
-
stage: Build dependsOn: Validate jobs:
- job: Build
steps:
-
task: UsePythonVersion@0 inputs: versionSpec: '$(pythonVersion)'
-
script: pip install -r docs/requirements.txt displayName: 'Install dependencies'
-
script: mkdocs build --strict displayName: 'Build documentation'
-
publish: site artifact: documentation
-
- job: Build
steps:
-
stage: Deploy dependsOn: Build condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) jobs:
-
deployment: Deploy environment: production strategy: runOnce: deploy: steps: - download: current artifact: documentation
- task: AzureStaticWebApp@0 inputs: app_location: '$(Pipeline.Workspace)/documentation' azure_static_web_apps_api_token: $(AZURE_STATIC_WEB_APPS_TOKEN)
-
undefinedtrigger:
branches:
include:
- main
paths:
include:
- docs/**
pool:
vmImage: 'ubuntu-latest'
variables:
pythonVersion: '3.11'
stages:
-
stage: Validate jobs:
- job: Lint
steps:
-
task: UsePythonVersion@0 inputs: versionSpec: '$(pythonVersion)'
-
script: | pip install -r docs/requirements.txt pip install markdownlint-cli2 displayName: 'Install dependencies'
-
script: markdownlint-cli2 "docs/**/*.md" displayName: 'Lint Markdown'
-
- job: Lint
steps:
-
stage: Build dependsOn: Validate jobs:
- job: Build
steps:
-
task: UsePythonVersion@0 inputs: versionSpec: '$(pythonVersion)'
-
script: pip install -r docs/requirements.txt displayName: 'Install dependencies'
-
script: mkdocs build --strict displayName: 'Build documentation'
-
publish: site artifact: documentation
-
- job: Build
steps:
-
stage: Deploy dependsOn: Build condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) jobs:
-
deployment: Deploy environment: production strategy: runOnce: deploy: steps: - download: current artifact: documentation
- task: AzureStaticWebApp@0 inputs: app_location: '$(Pipeline.Workspace)/documentation' azure_static_web_apps_api_token: $(AZURE_STATIC_WEB_APPS_TOKEN)
-
undefinedDocumentation Linting
文档检查
Markdownlint Configuration
Markdownlint 配置
json
// .markdownlint.json
{
"default": true,
"MD001": true,
"MD003": { "style": "atx" },
"MD004": { "style": "dash" },
"MD007": { "indent": 2 },
"MD009": true,
"MD010": true,
"MD012": true,
"MD013": { "line_length": 120, "code_blocks": false, "tables": false },
"MD022": { "lines_above": 1, "lines_below": 1 },
"MD024": { "siblings_only": true },
"MD025": { "front_matter_title": "" },
"MD026": { "punctuation": ".,;:!" },
"MD029": { "style": "ordered" },
"MD030": { "ul_single": 1, "ol_single": 1, "ul_multi": 1, "ol_multi": 1 },
"MD033": { "allowed_elements": ["details", "summary", "kbd", "br"] },
"MD035": { "style": "---" },
"MD036": false,
"MD040": true,
"MD041": true,
"MD046": { "style": "fenced" },
"MD048": { "style": "backtick" }
}json
// .markdownlint.json
{
"default": true,
"MD001": true,
"MD003": { "style": "atx" },
"MD004": { "style": "dash" },
"MD007": { "indent": 2 },
"MD009": true,
"MD010": true,
"MD012": true,
"MD013": { "line_length": 120, "code_blocks": false, "tables": false },
"MD022": { "lines_above": 1, "lines_below": 1 },
"MD024": { "siblings_only": true },
"MD025": { "front_matter_title": "" },
"MD026": { "punctuation": ".,;:!" },
"MD029": { "style": "ordered" },
"MD030": { "ul_single": 1, "ol_single": 1, "ul_multi": 1, "ol_multi": 1 },
"MD033": { "allowed_elements": ["details", "summary", "kbd", "br"] },
"MD035": { "style": "---" },
"MD036": false,
"MD040": true,
"MD041": true,
"MD046": { "style": "fenced" },
"MD048": { "style": "backtick" }
}Vale Configuration
Vale 配置
yaml
undefinedyaml
undefined.vale.ini
.vale.ini
StylesPath = styles
MinAlertLevel = suggestion
Packages = Microsoft, write-good, proselint
[*.md]
BasedOnStyles = Vale, Microsoft, write-good
StylesPath = styles
MinAlertLevel = suggestion
Packages = Microsoft, write-good, proselint
[*.md]
BasedOnStyles = Vale, Microsoft, write-good
Ignore code blocks
Ignore code blocks
BlockIgnores = (?s) *({3})
{3}.*?BlockIgnores = (?s) *({3})
{3}.*?Custom rules
Custom rules
Microsoft.Contractions = NO
Microsoft.HeadingPunctuation = YES
write-good.Passive = YES
write-good.Weasel = YES
write-good.TooWordy = YES
undefinedMicrosoft.Contractions = NO
Microsoft.HeadingPunctuation = YES
write-good.Passive = YES
write-good.Weasel = YES
write-good.TooWordy = YES
undefinedLiving Documentation
活文档
Generating API Docs from Code
从代码生成API文档
csharp
// API Documentation Generation with XML Comments
/// <summary>
/// Manages user authentication and authorization.
/// </summary>
/// <remarks>
/// <para>
/// This service handles all authentication flows including:
/// <list type="bullet">
/// <item>Password-based authentication</item>
/// <item>OAuth 2.0 / OpenID Connect</item>
/// <item>API key authentication</item>
/// </list>
/// </para>
/// </remarks>
/// <example>
/// <code>
/// var result = await authService.AuthenticateAsync(credentials);
/// if (result.IsSuccess)
/// {
/// var token = result.Value.AccessToken;
/// }
/// </code>
/// </example>
public interface IAuthenticationService
{
/// <summary>
/// Authenticates a user with the provided credentials.
/// </summary>
/// <param name="credentials">The authentication credentials.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>
/// A result containing the authentication response on success,
/// or an error on failure.
/// </returns>
/// <exception cref="AuthenticationException">
/// Thrown when authentication fails due to invalid credentials.
/// </exception>
Task<Result<AuthenticationResponse>> AuthenticateAsync(
AuthenticationCredentials credentials,
CancellationToken cancellationToken = default);
}csharp
// API Documentation Generation with XML Comments
/// <summary>
/// Manages user authentication and authorization.
/// </summary>
/// <remarks>
/// <para>
/// This service handles all authentication flows including:
/// <list type="bullet">
/// <item>Password-based authentication</item>
/// <item>OAuth 2.0 / OpenID Connect</item>
/// <item>API key authentication</item>
/// </list>
/// </para>
/// </remarks>
/// <example>
/// <code>
/// var result = await authService.AuthenticateAsync(credentials);
/// if (result.IsSuccess)
/// {
/// var token = result.Value.AccessToken;
/// }
/// </code>
/// </example>
public interface IAuthenticationService
{
/// <summary>
/// Authenticates a user with the provided credentials.
/// </summary>
/// <param name="credentials">The authentication credentials.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>
/// A result containing the authentication response on success,
/// or an error on failure.
/// </returns>
/// <exception cref="AuthenticationException">
/// Thrown when authentication fails due to invalid credentials.
/// </exception>
Task<Result<AuthenticationResponse>> AuthenticateAsync(
AuthenticationCredentials credentials,
CancellationToken cancellationToken = default);
}OpenAPI Documentation Generation
OpenAPI 文档生成
csharp
// Program.cs - Swagger/OpenAPI configuration
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "Project API",
Version = "v1",
Description = "API documentation for the Project",
Contact = new OpenApiContact
{
Name = "API Support",
Email = "api@example.com",
Url = new Uri("https://docs.example.com")
},
License = new OpenApiLicense
{
Name = "MIT",
Url = new Uri("https://opensource.org/licenses/MIT")
}
});
// Include XML comments
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
options.IncludeXmlComments(xmlPath);
// Security definitions
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme.",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = "bearer"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
Array.Empty<string>()
}
});
});csharp
// Program.cs - Swagger/OpenAPI configuration
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "Project API",
Version = "v1",
Description = "API documentation for the Project",
Contact = new OpenApiContact
{
Name = "API Support",
Email = "api@example.com",
Url = new Uri("https://docs.example.com")
},
License = new OpenApiLicense
{
Name = "MIT",
Url = new Uri("https://opensource.org/licenses/MIT")
}
});
// Include XML comments
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
options.IncludeXmlComments(xmlPath);
// Security definitions
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme.",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = "bearer"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
Array.Empty<string>()
}
});
});Documentation Testing
文档测试
Link Checking
链接检查
javascript
// check-links.mjs
import { remark } from 'remark';
import remarkLintNoDeadUrls from 'remark-lint-no-dead-urls';
import { read } from 'to-vfile';
import { glob } from 'glob';
import { reporter } from 'vfile-reporter';
const files = await glob('docs/**/*.md');
for (const file of files) {
const result = await remark()
.use(remarkLintNoDeadUrls, {
skipLocalhost: true,
skipOffline: true,
})
.process(await read(file));
console.error(reporter(result));
}javascript
// check-links.mjs
import { remark } from 'remark';
import remarkLintNoDeadUrls from 'remark-lint-no-dead-urls';
import { read } from 'to-vfile';
import { glob } from 'glob';
import { reporter } from 'vfile-reporter';
const files = await glob('docs/**/*.md');
for (const file of files) {
const result = await remark()
.use(remarkLintNoDeadUrls, {
skipLocalhost: true,
skipOffline: true,
})
.process(await read(file));
console.error(reporter(result));
}Screenshot Testing
截图测试
typescript
// docs.spec.ts - Playwright screenshot tests
import { test, expect } from '@playwright/test';
test.describe('Documentation Screenshots', () => {
test('homepage renders correctly', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot('homepage.png');
});
test('API reference page', async ({ page }) => {
await page.goto('/docs/api/reference');
await expect(page.locator('.api-content')).toBeVisible();
await expect(page).toHaveScreenshot('api-reference.png');
});
test('dark mode toggle', async ({ page }) => {
await page.goto('/');
await page.click('[data-theme-toggle]');
await expect(page).toHaveScreenshot('homepage-dark.png');
});
});typescript
// docs.spec.ts - Playwright screenshot tests
import { test, expect } from '@playwright/test';
test.describe('Documentation Screenshots', () => {
test('homepage renders correctly', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot('homepage.png');
});
test('API reference page', async ({ page }) => {
await page.goto('/docs/api/reference');
await expect(page.locator('.api-content')).toBeVisible();
await expect(page).toHaveScreenshot('api-reference.png');
});
test('dark mode toggle', async ({ page }) => {
await page.goto('/');
await page.click('[data-theme-toggle]');
await expect(page).toHaveScreenshot('homepage-dark.png');
});
});Best Practices
最佳实践
Content Organization
内容组织
| Practice | Description |
|---|---|
| Single Source of Truth | Each concept documented in one place |
| Progressive Disclosure | Start simple, link to details |
| Consistent Structure | Same sections across similar pages |
| Clear Navigation | Logical hierarchy, breadcrumbs |
| Search Optimization | Good headings, keywords, descriptions |
| 实践 | 说明 |
|---|---|
| 单一事实来源 | 每个概念仅在一处文档中说明 |
| 渐进式披露 | 从简单内容开始,链接到详细说明 |
| 一致的结构 | 相似页面使用相同的章节结构 |
| 清晰的导航 | 逻辑化层级结构,面包屑导航 |
| 搜索优化 | 合理的标题、关键词和描述 |
Writing Guidelines
写作指南
- Use active voice: "Configure the setting" not "The setting should be configured"
- Be concise: Remove unnecessary words
- Use examples: Show, don't just tell
- Maintain consistency: Same terms throughout
- Update regularly: Documentation rots quickly
- 使用主动语态:比如用"配置该设置"而非"该设置应被配置"
- 保持简洁:删除不必要的词汇
- 使用示例:演示而非仅描述
- 保持一致性:全程使用相同术语
- 定期更新:文档会快速过时
Versioning Strategy
版本控制策略
text
Documentation Versioning:
Option 1: Version Folders (Docusaurus/MkDocs mike)
├── docs/
│ ├── version-1.0/
│ ├── version-2.0/
│ └── current/
Option 2: Branch-based
├── main (current)
├── v1.x
└── v2.x
Option 3: Git Tags
├── v1.0.0
├── v2.0.0
└── latest
Recommendation: Use tool-native versioning (Docusaurus versioned_docs, mike for MkDocs)text
Documentation Versioning:
Option 1: Version Folders (Docusaurus/MkDocs mike)
├── docs/
│ ├── version-1.0/
│ ├── version-2.0/
│ └── current/
Option 2: Branch-based
├── main (current)
├── v1.x
└── v2.x
Option 3: Git Tags
├── v1.0.0
├── v2.0.0
└── latest
Recommendation: Use tool-native versioning (Docusaurus versioned_docs, mike for MkDocs)Workflow
工作流
When implementing docs-as-code:
- Choose Tooling: Select SSG based on team skills and requirements
- Set Up Structure: Create organized folder hierarchy
- Configure CI/CD: Automated builds, previews, deployments
- Add Linting: Markdown linting, link checking, spell check
- Enable Reviews: PR-based workflow with tech writer review
- Deploy Versioning: Set up version management strategy
- Monitor Analytics: Track usage, search queries, gaps
实施Docs-as-Code时的步骤:
- 选择工具:根据团队技能和需求选择静态站点生成器
- 设置结构:创建有序的文件夹层级
- 配置CI/CD:自动化构建、预览和部署
- 添加检查:Markdown检查、链接验证、拼写检查
- 启用审核:基于PR的工作流,包含技术作者审核
- 部署版本控制:设置版本管理策略
- 监控分析:跟踪使用情况、搜索查询和内容缺口
References
参考资料
For detailed guidance:
Last Updated: 2025-12-26
如需详细指导:
最后更新: 2025-12-26