技術にゃんこの混ぜご飯

関東某所でITエンジニア生活を送るブログ主がチラ裏メモを放り込む場所

【個人開発】装丁と紙束をRe:VIEWで製本してくれる司書さんを作った

らっぱー(σ´Д`)σいぇぁ

カテゴリ:個人開発(librarian / Wrapper around Re:VIEW)
noranuko13/mpmm, TheUjulalaによるPixabayからの画像 (窓から様子を伺う白っぽい猫

librarian

Re:VIEW という書籍制作ツールのラッパーです。詳細は README.md に書かれている通りです。

他に書くことがなさそうです。次にいきます。

何故作ろうと思ったのですか?

静的サイトジェネレーター然りフレームワーク然り、テーマ・テンプレートなどの皮の部分と、記事・コンテンツなどの中身の部分と。役割ごとにディレクトリを分けて、できれば Git リポジトリを分けて管理したい訳です。便宜上、ここでは装丁と紙束と呼びます。

装丁=テーマです。書籍なんて大体似たような装丁です。シリーズものなら色を変える程度、ちょっとした仕様書やマニュアルを書くとしても、大枠を使いまわしたいと思うのは世の常でしょう。なので混在している状態は都合が悪い。何とかできないかと。

紙束=コンテンツの部分にしても、Git で管理することを考えると、テーマ側の変更履歴が交じるのは見辛いです。ドキュメントの変更履歴とテーマの変更履歴が、全然関係ないのに混じることになります。プレフィックスを付けてフィルターかければ見れないことはないでしょうが、脳のリソースを持ってかれるのは非効率的。

なので『分割管理したものを、かき集めてきてマージしてから製本する』ことにしました。

由来はなんですか?

司書さんは本の修繕をしたり、本の選定や管理を行うので、なんとなく雰囲気で。

bookbinder で製本屋という意味ですが、製本は bookbinding で使いますし。実際にやってることは編集者でも作家でもなく、出来合いのものに加工を加える程度のことですし。印刷所は printing office なので、また誤解を招きそうな単語になってしまう。

もしかしたら他の機能も生やすかもしれないと考えたとき、本に関する色々をしているのはやはり司書さんかなと。

今後の予定は?

とりあえず困ってないので現状維持。バージョンアップには追随していく予定ですが、タイミングは気付いたときです。

開発中のあれこれ

標準出力の実装とテスト

色付けは rainbow で行っています。類似のライブラリで colorize もありますが、こっちは GPL-2.0 license のようです。ライセンス面倒です。

標準出力のテストは Using the output_to_stdout matcher を参照しつつ書きました。

it 'output formatted string to standard output' do
  expected = "\e[33m[warning] subject\e[0m body\n"
  expect { termout.warning('subject', 'body') }.to output(expected).to_stdout
end

今更ですけど、色を付けるだけなら error ではなく danger にした方が良かったかもしれません。debug, info, success, warning, danger。Bootstrap でも似たような感じですし。まあ今更です。気が向いたら直します。

いざ実装を終えて自動テストも書いて、GitHub Actions で実行しようとしたら、色が付いていませんでした。\e[33m などが消えています。ちゃっかり Diff: には出力されてます。なんだこれは。

librarian(GitHub Actions / RSpec Error)
noranuko13/librarian

spec_helper.rb では color_mode = :on にしている筈なのに…よく見るとRSpecではなく中身の出力の方です。docker compose exec が原因か、いやローカル環境では問題ない。Tオプションを付けると再現する、何故だ。rubocop は --color を指定したら色が付いた、何故だ。

docker compose exec -T review rspec

検索しました、ええ、しましたとも。--color=always だとか、--ansi=always だとか、環境変数を渡すだとか、GitHub Actions の container で直に実行…重複定義嫌だなとか、愚直に CI にコンテナ内と同じ環境を構築…もっと面倒だなとか。それはもう色々頭を過りましたとも。

途中で力尽きてしまったので後の課題にして、一旦『CLICOLOR_FORCE=1』を付けることで解決しました。『CLICOLOR=1』だけでは駄目でした。でも後々テキストログを吐くときなどに面倒そうです。やはり多少機能過多でも何らかのライブラリを使用するべきか。

Bootstrap式色分けログは割と使うんですが、ピンポイントでライブラリがあるかというと、そうでもない?

LGPL-2.1 license

私は極力MITライセンスくらい緩いライセンスを使ってますが、メインのライブラリが LGPL-2.1 license なので今回は面倒臭さと戦ってみました。何か間違いがあったら申し訳もございません。

基本的に全公開でライセンスも継承しているので問題はないと思いますが、何かあればご一報ください。

いや、この辺毎度調べながら適用するんですけど。MITライセンスなら一瞬で終わるのに、一つでもキツいライブラリがあると時間食い虫ですね。業務用途だと使えないライセンスもありますからね…。プログラミング界のイラスト屋、ロゴで許諾内容の表示、違反があったら優しく警告してくれる、そんなシステムがあれば良いのに…。

クラス設計・モジュール

「お主、Rubyが書けないじゃろ?」と言われても仕方がないと自負しています。恐らく「僕・私ならモジュールを使うのに」という方がおられるのではないかと思います。

Commandパターン で書くことには決めて、でも何でもクラスメソッドにならなくもない状態になって、クラスは生成することにしてでも Process::Collect.new(@arguments).run てどうなん?と本人は思っています。数年後には黒歴史になっているかもしれません。

もう少し勉強して暇してたら劇的ビフォアフターしようかと。

RSpec のまともな使い方

まともに書いたのはこれが初めてかもしれません。いえ、業務で RSpec を使うことはありますが、少なからず立ち上げた開発者の癖やプロジェクトの大人の事情が絡んで、へそ曲がりコードが紛れ込みがちなんですが。

今回はきちんと公式の Examples を見て、命名規則や shared_context の切り分け方など、意識してできた方だと思うのですよ。

https://rspec.info/features/3-13/rspec-core

あと RSpec/MultipleExpectations が厳しすぎる。Webアプリだとほぼ解除してあって、更新した全部のカラムを確認する無法地帯になりがち。個人的には変更前・変更後で1回ずつ確認はしておきたいです。

もう少しまとめられそうなんですけどね。特にファイルの準備と存在確認の辺り。

気になっている箇所

そうそう、テストがあまりにもあれ過ぎるので、せめて各テストのベースになるディレクトリは、一時ディレクトリなど可変にするようにしたいですね。でないと並列実行がまず無理ですし、生成に結構時間かかりますから。

ちょっと気になっているのは Open3.popen2e のところ。使い方これで合ってる筈なんですが、Re:VIEW のログをリアルタイムに出力しながら実行する指定が地味に決まらず。何個か記事が見つかりはするんですけど、それが合っているかの担保が取れないというか。

def pwd(dir) も正直不要な気がしていて、1箇所でしか使っていないので Dir.chdir に任せて前後にログを挟めば良いのではと。

個人的に欲しい機能

config.yml の texdocumentclass, options は配列内のテキストがかなり長いので。別に設定ファイルを用意した上で、そこから文字列を組み立てて代入するようにすれば、かなりスッキリするとは考えています。ただ数々の他のWrapperライブラリを見てきているので、そこまですると逆に学習コストは高くなってしまうので考えもの。

CSSは利便性を考慮するならSCSSにしたいところ。

現在対応しているのが PDF だけですが、ゆくゆくはテキストでも出せるようにしておきたいです。主にコマンドや定型文のコピペ用。他はテスト次第でしょうか。

悠々自適な独り開発ですので、のんびりやります( ˘ω˘)