今日は12/25です。メリー・クリスマス!私の12月はもうしばらく続きます。手間をかけずにそこそこいい感じの図をblogへ埋め込むために、Jekyll+Re:VIEWの環境を拡張していきます。最初に単体のRe:VIEWでほどよくグラフ出力できるようにし、その後にJekyll+Re:VIEWへと組み込み、最終的にNetlifyで自動ビルドできるところまで持っていきます。Re:VIEWのgraph機能の基礎と出力調整blockdiagのインストールと基本的な使い方あらかじめpipからblockdiagをインストールするのが前提です。本家サイトにさまざまな導入方法が書かれているので、環境にあわせてインストールしましょう。日本語を含む図の描画には、事前のフォント設定が必要です。/mnt/c/Users/muo2/workspace/blog/test/HGRGE.TTC手元開発環境かつ手動で画像へのレンダリングを試す(Gitリポジトリに投入しない)範囲ではライセンス上問題なさそうな、HGゴシックを試しに指定しました。実際にはサーバ上での自由な利用のためにNotoを選ぶことになるでしょう。Re:VIEW記法にblockdiagで図を埋め込む場合は次のように記述します。利用したのはblockdiag公式サイトにあったサンプル図を軽く改変したものです。ch01.htmlというようにドキュメントを簡易ビルドすると、images/html/ディレクトリ以下にfoo1.pngが生成され、HTML内にimgタグも生成されます。出力フォーマットをPNGからSVGへ変更するblockdiagから出力したPNG画像は少々文字が潰れ気味です(図2)(図3)。Re:VIEW+blockdiaで生成した図、SVG版デフォルトのPNGよりは時代的にSVGのほうが良いでしょう。サイズが小さくきれいに仕上がるケースが多いはずです。それでは、出力フォーマットを変更すべく、早速Re:VIEWを改造していきましょう。lib/review/builder.rbを見ると、こういう感じです。endと書かれています。この部分を試しに無理やり'svg'へ書き換えてみると、想定通りblockdiagでSVGが生成されました。ライブラリ本体へ手を入れるのをreview-ext.rbで回避gemを書き換えてforkしたり、出力フォーマットを可変にするためのpull-requestを本家へ出すのは少々大掛かりすぎます。Re:VIEWでは、review-ext.rbというファイルを原稿と同じディレクトリへ配置するだけで、簡易的な拡張が可能です。これは6年前に通った道です。endendごく単純なコードで出力フォーマットの変更に成功しました。Jekyll+Re:VIEWへのインテグレーションまあまあ厄介です。すると、当初の実装のように一時ファイルを作成するようにしたほうが楽かもしれません。pluginの仕様上の都合でディレクトリ指定があれこれ厄介なので、このまま通るわけはないのですが、試しに変換してみましょう。/mnt/c/..../_site/images/html/2019-12-25-diagram1.png案の定エラーが出ました。JekyllプラグインとしてRe:VIEWコンパイルする際に図をビルドする例の作りかけJekyll-Re:VIEWプラグインに手を入れていきます。いっても、HTMLBuilderのimage_extを前述のとおり差し替えるだけで、_post/images/html/ディレクトリへSVGファイルを書き込むところまで通りました。本文中ではHTMLBuilderクラスのimage_extをお手軽書き換えする方向で通しましたが、さきほど確認したgraph_blockdiag関数を書き換えるパターンも検討しました。この関数の変換プロセスのなかで一時ディレクトリを適当に作成し、そこにファイルを書き出し、先日実装した画像コレクタでコピーしてDocumentRoot以下へ回収しつつ、辻褄の合うパスを呼び出し元へ返してやればよい、と考えて試作までしましたが、その後のビルド工程の整合性を保つのが想像より大変でした(book.imgdir自体を当該tmpdirに指定すればなんとかなりそうだが、本末転倒感がある)。ビルドした図(画像)を再配置するblockdiagで生成した画像の書き出し先はimages/html/以下ですが、img参照時にhtml/部分をパスへ含める意味はあまりありません。本文中で参照する画像とRe:VIEWから生成する図との間でファイル名の衝突を避ける効果はありますが、本文中で参照する画像の大半がJPEGかPNGであることを考えると、拡張子.svg自体が簡易的に名前空間として機能するため、ディレクトリ切り分けによって得られる追加効果は限定的です。前回書いたように、記事間で参照画像名が被った場合の対応は要検討状態のままなので、今回なにか対応してもすぐに変更する可能性が大です。このため、今のところはDocumentRoot以下のimages/ディレクトリへどかどかとファイルコピーする仕様としました。Jekyll+Re:VIEW+Netlifyでのビルドさて、ようやく最終段階です。Re:VIEWとJekyllからみて外部依存にあたるblockdiagをNetlifyのビルド環境へインストールする必要があります。懸念は日本語対応フォント、pipでのblockdiagインストールとパス解決です。pipでのパッケージ導入Netlifyの公式ドキュメントで書かれているとおりです。freezeの結果をrequirements.txtに記入しておくと、ビルド環境の準備段階でインストールしてくれて、もちろん結果イメージはキャッシュしてくれます。特殊かな?と思ったのは、Python本体のバージョンをruntime.txt(あまり計画性を感じないファイル名)に書いておくとそれを使ってくれるとあります。requirements.txtとruntime.txtを作成して実際にやってみます。3.7で通っていますね。ログを確認する限りでは、フォント不足はあれど変換処理までは走っているのでパス解決も問題なさそうです。2019-12-25-diagram1フォントをなんとかする実は、今回の構成でフォントのレンダリングは実施されません。PNGへの書き出し時には文字列の画像へのレンダリングが必要ですが、SVGの場合はタグ内に直接文字列が埋め込まれており利用者の手元でレンダリングするためです。blockdiagはフォント不在状態を想定していないように見えます。軽くソースを追いかけた感じだと、UnicodeEncodeErrorを投げている場所へ行き当たらなかったので、依存関係の少々深いところに起因しているように思います。いくらか試した結果、ここで読み込むフォントは必ずしも対象グリフを含む必要はありません。空っぽのTrueTypeフォントファイルを作成して食わせれば通ると思います。残念ながら、文字間計算をこの情報に依存しているようで、適当な軽量フォントを食わせたところ日本語がツメツメ表示になるという典型的なかっこ悪いパターンでした*1。やむなくNotoSansJP-Regular.otfをバンドルすることにします。blockdiagで利用するフォントの設定方法はいくつかあります。コマンドラインから-f(--font)オプションを渡す$HOME/.blockdiagrcファイルでfontpathを指定する本エントリの冒頭で軽く紹介したファイルfont-mapを作成して渡す若干微妙な感じですが、ここでは暫定的にRe:VIEWプラグイン内で$HOME/.blockdiagrcファイルを作成することにします。textcolor="grey"];}このような記述で・・・。無事、にこごりが我が家に来てくれました。muo-yamuo-yamuo@muo.jpmuojpmuo_jpいろんなメモ書き。