Asciidoctor 與 gradle 整合生成 PDF備忘
緣起
簡單文件一般使用 markdown
就足夠了,尤其單頁文件,不過稍微複雜點的文件用這玩意顯然就很不方便了,就單單一個不支援 include
就很痛苦,雖然可以用 pandoc
做一些 hack 處理,不過麻煩啊,尤其還需要生成 html5
、pdf
的時候。
所以這時候個人傾向於使用 asciidoc
格式來寫文件。
配置
編譯 asciidoc
成 html5
、pdf
的話,Asciidoctor 提供了命令列工具,不過這玩意需要通過 gem 安裝,如果額外還想生成 PDF,還需要安裝 asciidoctor-pdf,看看官方文件就知道麻煩事不少。
所以還是配合 gradle
省事,一個配置檔案搞定,尤其對於 java 程式設計師來說,gradle 應該算是標配了吧——呃,maven 使用者可能有話說。
目錄結構
gradle 專案的一個最基本的目錄結構應該如下:
. ├── build.gradle ├── data │ ├── fonts │ │ ├── KaiGenGothicCN-Bold-Italic.ttf │ │ ├── KaiGenGothicCN-Bold.ttf │ │ ├── KaiGenGothicCN-Regular-Italic.ttf │ │ ├── KaiGenGothicCN-Regular.ttf │ │ ├── RobotoMono-Bold.ttf │ │ ├── RobotoMono-BoldItalic.ttf │ │ ├── RobotoMono-Italic.ttf │ │ └── RobotoMono-Regular.ttf │ └── themes │ └── basic-theme.yml ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src └── docs └── asciidoc ├── chapter │ └── 0010_overview.adoc ├── images │ └── keep └── spec.adoc
簡單說明一下:
- src/docs/asciidoc:
asciidoc
所在目錄 - data/fonts: 用於生成 PDF 的字型檔案目錄
- data/themes: 用於定義 PDF 的主題檔案目錄
build.gradle 配置
buildscript { repositories { maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } jcenter() mavenCentral() } } plugins { id "org.asciidoctor.jvm.convert" version "2.3.0" id "org.asciidoctor.jvm.pdf" version "2.3.0" } wrapper { distributionType = Wrapper.DistributionType.ALL } version = '1.0.0' asciidoctor { logDocuments true // sourceDir file('docs') sources { include 'spec.adoc' } baseDirFollowsSourceDir() // outputDir file('build/docs') // 強制每次都重新生成 outputs.upToDateWhen { false } outputOptions { backends = ['html5', 'pdf'] } // pdfThemes { // local 'basic', { // styleDir = file('data/themes/basic') // styleName = 'basic' // } // } attributes 'pdf-fontsdir': file('data/fonts') attributes 'pdf-stylesdir': file('data/themes') attributes 'pdf-style': 'basic' // 版本號 attributes 'revnumber': project.version // 一些通用屬性 attributes 'toc': 'left' attributes 'toclevels': 4 attributes 'toc-title': '目錄' attributes 'docinfo1': '' attributes 'imagesdir': 'images' // 語法高亮,可選項有 coderay, highlightjs, prettify, pygments // 為保證生成的 html5 和 pdf 均有語法高亮,所以啟用 coderay // 使用其它幾個選項還需要做不少額外的工作,沒有必要 attributes 'source-highlighter': 'coderay' attributes 'sectnums': true attributes 'sectanchors': true attributes 'sectlinks': true attributes 'experimental': true // TIP、NOTE 之類的用自體圖示顯示 // 之所以將此屬性放置在這兒是為了避免 idea asciidoc 外掛無法正常顯示 attributes 'icons': 'font' }
重點需要注意:
- plugins 下的兩個 plugin 使用版本為
2.3.0
,而官網是2.4.0
,但是後者在各個 maven 庫中都沒發現,估計截止當前位置尚未更新 - asciidoctor 配置中可以不用官網文件寫的
pdfThemes
,也就是上面原始碼中註釋的部分,直接採用attributes 'pdf-fontsdir'
這種配置即可,看原始碼就知道,前者也不過就是為了達到後者的效果 source-highlighter
使用coderay
,這個相比其它原始碼高亮工具稍顯簡單,不過好處是不需額外配置就可以提供 PDF 高亮。
PDF 示例:
入口 adoc 檔案示例
= 開發規範
:toc: left
:toc-title: 目錄
:toclevels: 3
:source-highlighter: coderay
:imagesdir: images
:icons: font
:sectnums:
:sectanchors:
:sectlinks:
:experimental:
:revnumber: v1.0
[#overview]
== 概述
include::chapter/0010_overview.adoc[]
上述檔案其實把 build.gradle 中的 attributes
又定義了一遍,之所以如此是為了在 vscode、WebStorm 之類的工具中可以直接預覽,當然這是可選項,如果不需要這種比較一致的預覽需求,完全可以把入口 adoc 中的這些配置項刪除。
PDF 中文字型的額外配置
上述配置完成之後執行 ./gradlew asciidoctor
已經可以生成 html5、pdf 了,不過開啟 pdf 的話會發現中文亂碼,中文都變成了¬
,此問題可參見官方說明 Built-In (AFM) Fonts
提示如下:
The following text could not be fully converted to the Windows-1252 character set:
| <string with unknown glyph>
PDF 亂碼示例:
之所以亂碼主要是 asciidoctor-pdf
預設使用的 default-theme.yml 中配置的字型檔案不支援中文,點開看看這個檔案就知道怎麼回事了。
可以去 asciidoctor-pdf-cjk-kai_gen_gothic 下載「懷源黑體」(思源黑體的 ttf 版)和「Roboto Mono」等寬字型,放置到 data/fonts
下面。
之後編寫 data/themes/basic-theme.yml
:
#
# 過載 https://github.com/asciidoctor/asciidoctor-pdf/blob/master/data/themes/default-theme.yml
# 使用中文字型解決 pdf 亂碼問題
#
extends: default
# 過載字型定義
font:
catalog:
KaiGen Gothic CN:
normal: KaiGenGothicCN-Regular.ttf
bold: KaiGenGothicCN-Bold.ttf
italic: KaiGenGothicCN-Regular-Italic.ttf
bold_italic: KaiGenGothicCN-Bold-Italic.ttf
Roboto Mono:
normal: RobotoMono-Regular.ttf
bold: RobotoMono-Bold.ttf
italic: RobotoMono-Italic.ttf
bold_italic: RobotoMono-BoldItalic.ttf
fallbacks:
- KaiGen Gothic CN
# 覆蓋基礎字型
base:
font_family: KaiGen Gothic CN
# 覆蓋等寬字型
literal:
font_family: Roboto Mono
最後在 build.gradle
中配置:
attributes 'pdf-fontsdir': file('data/fonts')
attributes 'pdf-stylesdir': file('data/themes')
attributes 'pdf-style': 'basic'
中文問題解決!
Spring REST Docs 版本要求
asciidoc
的另一個使用場景是配合 Spring REST Docs 生成 api 文件,不過需要注意的是這時候只能使用 1.5.x
版本的 org.asciidoctor.convert
,因為 Spring REST Docs
暫時還不支援新版 asciidoctor
。
這時候需要注意 build.gradle
中一些配置需要調整,例如:
outputOptions {
backends = ['html5', 'pdf']
}
需要調整為:
backends 'html5', 'pdf'