解決したい問題
GitHubリポジトリにREADME.adoc
という名前のファイルを作って、Asciidocの構文で文書を書くことができる。するとGitHubはAsciidocをHTMLに変換して応答するので、Markdownで書いたREADMEと同じようにきれいに整ったドキュメントをブラウザ上で見ることができる。
一例を挙げよう。
ところが困ったことがひとつある。GitHubのAsciidoc処理系(GFA, GitHub Flavored Asciidoc)が include
文をサポートしていないのだ。例のarticle.adocの最後のあたりに Include directive という見出しがあるのだが、そこをみてほしい。Asciidocのソースコード上はこう書いてある。
== Include directive
Here we include the source code of the file `src/main/java/my/Hello.java`.
[source,java]
----
include::src/main/java/my/Hello.java[]
----
GitHubが応答した画面上ではこういうふうに表示されている。
こうじゃないんだ、僕がほしいのは。プログラムのコードがドキュメントの中に埋め込まれた形になってほしい。つまりこうだ。
僕はGitHubレポジトリのREADMEドキュメントをAsciidocで書きたいと思っている。なぜかと言えばAsciidocならinclude
文が使えるはずだから。外部ファイルからプログラムのソースコードを採ってきてREADMEに埋め込みたい。これができればドキュメントを執筆する手間がおおいに省ける。いっぽうMarkdownではコードの埋め込みができない。だから僕はAsciidocでREADMEを書きたいのだ。
なぜGitHubはAsciidocをサポートしつつinclude文だけはサポートしないのだろうか?この問題は4年前から議論になっていて、いまだにopenのままだ。
これによればGitHubがinclude文をサポートする見込みは無さそうだ。でも僕はいますぐなんとかしたい。
解決方法
前述のIssue #1095のスレッドのなかで9th June 2021に @chevdoor がなんとかする方法を提案していた。参照の便宜のため、彼の投稿をそのまま引用しておこう。
This is by far my favorite workaround although it requires a little setup and tooling. Install pandoc and asciidoctor, you can then create a new (executable) .gti/hooks/pre-commit file with the following content:
#!/usr/bin/env bash
# convert all the files in the root
find . -iname "*.adoc" -type f -maxdepth 1 -not -name "_*.adoc" | while read fname; do
target=${fname//adoc/md}
xml=${fname//adoc/xml}
echo "converting $fname into $target"
asciidoctor -b docbook -a leveloffset=+1 -o - "$fname" | pandoc --markdown-headings=atx --wrap=preserve -t markdown_strict -f docbook - > "$target"
echo deleting $xml
rm -f "$xml"
done
# if we find a readme*.md, we rename to README.md
find . -iname "readme*.md" -not -name "README.md" -type f -maxdepth 1 | while read fname; do
echo Renaming $fname to README.md
mv $fname README.md
done
The script will look for all the adoc files in the root of your project (except those starting with _) and convert them. Since github picks the asciidoc by default when you have both a README.adoc and a README.md 🤦 , I have to further get my README.adoc out of the way renaming to README_src.adoc) and add extra renaming to the script.
To cheer us up, this option comes with a small benefit: your asciidoc is now linted before you ever commit, so you will spot wrong includes paths before your commit makes it in.
つまりAsciidocで書かれたファイルをHTMLに変換する処理をGitHubに依存するのを止める。ローカルでpandocとasciidocを使いREADME*.adocからREADME.mdに変換しよう。できたREADME.mdをレポジトリにcommitする。GitHub上のサイトを閲覧する人にはREADME.mdを見せればいい。
僕はこの回避策を試した。うまくいった。よし、これで行こう。
説明
僕の環境
- マシン: Mac Book Air
- OS: macOS Monterey v12.0.1
- シェル: Bash
依存するソフトウェア
pandoc
"pandoc, a universal document converter" をHomebrewでMacにインストールした。
$ brew install pandoc
asciidoctor
"asciidoctor, A fast text processor & publishing toolchain for converting AsciiDoc to HTML5, DocBook & more" をHomebrewでMacにインストールした。
$ brew install asciidoctor
プロジェクトに追加したコード
シェルスクリプト readmeconv.sh
自分のプロジェクトのルートディレクトリにシェルスクリプトを書いた。名前はなんでもいいのだが readmeconv.sh
とした。 中身は @chevdoor が示してくれたbashスクリプトをコピペしただけ。
このシェルファイルを実行可能にしておく必要がある。
$ chmod +x ./readmeconv.sh
このシェルをコマンドラインで直に実行することができる。こんなふうに。
$ ./readmeconv.sh
converting ./README_.adoc into ./README_.md
deleting ./README_.xml
converting ./article.adoc into ./article.md
deleting ./article.xml
Renaming ./README_.md to README.md
これで README_.adoc
ファイルから README.md
ファイルが生成された。
もしもAsciidocファイルに記述ミスがあればreadmeconv.sh
を実行したときにエラーが発生するだろう。エラーを手早く見つけるのに役立つ。
Gitフック
gitにpre-commitフックを設定した。.adoc
ファイルをエディタで編集した後でgit commit
コマンドを投入した時、commitが実行される直前に readmeconv.sh
を自動的に実行してREADME.md
ファイルを更新するようにした。<projectDir>/.git/hooks/pre-commit
ファイルにこう書いた。
#!/usr/bin/env bash
git secrets --pre_commit_hook -- "$@"
# convert README_.adoc to README.md
./readmeconv.sh
ファイル名をどうするか?
README_.adoc
とするのが良い。README.adoc
ではダメだった。
GitHubの公式ドキュメントAbout READMEsにこう書いてある。
If you put your README file in your repository's root, docs, or hidden .github directory, GitHub will recognise and automatically surface your README to repository visitors.
あなたのプロジェクトのレポジトリのルートディレクトリに README.adoc
と README.md
と二つのファイルがあったとしよう。ブラウザでそのレポジトリのトップページを開いた時にどっちのREADMEが表示されるだろうか?実際やってみるとREADME.md
ではなく、README.adoc
が表示された。README.adoc
ファイルを作りreadmeconv.sh
シェルで変換してREADME.md
ファイルを生成することは問題なくできる。しかしそれだと生成されたREADME.md
をGitHubが選んでくれないので意味がない。どうすればいいか?
readmeconv.sh
のbashスクリプトのコードの細部を読んでほしいのだが、このシェルはREADME_.adoc
のように余計な文字をくっつけた名前のAsciidocファイル許容し、生成したコードをREADME.md
に出力する。GitHubは README_.adoc
をREADMEドキュメントしては認識しない。GitHubはREADME.md
を見つけてそれをレポジトリの表紙として応答するだろう。これでファイル名の問題は解決した。
結論
Asciidocのinclude
文が使えればソフトウエアプロジェクトのドキュメントを書くのが楽しくなる。include
文が使えれば、プログラムのコードをREADMEに手作業でコピペする手間が省けるし、プログラムを書きかえたのにREADMEの方を直すのを忘れるおそれも無くなる。GFAがinclude文をサポートしないという問題を回避するために@chevdoorが提案した策は有効だ。これで僕はGitHubプロジェクトのREADMEをAsciidocで書くことができる。良かった、よかった。
補足
この記事はInclude directive is not supported in Github-flavored Asciidoc ---- a workaround proposedを日本語になおしたものです。
僕はMacでだけ試した。Windowsではどうなんだろうか?bashもpandocもasciidoctorもWindows版がある。それらをWindowsマシンにインストールして適切に設定すれば問題なく動くだろうと思うが、試してはいない。どなたか、やってみて報告いただければありがたいです。