図入りのAsciiDoc記述からPDFを生成する環境をGradleで簡単に用意する

# この記事でのゴール
* テキストベースでUMLなどの図まで含めたドキュメントを記述・管理したい
* HTMLだけでなくPDFでドキュメントを残したい
* ドキュメントの生成はGradleに任せてコマンド一発にしたい

# 環境構築
* GradleとGraphVizのインストールが必要
* Windows 8.1 + git bashの場合だけここでは記載するが、他OSでも大体似た感じでできるはず

## Gradleのインストール
* まずsdkmanをインストール

```bash
$ curl -s http://get.sdkman.io/ | bash

Thanks for using...                                                             
                                                                                
                                                                                
     SSSSSSSSSSSSSSS DDDDDDDDDDDDD       KKKKKKKKK    KKKKKKK
   SS:::::::::::::::SD::::::::::::DDD    K:::::::K    K:::::K
  S:::::SSSSSS::::::SD:::::::::::::::DD  K:::::::K    K:::::K
  S:::::S     SSSSSSSDDD:::::DDDDD:::::D K:::::::K   K::::::K
  S:::::S              D:::::D    D:::::DKK::::::K  K:::::KKK
  S:::::S              D:::::D     D:::::D K:::::K K:::::K
   S::::SSSS           D:::::D     D:::::D K::::::K:::::K
    SS::::::SSSSS      D:::::D     D:::::D K:::::::::::K
      SSS::::::::SS    D:::::D     D:::::D K:::::::::::K
         SSSSSS::::S   D:::::D     D:::::D K::::::K:::::K
              S:::::S  D:::::D     D:::::D K:::::K K:::::K
              S:::::S  D:::::D    D:::::DKK::::::K  K:::::KKK
  SSSSSSS     S:::::SDDD:::::DDDDD:::::D K:::::::K   K::::::K
  S::::::SSSSSS:::::SD:::::::::::::::DD  K:::::::K    K:::::K
  S:::::::::::::::SS D::::::::::::DDD    K:::::::K    K:::::K
   SSSSSSSSSSSSSSS   DDDDDDDDDDDDD       KKKKKKKKK    KKKKKKK


                      mmmmmmm    mmmmmmm     aaaaaaaaaaaaa  nnnn  nnnnnnnn
                    mm:::::::m  m:::::::mm   a::::::::::::a n:::nn::::::::nn
                   m::::::::::mm::::::::::m  aaaaaaaaa:::::an::::::::::::::nn
                   m::::::::::::::::::::::m           a::::ann:::::::::::::::n
                   m:::::mmm::::::mmm:::::m    aaaaaaa:::::a  n:::::nnnn:::::n
                   m::::m   m::::m   m::::m  aa::::::::::::a  n::::n    n::::n
                   m::::m   m::::m   m::::m a::::aaaa::::::a  n::::n    n::::n
                   m::::m   m::::m   m::::ma::::a    a:::::a  n::::n    n::::n
                   m::::m   m::::m   m::::ma::::a    a:::::a  n::::n    n::::n
                   m::::m   m::::m   m::::ma:::::aaaa::::::a  n::::n    n::::n
                   m::::m   m::::m   m::::m a::::::::::aa:::a n::::n    n::::n
                   mmmmmm   mmmmmm   mmmmmm  aaaaaaaaaa  aaaa nnnnnn    nnnnnn
                                                                                
                                                                                
                                                 Now attempting installation...

Looking for a previous installation of SDKMAN...
Looking for unzip...
Looking for curl...
Looking for sed...
Installing SDKMAN scripts...
Create distribution directories...
Getting available candidates...
Prime the config file...
Download script archive...
Extract script archive...
Install scripts...
Set version to 3.3.1 ...
Attempt update of bash profiles...
Created and initialised /c/Users/tokumoto/.bash_profile
Created and initialised /c/Users/tokumoto/.bashrc
Attempt update of zsh profiles...
Created and initialised /c/Users/tokumoto/.zshrc



All done!


Please open a new terminal, or run the following in the existing one:

    source "/c/Users/tokumoto/.sdkman/bin/sdkman-init.sh"

Then issue the following command:

    sdk help

Enjoy!!!

```

* git bashを再起動するか、以下のコマンドでsdkmanへのパスを設定する

```bash
$ source ~/.sdkman/bin/sdkman-init.sh
```

* 以下のコマンドを入力し、gradleをインストール

```bash
$ sdk install gradle 2.10
==== BROADCAST =================================================================
* 22/01/16: Springboot 1.3.2.RELEASE released on SDKMAN! #springboot
* 21/01/16: Kotlin 1.0.0-beta-4589 released on SDKMAN! #kotlin
* 21/01/16: Grails 3.0.12 released on SDKMAN! #grailsfw
================================================================================

Downloading: gradle 2.10

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100   355    0   355    0     0    261      0 --:--:--  0:00:01 --:--:--     0
100 44.2M  100 44.2M    0     0  3618k      0  0:00:12  0:00:12 --:--:-- 4242k

Installing: gradle 2.10
Done installing!

Do you want gradle 2.10 to be set as default? (Y/n): y

Setting gradle 2.10 as default.
```

