先日書いたMeatPieDayで電子書籍を書きたい、というのを、実際にやってみる事にする。 とりあえず名前はMpdEbookとしておこう。

方針

一章一Markdownファイルを用意するまではMeatPieDayと適当なアプリやスクリプトでやる。 ここまではほぼ決定で良い。

生成するファイルももうpdfは要らないかな、という気がする。 epubかmobiで良いだろう。Google Play Booksがまぁまぁなのでepubだけで良いか、という気もしている。

最初はRe:VIEWのMarkdownを生成しようかと思ったが、改めてInsideBinderで書いたreファイルを見直すと、 Markdownが詳細すぎてそこまで指定したくないなぁ、という気がした。 もっとjekyll程度でやりたいなぁ。

途中の段階ではwebでも見たいので、jekyllのサイトも生成するようにしよう。 だからなるべくjekyllのMarkdownと似た物にしておきたい。

jekyllからepub生成するのも2つほどあるようで調べたがそんなにアクティブにメンテされてる感じでも無い。 しかも、環境作って試してみないと良く分からない事が多い。

試しにjekyll-ebookというのを試してみたら、UTF8だとYAMLのloadに失敗する。 少しいじってUTF8にしたら今度はヘッダ部分抜き出す正規表現がマッチしなくなる。

良く分からないなぁ、と結局一行ごとに読むように直したら、BOMではまったりいろいろあったが、 最終的にはpandocが無い、とか言われる。 pandocは別途インストールする必要があるのか。

うーん、あんまりこのマシンにそういうの入れたくないなぁ。

GCP上にdocker用意して作業するか。かったるいが、どうせtravis化する時に要るだろうし。

jekyll-ebookは小さいスクリプトなので、この位ならgolangになおしてしまうのが一番早いかも。

でもめんどくさいなぁ。俺は章ごとのmdを用意するだけ以外の事はやりたくないんだよなぁ。

先に書き始める方が良い

書き始めるまでに必要な事が多すぎてやる気が失せる。 多分順番を間違えているな。

書き始めるのに必要最低限な物は、ipynbをgithubにputする物だけのはずだ。 最終的にこのipynbから生成するのは決定しているのだから、 ここは最初に作って書き始めても無駄にならない。

次に必要なのはjekyllを生成する物なんじゃないか。 これは普段書いているブログと必要な技術要素は同じなので、やれば出来る。 そして、途中経過を確認していく事を考えればどちらにせよjekyllは生成するだろう。

この2つを揃えてある程度書いてみて、 良い内容が書けたらepub化を考えれば良い。

始めるまでにやらなきゃいけない事が多すぎて、いざ始めてみてやっぱりいまいちだから辞める、では目も当てられない。 まず書いてみて良い物になりそうか確認するのが先だよな。

という事でまずipynbをポストするアプリを書こう。

Mpd2Github

ipynbファイルのSendToを受け取り、レポジトリにgithub APIでputする。

仕様としては、最初のセルにレポジトリのurlとかファイル名とかタイトルとかを書いておく事にして、このipynbをファイル名以外はそのままの状態でgithubにポストする。

画像とかはbase64で埋め込まれるので、 それを取り出して画像ファイルにしたりするのはCI側でやる。

書いてるファイルをgithubに置ければとりあえず間違ってデータ消す心配とかはなくなるので、本を書いていける。

置く場所はMeatPieDayブランチにしよう。フォルダは掘らないでいいだろう。

手元にURLConnectionを使ったほとんど同じ事をするコードがあるのだが、 これはやっつけでなるべくサイズ小さい物を作ろうとした結果なので、 コードは酷い。

似たようなコードは良く必要になるので、今回はちょっと真面目に作っておこう。 HTTPとしては、kotlinっぽい物を使ってみよう、という事で今回はFuelを使う事にする。 OAuthは自分でやる。

fuel-androidも最初は加えていたが、コードをちらっと見たら、RxJava使うと要らないな。 この辺何が必要か良く分からないので、各ライブラリごとに何を提供するか主要な物のリストくらい作っておいてくれよ…

ただfuel-rxjavaはいいね。これだよこれ、って感じのAPIだ。 kotlin時代のhttpとしては、以後はfuelで行こうかな、という気になる。

Kotlinは文字列処理とかレシピ集が欲しいなぁ、と思うのだが、Kotlin Cookbookでググったら中身が単なる言語解説っぽくて違う、そうじゃない、と思ってそっ閉じ。 誰か書いて。

なお今回書いたコード

val yamlMap = content.lines()
    .map { it.split(":") }
    .filter { it.size == 2 }
     .map { Pair(it[0].trim(' '), it[1].trim(' ')) } 
     .toMap()

この辺書いているとkotlin楽しくて良いね。

そのあとgithub APIのPUTがjsonしか受け付けないのにpost parameterで渡してハマる、 という半年前と同じ罠にはまったりもしたが、無事動いた。 レポジトリは以下。

Mpd2Github

最初のセルに、

name 説明
GithubUrl レポジトリのurl
FileName レポジトリにポストするファイルの名前

をコロン区切りで書いておくと、GithubUrlで指定されたレポジトリのMeatPieDayブランチにipynbファイルを置く。 このメタデータにタイトルとかも埋め込もうかなぁ、と思っている。

とりあえず以下のレポジトリにipynbを貯めていく予定。

https://github.com/karino2/MLProbability

このレポジトリのMeatPieDayブランチに更新があったらCIが走ってjekyllサイトとepubを生成する、というのを最終的には書きたいが、まずはipynbを書き溜めます。

mpd2md

内容の確認の為も含めて、jekyllのサイトをCIで生成するようにした。 まずipynbからjekyllのMarkdownを生成する、mpd2mdというのをgoで書いてtravis CIとつなげる。

golangはjsonの扱いはいまいち融通が効かない所があるが、 久しぶりに使って書き方を忘れてもC言語のようになら書ける、 というのは良さの一つに思う。 とりあえずC言語のように書いておくと段々と思い出してくるので、 タスクを片付けつつリハビリが出来る。

これでMeatPieDayで書いたメモがそのままwebサイトになるようになったぜ。

このmpd2mdはそのうち少しいじってpandocのMarkdownも生成出来るようにしたい。 ただそれはもうちょっと内容が増えてからでいいかなぁ。

pandocによるpdf生成

何も考えずにpandocにjekyllのMarkdownを渡してepubを生成した所、数式が表示されない。 画像に変換するのが良さそうだが、自力でやらないといけなさそう。

でもPDFに変換したら数式も綺麗に読めたので、当面はpdfでいいか、という事に。 最近はepubで読みたいなぁ、という思いも強いので、いつかは画像に差し替える、というコードを書きたいが、そちらは本が完成してからで良かろう。

pandocにはMarkdownを渡す訳だが、その順番はどこかには書いておく必要がある。 とりあえずは一番簡単に、contents.txtというファイルにmdの名前一覧を書いておいて、それをpandocに渡すようした。

最初は変換用のgoスクリプトを書く気だったが、pandoc叩くだけのコードになったので、レポジトリの中に入れておく程度にする。

Dockerfileと合わせて、MeatPieDayブランチに置く事にした。