Skip to main content

使用DocFx生成Java项目文档网站

· 6 min read
Ferdinand Su

DocFx是一个非常好用的文档生成软件,其优势在于配置简便,能够方便地生成API文档+人工文章文档有机结合的静态文档网站,而不需要过多的工作。

然而,DocFx的自动API文档生成目前仅官方支持.NET项目,而Java项目的默认Javadoc只包括API文档,缺乏人工文档辅助而过于拉跨。笔者问了Bing,发现Java平台下确实没有特别好用的文档生成工具,因此最后还是决定使用DocFx加上一个非官方插件docascode/docfx-doclet(Archived)的Fork: googleapis/java-docfx-doclet,用于构造HIT-ReFreSH/JMobileSuit的文档网站。这玩意坑还是很多的,笔者进行了许多小修小补。

下载Release

原仓库的Release实际上几乎完全不能用,请下载googleapis/java-docfx-doclet的Release,笔者使用了1.9.0版本,尽管代码里的最新版是1.12.0,但是实际上并不能用,master上的代码无法通过单元测试。

如果出现了什么意外,原Release下载不了,可以去JMobileSuit/docs/lib下看看。

利用maven-javadoc.plugin调用该doclet插件生成API文档

今天累了,避坑过程就不写了,直接上POM:

POM.xml
...
<build>
...
<pluginManagement>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<encoding>UTF-8</encoding>
<charset>UTF-8</charset>
<docencoding>UTF-8</docencoding>
<locale>en_US</locale>
<docletPath>${project.basedir}/docs/lib/docfx-doclet-1.9.0-jar-with-dependencies.jar(改成你自己的路径,注意前面的${project.basedir}不能省略)
</docletPath>
<doclet>com.microsoft.doclet.DocFxDoclet</doclet>
<useStandardDocletOptions>false</useStandardDocletOptions>
<additionalOptions>
-outputpath ${project.basedir}/docs/api(可以改成你自己的位置) -projectname (随便娶一个就好)
</additionalOptions>
<outputDirectory>docs/api</outputDirectory>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
...
...

利用脚本清洗自动生成的API Doc目录

自动生成的api/doc.yml有一些问题:

  1. 无效折叠:只有一个以包名为名的根节点,应该直接去掉,简化目录树,方便阅读
  2. 奇怪的- heading:用法,似乎目前最新版的DocFx并不支持
  3. 我不需要Version history文档 因此写脚本去掉,这里用的是C#,当然可以用python或者其他语言,甚至shell,不过shell我不会写,python还需要现装(这里已经装了Java和.NET,再装个python有点过了),Java太难写,干脆就用C#写脚本了,为此需要装个依赖dotnet-script: dotnet tool install -g dotnet-script,运行脚本只需dotnet script [脚本路径]即可。 附上脚本,最新版位于这里
docs/scripts/CleanToc.cs
/**
* Author: Ferdinand Su
* Date: December 2nd, 2023
* Description:
* This is a workround.
* The docfx `toc.yml` generated `googleapis/docfx-doclet-1.9.0` has bad enties,
* so we have to manually fix it.
* Usage: Run at root directory, `dotnet script .\docs\scripts\CleanToc.cs`
*/

using System;
using System.IO;
var file = "docs/api/toc.yml";
if (!File.Exists(file))
{
System.Console.WriteLine("File does not exist!");
return;
}
var lines = File.ReadAllLines(file);
var output = new List<string>();
foreach (var line in lines)
{
if (line.StartsWith("- name:") ||
line == " items:" ||
line.Contains("- heading:") ||
line.EndsWith("name: \"Version history\"") ||
line.EndsWith("href: \"history.md\"")) continue;
else if (line.StartsWith(" ")) output.Add(line[2..]);
else output.Add(line);
}
File.WriteAllLines(file, output);

System.Console.WriteLine("Cleaned Successfully.");

利用DocFx生成文档

照葫芦画瓢即可,最新版位于这里

note

这里只给了配置文件,实际上目录toc.yml还有人工文档的编写没有放在博客里,你可能需要参考DocFx官方文档

docfx.json
{
"build": {
"content": [
{
"files": [
"docs/api/*.{md,yml}",
"docs/articles/*.{md,yml}"
]
},
{
"files": [
"toc.yml",
"*.md"
],
"src": "./",
"dest": "./"
}
],
"resource": [
{
"files": [
"images/**"
]
}
],
"overwrite": [
{
"files": [
"apidoc/**.md"
],
"exclude": []
}
],
"dest": "docs/_site",
"globalMetadataFiles": [],
"globalMetadata": {
"_appName": "ReFreSH.JMobileSuit",
"_appLogoPath": "images/logo_docfx.png",
"_appFaviconPath": "images/logo.png"
},
"fileMetadataFiles": [],
"template": [
"default",
"modern",
"docs/templates/material"
],
"postProcessors": [],
"markdownEngineName": "markdig",
"noLangKeyword": false,
"keepFileLink": false,
"cleanupCacheHistory": false,
"disableGitFeatures": false
}
}

编写Github Actions,实现自动发布

话不多说,附上我写的CI配置,最新版位于这里

.github/workflows/docs.yml
name: deploy_documentation
on:
push:
branches:
- master # Default release branch
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false

jobs:
publish-docs:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Build docfx-javadoc with Maven
run: mvn javadoc:javadoc
- name: Dotnet Setup
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.x
- name: Install docfx
run: dotnet tool update -g docfx
- name: Install dotnet-script
run: dotnet tool install -g dotnet-script
- name: Clean docfx toc.yml
run: dotnet script docs/scripts/CleanToc.cs
- name: Build documentation with docfx
run: docfx docfx.json
- name: Setup Pages
uses: actions/configure-pages@v3
with:
enablement: true
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
with:
# Upload entire repository
path: 'docs/_site'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2