## Graphvizのインストール
* http://www.graphviz.org からインストールパッケージをダウンロード
* インストールパッケージを実行し、インストール
* 環境変数PATHにgraphvizに含まれるdotへのパスを加える
 * 例：windows(64ビット)環境でgraphvizの版数が2.28の場合、C:\Program Files (x86)\Graphviz 2.28\bin

# ここでの例におけるディレクトリ構成
* projectroot配下でgradleを実行することを想定
* 自前で用意するのはbuild.gradleとsrc/docs/asciidoc/*.adocだけ

```
projectroot
|-build.gradle
|-src
|  `-docs
|     `-asciidoc
|        `-sample.adoc
`-docs
   |-html5
   |  `-sample.html(生成物)
   |-pdf
   |  `-sample.pdf(生成物)
   `-images
      |-classediagram.png(生成物)
      `-syntaxtree.png(生成物)
```

# AsciiDocの記述例
* AsciiDocの基本的な記述方法については[こちら](http://qiita.com/xmeta@github/items/de667a8b8a0f982e123a)などを参照してもらい、ここでは図などの特殊な記法についてのみ例を挙げる。
* PlantUMLの記述方法については[こちら](http://ja.plantuml.com/)を参照のこと
* ditaaの記述方法については[こちら](http://ditaa.sourceforge.net/)を参照のこと
* PlantUMLはサポートしている記法も多くかなり強力な印象だが、ditaaが使える範囲は限られるかも

```asciidoc:sample.adoc
= サンプル設計書
サンプル太郎 <sample@example.com>
v1.0, 2016-03-15
:toc:

== PlantUMLによるクラス図の例
UMLはPlantUMLで記述できる。日本語（UTF-8）でも記述可能。

.クラス図
[plantuml, classediagram, png]
....
class "クラスA" {
  +メソッド1()
}
class "クラスB" {
  +メソッド2()
}
class "クラスC" {
}
"クラスA" -- "クラスB"
"クラスA" <|-- "クラスC"
....

== Ditaaによる図の例
箱と線で表現するものはDitaaで記述可能。日本語（UTF-8）は文字化けする

.a = 1 + 3の構文木
[ditaa, syntaxtree]
....
    /--------\
    |cmpExpr |
    |text:'='|
    \--------/
       |   |
  /----/   \-----\
  |              |
/--------\   /--------\
|variable|   |addExpr |
|text:'a'|   |text:'+'|
\--------/   \--------/
               |   |
           /---/   \---\
           |           |
     /----------\  /----------\
     |literal   |  |literal   |
     |text:'1'  |  |text:'3'  |
     \----------/  \----------/
....
```

# build.gradleの記述例
* 基本的な記述については[こちら](https://github.com/asciidoctor/asciidoctor-gradle-plugin)を参照
* AsciiDocの記述ファイルをsrc/docs/asciidocに置く
* docs配下にhtml5, pdf, imagesの3つのディレクトリが生成される
* pdfの出力だけにすると画像の埋め込みができない。なので、html5生成を先に行い、そのときに生成される画像ファイルをpdf生成時に流用するというトリッキーな方法を用いている

```groovy:build.gradle
apply plugin: 'org.asciidoctor.convert'
apply plugin: 'org.asciidoctor.gradle.asciidoctor'
buildscript {
	repositories {
		jcenter()
	}
	dependencies {
		classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.3'
		classpath 'org.asciidoctor:asciidoctorj-diagram:1.3.1'
		classpath 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.11'
	}
}
asciidoctorj {
	version = '1.5.4'
}
asciidoctor {
	backends = ['html5','pdf']
	requires = ['asciidoctor-diagram']
	outputDir = file('docs')
	attributes (
		'imagesdir' : "$rootDir/docs/images",
		'toc-title' : '\u76EE\u6B21',
		'numbered' : true,
	)
}
```

# コマンド
* 以下のコマンド一発でhtmlとpdfのドキュメントが生成される

```bash
$ gradle asciidoctor
```

# 出力
* 以下はPDFの出力例（余白が多いので例としてはちょっと見づらい…）

![sample-1.png](https://qiita-image-store.s3.amazonaws.com/0/37926/5a02dbc0-1411-dc78-28e7-10c400adf397.png)
![sample-2.png](https://qiita-image-store.s3.amazonaws.com/0/37926/22929181-0572-400d-6f86-de3523ebde40.png)
![sample-3.png](https://qiita-image-store.s3.amazonaws.com/0/37926/f44ccf9b-c718-ab36-a35d-86953472aa7b.png)

# 発展系
* gitで管理することで、チームでのドキュメンテーションをしやすくする
* CIに入れることで、継続的なドキュメント生成が可能
* epub3形式でもドキュメント生成可能

# ちょっと気になること
* 改行など一部の表示がhtmlとpdfとで異なる
* htmlが先に生成されるという前提でpdfの図の埋め込みを実現しているため、asciidoctorプラグインの変更次第でそのあたりの前提が崩れる可能性もあり