aozora2htmlのご紹介

この記事は[青空文庫 Advent Calendar 2017](https://qiita.com/advent-calendar/2017/aozora)の２日目のエントリになります。

さて、aozora2htmlというRubyGemsがあります。

* https://rubygems.org/gems/aozora2html
* https://github.com/aozorahack/aozora2html

今日はこのツールの紹介を書きます。

## aozora2htmlとは

aozora2htmlは、青空文庫フォーマットのテキストをHTMLに変換するツールです。

もともと、青空文庫にはt2hs.rbというスクリプトがあります。これはtxt2htmlツールというものに同梱されています。

* http://kumihan.aozora.gr.jp/slabid-14.htm

このスクリプトをベースにして、Gemにして拡張を加えたものがaozora2htmlになります。

## txt2htmlとその課題

txt2htmlは、注記記法ごとにクラスが用意されていたりするなど、比較的凝った作りになっていました。しかしながら、

* gemになっていないのでインストールが煩雑
* あらゆるクラスが1ファイルのみに突っ込まれていて見通しが悪い
* Shift_JISで書かれている
* 単体のツールとして作られているため、「マークアップの変換ライブラリ」としては使いづらい
* Ruby 1.9の頃に書かれたもので、2.xの現在では更新したいところがある

などの課題があり、今後もずっと使われることを考えると、継続して更新できるように整理したくなってきます。

とはいえ、当初はtxt2htmlの開発がどうなっているのかがよくわからなかったため、lib/t2hs.rbには最低限の修正を行うだけで、極力周辺に追加する形で開発を進めていました。しかし、後日青空文庫の方に話をうかがったところでは、text2htmlの方は公開されている版が最新版で、その後は誰もいじっていないとのことでした。そのため、現在ではlib/t2hs.rbをがんがん変更しています。

aozora2htmlは、以下の特徴を持つようになっています。

* gemになっているので、最近のRubyが使える環境では`gem install aozora2html`でインストールできる
* ファイル構造はおおむね今風の構造になっている
* txt2htmlからコマンドラインオプションがいくつか追加されている


## aozora2htmlの使い方

### インストール

aozora2htmlはRubyのバージョン2.0以上が対象です(一応1.9.3でも動くはずです)。前述の通り、Rubyがインストールされていれば、以下のコマンドでインストールできます。

```shell
gem install aozora2html
```

### 使い方

t2hs.rbと同様、「入力ファイル（青空文庫形式テキストファイル）」と「出力ファイル（HTML）」を与えると、出力ファイルのファイル名でHTMLファイルが作られます。

sample.txtをsample.htmlに変換したいときは以下のように入力します。

```shell
aozora2html sample.txt sample.html
```

また、t2hs.rbとは異なり、引数が1個のみでも実行できます。その場合、変換結果のHTMLは標準出力に(Shift_JISで)出力されます。

```shell
aozora2html sample.txt
```

さらに、引数としてURLを指定することもできます。URLを与えた場合、そのURLからファイルを取得してから変換します。

そしてさらに、テキストファイルではなく、zipファイルを指定することもできます。これは、青空文庫のサイトでは、青空文庫形式のファイルはzipで圧縮した形で配布しているためです。なお変換のロジックとしては、zipを展開して最初に見つかった*.txtファイルが青空文庫形式のファイルであると見なすようになっています。

これを使うと、例えば不意にラブクラフトの[『ダゴン』](http://www.aozora.gr.jp/cards/001699/card57443.html)を手元で読みたい！と思ったときでも、HTML版のページを開いて保存する代わりに、

```shell
aozora2html http://www.aozora.gr.jp/cards/001699/files/57443_txt_58143.zip dagon.html
```

とすれば、dagon.htmlというファイルで変換結果を保存することができるわけです。便利ですね。

#### 外字に関するオプション

他にもオプションがあります。

青空文庫形式のテキストファイルはShift_JISでエンコーディングされていますが、実際にはJIS(JIS X 0208)に含まれていない文字（ここではこれを「外字」と呼ぶことにします）も使われています。これの外字は、青空文庫のWebサイトでは画像として表示されています。

例えば、[中島敦『山月記』](http://www.aozora.gr.jp/cards/000119/card623.html)では、「虢略」の「虢」、「袁傪」の「袁」、また「愈〻」の「〻」といった文字が使われています。これらの文字はJIS X 0213で追加された文字のため、JIS X 0208では表現できません。そのため、 http://www.aozora.gr.jp/cards/000119/files/623_18353.html では、これらは画像で表現されています。

これに対して、

```shell
aozora2html --use-jisx0213 http://www.aozora.gr.jp/cards/000119/files/623_ruby_18352.zip sangetsuki.html
```

と実行すると、sangetsuki.htmlは画像を使わず「虢略」「愈〻」「袁傪」はテキストとして表示されます。HTMLファイルとしては、`&#x8662;略`, `愈&#x303B;`, `袁&#x50AA;`となっているのはソースを確認するとわかります。

同様に、JIS X 0213にはないけれどUnicodeにはある文字を変換するには、`--use-jisx0213` に加えて `--use-unicode` オプションを追加すると、画像を使わずにすむことができます。

その他にもオプションがあるので、興味のある方は`--help`オプションを実行してみて下さい。……と書きつつ、実際に確認してみたら`--help`も`--version`も表示されなかった……あとで直さないと。

## aozora2htmlの今後

最初にあげた課題のうち、現状でもまだ解決できていない大きな点として「Shift_JISで書かれている」があります。

aozora2htmlでは、[lib/t2hs.rb](https://github.com/aozorahack/aozora2html/blob/master/lib/t2hs.rb)以外はShift_JISで頑張って書いているものの、このファイルだけはどうにもShift_JISを脱却できていません。というのも、青空文庫形式自体が日本語でマークアップされていることと、その解析のために正規表現で頑張っていることにより、Unicodeで置き換えるのが大変面倒なのです。

「青空文庫形式自体が日本語でマークアップされている」というのは、要するに`○○［＃「○○」に傍点］`とか、`吹喋［＃「喋」に「ママ」の注記］`とか`［＃ここから３字下げ］`といった文字列をマークアップとしてparseしないといけないわけです。もうちょっと賢いやり方があるのでは……という気持ちもあるのですが、どこかであきらめがついたらひたすら`encode("shift_jis")`を駆使して対応することにするかもしれません。

この辺りが解決されたら、1.0をリリースしたいと思っています。

いずれにしても、よろしければ実際に使ってみて、フィードバック等いただければありがたいです。気になることがあれば https://github.com/aozorahack/aozora2html/issues に書き込んでいただければ幸いです。どうぞよろしくお願いいたします。