AsciiDoc+Dockerで技術文書を作成する環境を整える

はじめに
========

AsciiDocはテキストで技術文書を作ることに適した記法ですが、配布する際にPDFや紙などへ印刷しなければなりません。紙の場合も一旦PDFにしておくと、印刷とPDFとでデザインやレイアウトに差異がなくなり、安心です。
AsciiDoc記法で書かれたテキストを技術文書らしくPDFに変換する方法は、2つあります。

1. [asciidoctor-pdf](https://github.com/asciidoctor/asciidoctor-pdf)
    Javascript実装されているツール、Node.js環境が必要
1. [asciidoctor-web-pdf](https://github.com/ggrossetie/asciidoctor-web-pdf)
    Rubyで実装されているツール、Ruby on Rails環境が必要

どちらもプログラミング言語の実行環境を整備する必要があります。ここで問題になるのが、言語側のバージョンアップが頻繁に起こることです。[こちらの記事](https://qiita.com/mmake/items/f43be3b5cd9c543c1309)によれば、1年程度で入れ替わりが起こっていることがわかります。バージョンアップが起こった際に印刷できなくなるのは避けたいです。
また、開発現場において、設計書や取扱説明書を分担することや担当プロジェクトが移り変わることが多々あるため、担当者PCにあれやこれやとインストールするのは抵抗があります。

そこで、DockerコンテナにAsciiDocの環境を構築し、バージョンアップの影響を受けないようにしました。
また、Dockerコンテナ内のAsciiDocをホスト側のVisual Studio Codeで利用するために試行錯誤しましたので、その環境構築の方法とVisual Studio Codeの設定を紹介したいと思います。

システム構成
============

自分のPC(Clientと呼びます)だけで技術文書作成に必要なものを準備します。

```mermaid
classDiagram
    class Client {
        +OS Windows
    }
    class User {
    }
    class VScode {
        +Install AsciiDoc extension
        +Install Draw.io Integration extension
        +Initial configuration for extensions
        +Create documents with AsciiDoc syntax
        +Create diagrams with Text to Diagram syntax
        +Request PDF output from AsciiDoc
    }
    class WSL {
        +Install Docker
    }
    class Docker {
    }
    class BatchFile {
    }
    class AsciiDoc {
        +Render and preview documents
        +Request rendering to Kroki
        +Execute batch file for PDF output
    }
    class Kroki {
        +Render UML and SysML diagrams
    }
    class Draw-io-Integration {
        +Create non-UML_SysML diagrams
        +Save diagrams as SVG files
    }
    class asciidoctor {
        +Convert files to PDF
        +Save PDF to specified location
    }
    class PNG {
    }
    class SVG {
    }

    User --> Client : Installs on
    User --> WSL : Installs on
    User --> VScode : Installs on
    User --> AsciiDoc : Edits documents with
    User --> Draw-io-Integration : Uses for diagrams
    User --> BatchFile : Creates
    Client --> WSL : Contains
    Client --> VScode : Contains
    Client --> Docker : Runs in container
    VScode --> AsciiDoc : Uses extension
    VScode --> Draw-io-Integration : Uses extension
    AsciiDoc --> BatchFile : Uses
    AsciiDoc --> Kroki : Sends rendering requests to
    AsciiDoc --> asciidoctor : Sends PDF output request to
    AsciiDoc --> SVG : Gets
    AsciiDoc --> PNG : Gets
    Draw-io-Integration --> SVG : Creates
    BatchFile --> asciidoctor : Uses
    WSL --> Docker : Contains
    Docker --> asciidoctor : Runs
    Docker --> Kroki : Runs
    asciidoctor --> PDF : Converts and saves
    asciidoctor --> Kroki : Uses
    asciidoctor --> PNG : Gets
    Kroki --> PNG : Creates
```

インストールと初期設定
======================

Client
------

Clientの前提は次のとおりです。

-   Windows 10 Pro

-   Zscaler によるTLS通信

-   プロキシ経由でインターネット接続

-   BISOのIntel VT-d設定が有効化済み(要らないかも)

プロキシ、Zscalerのインストールや初期設定は終えているものとします。

### VSCode (Visual Studio Code)

技術文書を編集するツールとして利用します。

[公式HP](https://code.visualstudio.com/)からインストーラをダウンロードし、実行します。
インストール設定はデフォルトのままで良いです。

### WSL & Docker

WindowsにインストールできるDockerは、Docker Desktop for Windows と
Docker on WSL があります。

-   Docker Desktop for Windows:

    -   簡単にインストール可能、GUI上でコンテナやイメージを管理できる

    -   ('24/4時点)商用利用は、10万米ドルの収入、もしくは、従業員251人以上の企業の場合、ビジネスサブスクリプション契約が必要

    -   バックエンドにHyper-V、もしくは、WSL2を選択する(詳しくは[Docker公式HP](https://docs.docker.jp/desktop/install/windows-install.html)を参照のこと)

-   Docker on WSL

    -   Linuxコマンドを使いインストール、`おま環` によってはうまくいかない場合がある、LinuxやPowerShellなどの知識が必要

    -   今のことろ利用制限はない

    -   WSL上でDockerを実行する

本記事ではWSLの方の手順を記載します。

`Windowsキー` &gt; `PowerShell` を入力 &gt; 候補の中から `Windows PowerShell` を右クリック &gt; `管理者として実行` &gt; 以下のコマンドを実行

**PowerShell**
```PowerShell
wsl --list --online
# Ubuntu-22.04 があることを確認
wsl --install -d Ubuntu-22.04
# ユーザ名とパスワードを入力
```

インストール後WSLが起動します。放置していると初期設定後WSLが自動的に終了しますが、終了しないときは次のコマンドで終了します。以降も終了するときに使います。

**WSL**
```bash
exit
```


WSLを起動し、Dockerをインストールします。以後起動する手順は基本的に明示しません。

**PowerShell**
```PowerShell
wsl -d Ubuntu-22.04
# ディストリビューションが1つなら wsl だけでよい
```

**WSL**
```bash
sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt update -y
sudo apt install -y docker.io docker-compose
sudo gpasswd -a $(whoami) docker
sudo chgrp docker /var/run/docker.sock
exit
```

:::note info
-   プリインストールされているパッケージがトラブルの原因にならないように一度削除します。

-   インストール後、`sudo` なしでdockerコマンドを扱えるようにWSLユーザをグループに追加します。
:::

一度WSLを再起動し、Dockerプロセスに変更した内容を反映します。

**PowerShell**
```PowerShell
wsl --shutdown
wsl -d Ubuntu-22.04
```

**WSL**
```bash
docker version
# 下記 docker-version.log を参照
```

**docker-version.log**

    Client: Docker Engine - Community
     Version:           26.0.0
     API version:       1.45
     Go version:        go1.21.8
     Git commit:        2ae903e
     Built:             Wed Mar 20 15:17:48 2024
     OS/Arch:           linux/amd64
     Context:           default

    Server: Docker Engine - Community
     Engine:
      Version:          26.0.0
      API version:      1.45 (minimum version 1.24)
      Go version:       go1.21.8
      Git commit:       8b79278
      Built:            Wed Mar 20 15:17:48 2024
      OS/Arch:          linux/amd64
      Experimental:     false
     containerd:
      Version:          1.6.28
      GitCommit:        ae07eda36dd25f8a1b98dfbf587313b99c0190bb
     runc:
      Version:          1.1.12
      GitCommit:        v1.1.12-0-g51d5e94
     docker-init:
      Version:          0.19.0
      GitCommit:        de40ad0

Zscalerのルート証明書をインストールし、Docker hub等のDockerイメージをpullできるようにします。`Win-User` はWindowsのユーザ名に置き換えます。以降同様に置き換える場所があります。

`Windowsキー` &gt; `証明書の管理` を入力 &gt; 候補から `ユーザ証明書の管理` を選択 &gt; `信頼されたルート証明機関` &gt; `証明書` &gt; `Zscaler Root CA` &gt; `詳細` &gt; `ファイルにコピー` &gt; `次へ` &gt; `Base 64 encoded X.509` &gt; 保存する場所を選択(ex. C:\\Users\\Win-User\\zscaler.cer) &gt; `次へ` &gt; `完了` &gt; WSL上で以下のコマンドを実行

**WSL**
```bash
sudo cp -p /mnt/c/Users/Win-User/zscaler.cer /usr/local/share/ca-certificates/zscaler.crt
sudo update-ca-certificates --fresh
```

初期設定後、hubからpullできるか試します。

**WSL**
```bash
docker run hello-world
# 下記 docker-run.log を参照
```

**docker-run.log**

    Unable to find image 'hello-world:latest' locally
    latest: Pulling from library/hello-world
    c1ec31eb5944: Pull complete
    Digest: sha256:53641cd209a4fecfc68e21a99871ce8c6920b2e7502df0a20671c6fccc73a7c6
    Status: Downloaded newer image for hello-world:latest

    Hello from Docker!
    This message shows that your installation appears to be working correctly.

    To generate this message, Docker took the following steps:
     1. The Docker client contacted the Docker daemon.
     2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
        (amd64)
     3. The Docker daemon created a new container from that image which runs the
        executable that produces the output you are currently reading.
     4. The Docker daemon streamed that output to the Docker client, which sent it
        to your terminal.

    To try something more ambitious, you can run an Ubuntu container with:
     $ docker run -it ubuntu bash

    Share images, automate workflows, and more with a free Docker ID:
     https://hub.docker.com/

    For more examples and ideas, visit:
     https://docs.docker.com/get-started/

### asciidoctor

WSLで以下のコマンドを実行しDockerイメージをDocker hubよりpullします。

**WSL**
```bash
docker pull asciidoctor/docker-asciidoctor:latest
```

asciidoctorはPDF出力の度に実行しますので、この時点で `docker run` は実行しません。

### Kroki

UML/SysUMLなどのText to Diagramにより記述された図を画像に変換するKrokiをインストールします。Krokiは公式サーバを使用できますが、文書データがインターネット上に流れるため社内手続きが困難だったりそもそも使用が制限されていたりします。よって、Client上で動作するDockerコンテナを使用します。

Krokiは、PlantUML、Mermaid、D2といった様々なText to Diagramの記法に対応しています。各記法には長所短所があり、1つの文書の中で使い分けることができます。もちろん、AsciiDocはそれらの記法に対応しています。詳しくは、[\[Kroki公式HP\]](#Kroki公式HP)のご参照ください。

空白と全角文字を含まないフォルダ(ex. C:\\Users\\Win-User\\work)に作成し、フォルダ内を右クリックのコンテキストメニューから `Code で開く` を選択 &gt; VSCodeのサイドメニューから `Explorer` を選択 &gt; &gt; `Explorer` の `(フォルダ名)` の `New file …​` を選択し、ファイル名に `docker-compose.yml` を入力 &gt; ファイルの内容に下記の内容を貼り付けて保存

**docker-compose.yml**

    version: "3"
    services:
      core:
        image: yuzutech/kroki
        environment:
          - KROKI_MERMAID_HOST=mermaid
          - KROKI_BPMN_HOST=bpmn
          - KROKI_EXCALIDRAW_HOST=excalidraw
        ports:
          - "8000:8000"
      mermaid:
        image: yuzutech/kroki-mermaid
        ports:
          - "8002:8002"
      bpmn:
        image: yuzutech/kroki-bpmn
        ports:
          - "8003:8003"
      excalidraw:
        image: yuzutech/kroki-excalidraw
        ports:
          - "8004:8004"

WSLで次のコマンドを入力します。
`WSL_User` はWSLのユーザ名に置き換えます。以降同様に置き換える場所があります。

**WSL**
```bash
cp /mnt/c/Users/WSL_User/work/docker-compose.yml .
docker-compose up -d
```

ブラウザから[KrokiサーバのURL](http://localhost:8000/)にアクセスし、Krokiのトップページが表示されるか確認します。

### (2024/6/26変更) BatchFile

VSCodeを操作することでasciidoctor-pdfを実行するためのバッチファイルを作成します。

`docker-compose.yml` と同様に、同じフォルダに `conv-asciidoc-pdf.bat` を作成 &gt; ファイルの内容に下記の内容を貼り付けて保存

`WSL_User` と `WSL_Distribution` の値は、WSLのユーザ名とディストリビューションに置き換えます。

**conv-asciidoc-pdf.bat**
```bat
@echo off
setlocal enabledelayedexpansion

REM User Settings
set "WSL_User=hoge"
set "WSL_Distribution=Ubuntu-22.04"

REM Set the current directory to the variable "volume"
for %%A in ("%CD%") do set "volume=%%~dA"

REM Initialize variables
set "pdfArgs="
set "vpath="
set "ipath="
set "tpath="
set "w_tpath="
set "nextIsPath=false"
set "themeFound=false"

REM Process command line arguments
for %%I in (%*) do (
    set "arg=%%~I"
    if "!nextIsPath!"=="true" (
        set "vpath=%%I"
        set "vpath=!vpath:c:\=/mnt/c/!"
        set "vpath=!vpath:\=/!"
        set "nextIsPath=false"
    ) else if "!arg!"=="-B" (
        set "nextIsPath=true"
    ) else if "!arg!"=="-" (
        REM Do nothing
    ) else (
        if "!arg:~-4!"==".pdf" (
            set "pdfArgs=!pdfArgs! "/documents/%%~nI%%~xI""
            set "ipath=!ipath! "/documents/%%~nI.adoc""
            set "w_tpath=%%I"
            set "w_tpath=!w_tpath:.pdf=.yml!"
            set "tpath=!tpath! "/documents/%%~nI.yml""
        ) else (
            set "pdfArgs=!pdfArgs! %%I"
        )
    )
)

REM Check if the theme file exists and run the appropriate Docker command
if exist "%w_tpath%" (
    set "themeFound=true"
    powershell -Command ^
        wsl -d !WSL_Distribution! -u !WSL_User! exec ^
            docker run ^
                --rm ^
                --network host ^
                -v !vpath!:/documents ^
                asciidoctor/docker-asciidoctor ^
                    asciidoctor-pdf ^
                        -n -q ^
                        -b pdf ^
                        -d article ^
                        --theme !tpath! ^
                        -a source-highlighter=rouge ^
                        -a rouge-style=monokai ^
                        -a scripts=cjk ^
                        -a allow-uri-read ^
                        -r asciidoctor-kroki ^
                            -a kroki-server-url=http://localhost:8000 ^
                            -a kroki-default-format=png ^
                        !pdfArgs! ^
                        !ipath!
) else (
    set "themeFound=false"
    powershell -Command ^
        wsl -d !WSL_Distribution! -u !WSL_User! exec ^
            docker run ^
                --rm ^
                --network host ^
                -v !vpath!:/documents ^
                asciidoctor/docker-asciidoctor ^
                    asciidoctor-pdf ^
                        -n -q ^
                        -b pdf ^
                        -d article ^
                        -a source-highlighter=rouge ^
                        -a rouge-style=monokai ^
                        -a scripts=cjk ^
                        -a pdf-theme=default-with-fallback-font ^
                        -a allow-uri-read ^
                        -r asciidoctor-kroki ^
                            -a kroki-server-url=http://localhost:8000 ^
                            -a kroki-default-format=png ^
                        !pdfArgs! ^
                        !ipath!
)
```

:::note info
-   このBatchFileは、VSCodeのAsciiDocから実行されます。その設定は、この後行います。

-   AsciiDocからファイルパスなどの引数を受け取り、ファイルパスはWSLのファイルパスに置き換えます。

-   PowerShell &gt; WSL &gt; Docker &gt; asciidoctorコンテナRun &gt; asciidoctor-pdf を実行しています。

-   PDFに出力する際に参照するテーマファイルを指定できます。テーマファイルの指定方法は、[TipsのHeader & Footer](https://qiita.com/drafts/3118c12e73e54f479395/edit#2024626%E8%BF%BD%E8%A8%98-header--footer)で説明します。テーマファイルの指定はいくつか方法がありますが、間接的に実行するため、Docker上の絶対パスが指定できる`--theme` オプションを使用します。テーマファイルの指定方法は、リファレンスマニュアルの[Apply a Theme](https://docs.asciidoctor.org/pdf-converter/latest/theme/apply-theme/)を参照してください。

-   テーマファイルを指定しなければ、日本語に対応しているテーマファイルを使用します。
   
-   asciidoctor-krokiはUMLをSVGに変換できますが、現バージョンではラスタライズ面に問題があり、テキストが消えてしまうため、PNGに変換しています。

-   asciidoctor-pdfが変換したPNGは、HTTPのPOSTまたはGETメソッドでKrokiから取得します。その際、`--network host` と `-a allow-uri-read` のオプションが必要になります。

-   PowerShellスクリプトを試してみましたが、VSCodeからの引数を受け取れなくうまくいきませんでした。
試したこと: [PowerShellの実行権設定](https://qiita.com/KANTU/items/e843480b5b8bc4a4590a)、[PowerShellポリシー](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.security/set-executionpolicy?view=powershell-7.4)
:::

### AsciiDoc

VSCodeにAsciiDocの拡張機能をインストールします。AsciiDocは、LMLの一種で、Markdownより設計書や取扱説明書などの技術文書を作ることに向いています。Markdownとの比較は、[このサイト](https://qiita.com/zyyx-matsushita/items/203038497d29a667106e)や[このサイト](https://qiita.com/sake8223/items/d26001dda80d9e2d9307)で紹介されています。

VSCodeのサイドメニューから `Extensions` を選択 &gt; `Search Extensions..` に `AsciiDoc` を入力 &gt; 候補の中から `AsciiDoc (asciidoctor)` の `Install` を選択

VSCodeのサイドメニューから `Manage` を選択 &gt; `Settings` で以下を設定

-   `Seach settings` に `asciidoc kroki` を入力 &gt; `Asciidoc > Extensions: Enable Kroki` をチェックオン

-   `Seach settings` に `asciidoctor pdf command path` を入力 &gt; `Asciidoc > Pdf: Asciidoctor Pdf Command Path` に `conv-asciidoc-pdf.bat` のファイルパスを入力(ex.   C:\\Users\\Win-User\\work\\conv-asciidoc-pdf.bat)

-   `Seach settings` に `asciidoctor preview attributes` を入力 &gt; `Asciidoc > Preview: Asciidoctor Attributes` の `Edit in settings.json` を選択 &gt; `settings.json` の `"asciidoc.preview.asciidoctorAttributes"` を次のように入力

**settings.json**

        "asciidoc.preview.asciidoctorAttributes": {
            "kroki-server-url": "http://localhost:8000", // <- added
            "kroki-default-format": "png" // <- added
        },

### Draw.io Integration

VSCodeにDraw.ioの拡張機能をインストールします。Draw.ioは、簡単に言えばMS-PowerPointの代わりにポンチ絵作成することに加え、UMLのモデリング、フローチャートなど技術文書で使う図はほとんど描けるツールです。UMLの図であれば、Text to Diagramのテキストを出力できます。

VSCodeのサイドメニューから `Extensions` を選択 &gt; `Search Extensions..` に `Draw.io` を入力 &gt; 候補の中から `Draw.io Integration (Henning Dieterichs)` の `Install` を選択

Test
====

試しにAsciiDocファイルを作成し、プレビューとPDF出力が可能かテストします。

VSCodeを起動し、`C:\Users\Win-User\work\hoge.adoc` を作成し、以下の内容を保存します。

**hoge.adoc**
```asciidoc
= テストタイトル

== 見出し1

ほげ

[source, bash]
----
echo -n hoge && echo foo
----

[mermaid]
----
classDiagram
    class Client {
        +OS Windows
    }

----

image:hoge.drawio.svg[hoge svg]
```

VSCodeで `C:\Users\Win-User\work\hoge.drawio.svg` を作成します。VSCodeで `hoge.drawio.svg` を開くと、Draw.ioでSVGファイルを編集できます。 デフォルトだと `.drawio.svg` 等の拡張子でDraw.ioが起動する設定になっています。

AsciiDoc記法については、下記が参考になります。

-   [AsciiDoc公式ユーザーズガイド](https://asciidoc-py.github.io/userguide.html)

-   [チートシート](http://www.venus.dti.ne.jp/~iisaka/DocSys/cheatsheet-ja/asciidoc-869/asciidoc-869.html)

-   [文法クイックリファレンス](https://takumon.github.io/asciidoc-syntax-quick-reference-japanese-translation/)

-   [asciidoctor公式リファレンス](https://docs.asciidoctor.org/asciidoc/latest/sections/numbers/)

Krokiで扱える記法については、下記が参考になります。

-   <https://kroki.io/>

Preview
-------

VSCode でAsciiDocのプレビューを表示します。

VSCode上で `.adoc` ファイルを開く &gt; ファイルタブ上で右クリック &gt; `Open Preview`

PDF Export
----------

VSCode でPDFファイルを出力します。

VSCode上で `.adoc` ファイルを開く &gt; ファイルエディタがアクティブになっている状態で `F1キー` &gt; `AsciiDoc: Export Document as PDF` を入力 &gt; 候補から `AsciiDoc: Export Document as PDF` を選択 &gt; PDFで保存するファイルの名前と場所を選択

指定されているスクリプトを実行できればVSCodeの右下にポップアップが表示されますが、PDFを出力できたかどうかはわからないです…​

TIPS
====

AsciiDoc
--------------

#### 画像貼り付け

Wordの画像貼り付けの感覚で、クリップボードの画像を文書に挿入できます。

画像データがクリップボードにある状態で、VSCodeのAsciiDocエディタに `Ctrl` + `Alt` + `V` を入力すると、クリップボードの画像を貼り付けられます(実際はクリップボードの画像をファイルに保存し、リンクを貼り付けられる)

#### 文書のセクションマージ

AsciiDoc文書をAsciiDoc文書に挿入できることを利用し、文書作成を分担できます。

例えば、Aさんが表紙と1章、Bさんが2章を担当しているとします。下記のように文書をそれぞれ作成します。

**ファイル**
```
work
├── classdiagram.adoc
├── main.adoc
├── section1.adoc
└── section2.adoc
```

**main.adoc (Aさん)**
```
= Doc Title
:author: tirple-3-packun
:version-label: v1.0
:docdate:  2024-04-01
:experimental:
:toc: left
:toclevels: 2
:sectnums: |,all|
:lang: ja
:imagesdir: ./assets/
:xrefstyle: short

== introduction

This is tech doc.

== section1

include::section1.adoc[]

== section2

include::section2.adoc[]

```

**section1.adoc (Aさん)**
```
setction1 contents
```

**section2.adoc (Bさん)**
```
setction2 contents

include::classdiagram.adoc[]
```

**classdiagram.adoc (Bさん)**
```
[mermaid]
----
classDiagram
    class Client {
        +OS Windows
    }

----
```

`main.adoc` をプレビューすると、`section1.adoc` と `section2.adoc`、`classdiagram.adoc` の内容を読み込み、1つの文書になります。PDFも同様です。
AsciiDocに限らずソースコードなどテキストで書かれているものなら大抵挿入できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695440/bc9eac3f-8331-ce1d-f5bc-140ad9101925.png)

#### (2024/6/26追記) Header & Footer

PDFに出力する際にヘッダーとフッターを加える方法を解説します。

デフォルトのテーマファイルを使用すると、ブック形式のページ番号（奇数ページが左下、偶数ページが右下）のフッターが追加されます。ヘッダーはありません。

ヘッダーを追加したり、フッターの内容を変更するには、テーマファイルを準備します。テーマファイルはYAML記法で記述します。

**出力イメージ**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695440/9da79911-352b-4d98-016f-bb0443c6f2bc.png)

**ファイル**
```
work
├── confidential_mark.drawio.svg
├── hoge.drawio.svg
├── main.adoc
└── main.yml
```

**main.adoc**
```asciidoc
= テストタイトル
:author: tirple-3-packun
:revnumber: 1.0
:docdate: 2024-06-25
:experimental:
:toc: left
:toclevels: 2
:sectnums: |,all|
:lang: ja

== 見出し1

ほげ

[source, bash]
----
echo -n hoge && echo foo
----

[mermaid]
----
classDiagram
    class Client {
        +OS Windows
    }
----

image:hoge.svg[]
```

**hoge.drawio.svg**
VSCodeでSVGファイルを作成します。作成後、エクスポートします。

`File` > `Export` > `.svg` > ファイル名に`hoge.svg`を入力し、保存場所を指定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695440/28fccc2f-f6b2-f54e-d3cc-56c7e958f582.png)

:::note info
- 文字列を図形に加える場合、asciidoc-pdfのDockerコンテナにインストールされているフォントファミリーを指定する必要があります。今回準備するテーマファイルは、テーマファイルを指定しない場合に使用する、日本語対応のプリインストールテーマファイルがベースになります。プリインストールのテーマファイルが使用しているフォントファミリーを調べる方法は、「[プリインストールのテーマファイルの内容を確認する](https://qiita.com/drafts/3118c12e73e54f479395/edit#2024626%E8%BF%BD%E8%A8%98-%E3%83%97%E3%83%AA%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%AEtheme%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%86%85%E5%AE%B9%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B)」に記載します。調べたフォントファミリーをマークのフォントファミリーに指定します。
- 文字列を装飾する場合、文字をSVGに変換する必要があり、VSCodeのdrawio.integrationのエクスポート機能は変換に対応していません。よって、マークの文字装飾オプションをOFFにします。装飾付きで出力する方法は、[Drawwioの公式HP](https://www.drawio.com/doc/faq/svg-export-text-problems)で解説されています。
:::

**main.yml**
.adocファイルと同じ名前でファイルを作成します。異なるファイル名を指定したい場合は、BatchFileを変更します。

```yml
extends: default-with-font-fallbacks
header:
  height: 0.5in
  line-height: 1
  margin: [0, 0.3in, 0, 0.3in]
  padding: [0.1in, 0, 0.1in, 0]
  border-color: #DDDDDD
  border-style: solid
  border-width: 0.25
  columns: <20% =0% >80%
  recto:
    left:
      content: image:confidential_mark.svg[fit=scale-down, position=center left]
    right:
      content: '{document-title} - Rev.{revnumber}'
  verso:
    left:
      content: $header-recto-left-content
    right:
      content: $header-recto-right-content
footer:
  height: 0.5in
  line-height: 1
  margin: [0, 0.3in, 0, 0.3in]
  padding: [0.1in, 0, 0.1in, 0]
  border-color: #DDDDDD
  border-style: double
  border-width: 1
  columns: <80% =0% >20%
  recto:
    left:
      content: '(C) Copyright {docyear} Your company All rights reserved.'
    right:
      content: '{page-number} of {page-count}'
  verso:
    left:
      content: $footer-recto-left-content
    right:
      content: $footer-recto-right-content
page:
  numbering:
    start-at: toc
```

:::note info
- `extends`は、ベースとするテーマファイルです。今回は、テーマファイルを指定しない場合に使用するプリインストールされているテーマファイルを指定しています。
- `columns`は、ヘッダーを3列に分割し、それぞれの幅割合と寄せ位置を指定します。
- `recto`は、奇数ページに適用されるルールです。`verso`は、偶数ページに適用されます。`$header-recto-left-content`を指定することで奇数ページに指定しているルールをそのまま適用しています。
- 指定可能な項目は、リファレンスマニュアルの[Theme Keys Reference
](https://docs.asciidoctor.org/pdf-converter/latest/theme/keys/)を参照してください。`header`と`footer`は、[Running Content Category Keys](https://docs.asciidoctor.org/pdf-converter/latest/theme/running-content/#footer)に記載されています。
- `{document-title}`は.adocファイルの`= テストタイトル`の値を参照します。
- `{revnumber}`は.adocファイルの`revnumber`の値を参照します。
- `{docyear}`は、adocファイルの`docdate`の年を参照します。
- 他のプレースホルダーは、リファレンスマニュアルの[Add Running Content](https://docs.asciidoctor.org/pdf-converter/latest/theme/add-running-content/)と[Document Attributes Reference](https://docs.asciidoctor.org/asciidoc/latest/attributes/document-attributes-ref/)を参照してください。
:::

**confidential_mark.drawio.svg**
テーマファイルに指定しているConfidentialマークをhoge.drawio.svg同様に作成し、エクスポートします。テキストのプロパティも同様に指定します。

`File` > `Export` > `.svg` > ファイル名に`confidential_mark.svg`を入力し、保存場所を指定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695440/826e92ef-6357-d6ce-3deb-08ceca8d30b3.png)

ファイルを準備できましたら、[PDF Export](https://qiita.com/drafts/3118c12e73e54f479395/edit#pdf-export)を操作し、PDFを出力します。

#### (2024/6/26追記) プリインストールのThemeファイルの内容を確認する

プリインストールのテーマファイルで使用しているフォントファミリーやその他設定値を確認するには、以下の操作を行います。

**WSL**
```bash
docker run -it --rm --entrypoint /bin/ash asciidoctor/docker-asciidoctor
find / -type f -name "*default-with-font-fallbacks*"
# find.log参照
cat /usr/lib/ruby/gems/3.2.0/gems/asciidoctor-pdf-2.3.15/data/themes/default-with-font-fallbacks-theme.yml
# cat.log参照
```

**find.log**
```
/usr/lib/ruby/gems/3.2.0/gems/asciidoctor-pdf-2.3.15/data/themes/default-with-font-fallbacks-theme.yml
```

**cat.log**
```
extends: default
font:
  catalog:
    merge: true
    # M+ 1p supports Latin, Latin-1 Supplement, Latin Extended, Greek, Cyrillic, Vietnamese, Japanese & an assortment of symbols
    # It also provides arrows for ->, <-, => and <= replacements in case these glyphs are missing from font
    M+ 1p Fallback: GEM_FONTS_DIR/mplus1p-regular-fallback.ttf
    Noto Emoji: GEM_FONTS_DIR/notoemoji-subset.ttf
  fallbacks: [M+ 1p Fallback, Noto Emoji]
```


GitHub Copilot
--------------

LMLは、名前のとおり一種のプログラミング言語です。プログラミング言語ということは、GitHub Copilotによる支援を受けられるということです。VSCodeは、GitHubの拡張機能があり、記事を書きながら支援を受けられます。

* VSCodeのサイドメニューから `Extensions` を選択 &gt; `Search Extensions..` に `GitHub Copilot` を入力 &gt; 候補の中から `GitHub Copilot (GitHub)` の `Install` を選択 (GitHub Copilot Chatも同時にインストールされる)

* VSCodeのサイドメニューから `Accounts` &gt; `Sign in with GitHub to use GitHub Copilot` を選択 &gt; ブラウザが起動し、`Visual Studio Code を開こうとしています。` の `開く` を選択 &gt; GitHubにサインイン

次のような支援を受けられます。一度使い始めたらヤメラレません。

-   .adocファイルを編集すると文書全体を俯瞰した候補を出してくれる。

-   .adocファイルの右クリックでコンテキストメニューから `Copilot` &gt; `Start Inline Chat` &gt; プロンプトを入力すると、候補を出してくれる。

-   VSCodeのサイドメニューから `Chat` を選択 &gt; チャットウィンドウが表示されるので、プロンプトを入力すると候補を出してくれる。参照範囲は、VSCodeで開いているフォルダやファイルになり、ファイルを俯瞰的、かつ、ファイル間を横断的に見て支援してくれる。画像もSVG形式で保存する理由はこれが大きい。

:::note warn
-   GitHub Copilotは、GitHubの有料プランになりますので、GitHubのアカウント取得と別途契約が必要です。

-   Copilotのビジネス利用は、生産性を劇的に向上させる反面、様々なリスクを伴います。企業における利用は十分検討の上、リスク対策を行ってください。参考URL:

    -   <https://logmi.jp/tech/articles/329510>

    -   <https://levtech.jp/media/article/column/detail_340/>

    -   <https://tech.macloud.jp/entry/2023/03/31/125606>
:::

記法変換
--------

AsciiDocから、例えばQiitaが対応しているMarkdownに記法を変換する方法を紹介します。CopilotやGPTにお願いしても良いですが、1プロンプトの文字数制限があり少し使いづらいです。この方法は、ファイル単位で変換できます。

VSCode上で `.adoc` ファイル(ex. c:\\Users\\Win-User\\work\\hoge.adoc)を開く &gt; ファイルエディタがアクティブになっている状態で `F1キー` &gt; `AsciiDoc: Save to DocBook` を入力 &gt; 候補から `AsciiDoc: Save to DocBook` を選択

**WSL**
```bash
sudo apt install -y pandoc # 初回のみ
pandoc -f docbook -t markdown_strict --wrap=preserve /mnt/c/Users/Win-User/work/hoge.xml -o /mnt/c/Users/Win-User/work/hoge.md
```

`-t markdown_strict` は、HTMLを指定することもできます。
注意点として、AsciiDocのキー入力示す `kbd:[Windows]` は変換により `Windows` と装飾の無い文字列になります。よって、変換の可能性があるならAsciiDocにおいても `kbd:[Windowsキー]` と敢えて"キー"を付けることを推奨します。

Text to Diagram
---------------

Text to Diagramは、記法と図法ごとに文法の知識が必要ですが、覚える必要はありません。文法への翻訳はAIに任せればよいです。例えば、上のクラス図は、以下のユースケースシナリオのプロンプトをGPTに入力し、出力されたものを手直しして作成しました。Text to Diagramで図を描く最大のメリットは、AIに作らせたテキストの図を自分で手直しできることだと思います。

**Prompt**

    あなたはシステム設計のプロフェッショナルである。Mermaid記法のclassDiagram形式で以下の関係を記述せよ。
    #ClientのOSはWindowsである
    #ユーザはClientにVScodeとWSLをインストールする
    #ユーザはWSLにDockerをインストールする
    #ユーザはClientにdocker-compose.ymlとconv-asciidoc-pdf.batを作成する
    #ユーザはVSCodeにAsciiDocとDraw.io Integrationの拡張機能をインストールし、それぞれ初期設定を行う
    #ユーザはClientのDockerコンテナ上にasciidoctorとKrokiを実行する
    #ユーザはVSCodeを使用しasciidoc記法でドキュメントを作成する
    #AsciiDocはユーザがドキュメントを編集する度にレンダリングし、プレビューに出力する
    #ユーザはVSCodeを使用しText to Diagram記法でUMLとSysMLを作図する
    #AsciiDocはユーザがUML又はSysMLを編集する度にKrokiへレンダリングを要求し、Krokiから受け取ったレンダリング結果をPreviewに表示する
    #ユーザはDraw.io Integrationを使用しUMLとSysML以外の図を作図する
    #ユーザはDraw.io Integrationで作図した図をSVG形式で保存し、ドキュメントにSVGファイルを指定する
    #ユーザはVSCodeのAsciiDocに指定のファイルのPDF出力を指示する
    #AsciiDocはPDF出力を指示されたら、バッチファイルを実行しWSLのasciidoctorへPDF出力を要求する
    #asciidoctorはPDF出力を要求されたら、指定のファイルをPDFに変換し、指定の保存場所へPDFを保存する

さいごに
========

AsciiDocの環境を調べながら構築してみたところ途中でDocker Desktopの利用規約の変更を知り、急遽WSL版に書き換えた結果、環境が少し複雑になりました。Markdownの方が楽に構築できます。それでも、自動で見出し番号を振ってくれる、外部ファイルをインポートできたりなど、MarkdownよりAsciidocの方が技術文書を作る機能が充実しており、個人的には手間をかける価値はあると感じています。

また、担当者の個人作業は担当者PC内で処理を完結したいこともあって上のシステム構成になりましたが、サーバ側でPDF変換やUMLの図変換をできれば環境構築がもっと楽になります。機会があれば、開発サーバ側でGitやJenkinsと連携し、textlintによる文章の静的解析や、Merge pull request後にPDFファイルをリリースできるようにしたいです。

参考文献
========

<https://hub.docker.com/r/asciidoctor/docker-asciidoctor>

<https://github.com/asciidoctor/asciidoctor-kroki>

<https://hub.docker.com/r/yuzutech/kroki>

<https://qiita.com/ichi-ken/items/5a04a732524c72ff809a>

<https://learn.microsoft.com/ja-jp/windows/wsl/install>

<https://www.linkedin.com/pulse/how-resolve-x509-certificate-issue-wsl2-abhinav-kumar-singh>

<https://dev.classmethod.jp/articles/docker-cli-without-dockerdesktop-on-windows/>