Chienomi

Chienomi リニューアル!

開発::web

悲願達成

ついにきましたリニューアル。

ChienomiをPureBuilder Simplyベースにしたいということは、PureBuilder Simplyを開発した2017年からずっと言っていて、ようやく達成した形である。

Chienomiが難しかったのは、もともとWordPressで運用していて、記事が古いものはPureDocで書かれていたりするため、PureBuilder Simplyにそのまま組み込めないこと、 そして手で打ち直すにはあまりにも量が多いことなどが理由で、WordPressからの移行を考えなければならなかった。

加えて、Chienomiの場合、アクセスが非常に多く、下手に止めることができない。

そこで最後に残ってしまったのがChienomiで、結局様々なコンポーネントの開発、PureBuilder Simplyの改良などを経てついに公開に至った。

公開の大きなきっかけとなったのはchienomi.orgドメインが取得できたことであり、これがなければまだしばらくはWordPressのままだったと思う。

WordPressからのインポート

WordPressからの記事以降をどのようにするかは難題であった。

ソースがそのまま使えるのが理想だが、残念ながらChienomiの記事ソースはplain text, PureDoc, POD, RDoc, PureDoc Zと結構様々なフォーマットで書かれている。

しばらくの間有力視していたのは、Pandocを使ってHTMLからMarkdownに変換することだが、これをするとかなり汚いMarkdownが出来上がる。

結局のところ、WordPressで書いた記事はそもそもPureBuilder Simplyでできるようなドキュメント管理機能がないことを踏まえて、「HTMLで抜き出してビルドデータにmergeする」という手段を選択した。

ポイントとなるのはディレクトリ構造である。

パーマリンク機能を使わない場合、WordPress記事のリンクは/?p=nnnという感じになるが、パーマリンク機能を使うと一般的には/archives以下にリンクされる。 PureBuilder Simplyは静的HTMLファイルとして配置するものであるため、このリンクに従ってHTMLファイルを配置すれば単純なリダイレクトで記事が失われない。 マップを書くよりもだいぶ建設的だ。

画像に関しても基本的に/wp-content/uploads以下にあり、これはファイルとしてそのままコピーすれば良い。

問題は、静的HTMLにビルドするとなると、PureBuilder Simplyの生成機構が使えないことである。 PureBuilder Simplyは生成過程でPandocのテンプレートエンジンを使用しており、PureBuilder SimplyのサイトはPandocテンプレートを使用する前提となっている。

そこでインポーターには「Pandocテンプレートを使って既に生成したHTMLファイルをテンプレートとする」という方法をとった。 ごく単純に、特定文字列を置き換えることで、特定文字列を含める形のMarkdownドキュメントを用意すれば簡単にPureBuilder Simplyと共存する形で変換できる。

WordPressの記事はWordPressの機能を使ってXML形式にエクスポートできる。 これはRSSのような形式だが、RSSではない。

当初REXMLライブラリでなんとかしようとしていたのりだが、いまひとつうまくいかなかったので、結局ActiveRecordを使用した。 あとは値を文字列置き換えではめ込んでいくだけである。

極めてシンプルなアプローチだが、非常に強力で実用的なプログラムが完成した。 それがGitLabで公開中のこちらだ

その後、TOCの変換にも対応するように手を加えたが、結局はこれのためにコード量が倍になってしまった。 HTMLのTOCは飛ばしたりすることがあるため、なかなか難しい。もっと上手い考え方はないのだろうか。

検索機能

Chienomiは記事数が多く、特定のテクノロジーなど検索対象が明確なので、検索機能はなくてはならない。 Mimir YokohamaのときはGoogleに逃げてしまったが、最近のGoogleはサイト内検索ですらまともに機能しないので、自前で実装する必要があった。

インポート機能が作業を決めてから仕様が大きく変わったのに対して、検索機能のほうは「事前にplain textなファイルを生成しておき、grepする」という方針がきていた。

実は一時期RroongaやNamazuを使う方法も検討したのだが、結局自分が望む振る舞いではないということが分かって断念した。 やっぱりgrepである。

基本的にはgrepを使いたかったのだが、問題は「Chienomi的にはand検索が欲しい」ということだ。 grepで任意個数のand検索をするスクリプトは書きにくいし、重いし、遅い。

そこで、Rubyで直接実装することにした。ちょっとしたこととしてはcase insensitiveにする工夫が入っていたりする。

考え方としては2つに分かれている。

ひとつはインデックスを作るものだ。 plain text化するのだが、これをどうしようか随分悩んだ割に結局はシンプルに、「タイトルと本文エレメントを正規表現で抜き出し、ここからタグをすべて除去したテキストファイルを作る」という感じになっている。 grep同様、「一致した前後のテキストを取得する」という機能を使えるように空行を除去する機能も持たせてある。

このとき必要な要素は

  • タイトル
  • 記事のアドレス
  • 検索対象の本文

の3つ。これをどう含めるかが問題になっていたのだけど、

  • タイトルを「一行目」とする
  • アドレスは、元ファイルと同じヒエラルキーで持たせる
  • 設定ファイルに元ファイルとインデックスファイルの起点を「絶対パスで」書かせる

という方法でクリアした。 このあたりは細かい小技が多い。また、この決定には、「RubyのDir#.glob**/が使える」という点が大きい。

また、検索対象に含めてほしくないものはどうするか、という点については、検索対象をグロブで明示する、という形にした。 PureBuilder Simplyは綺麗なヒエラルキーを組みやすいので、この点にも利した。

ここまでくれば検索は、

words.any? {|i| doc.include?(i) }

AND検索なら

words.all? {|i| doc.include?(i) }

で良いことは明らかである。

ただ、実際にはそこまで単純にはなっていない。もう少し汎用性をもたせる必要があるためだ。 特に、「前後の行を含める」ためのコードが長め。

検索ワードの解釈はShellwordsライブラリを使用しており、ダブルクォートで囲むことができる仕様。 AND検索とOR検索の組み合わせは、Chienomiの規模では必要性に乏しいためサポートしなかった。

サイト固有の事情をすべて飲み込むことは到底できないので、コアライブラリとして提供し、それを利用したウェブアプリケーションを作ってね、という形になっている。 公式にもサンプルとなるCGIがあり、これは動作確認済みなのだが、本体が56行なのに対し、CGIが46行とあまり文量は変わらない。 ちなみに、このサンプルCGIでもPureBuilder Simplyとの整合性のため、WPimporterと同じような方法をとっている。

こちらもGitLabで公開中

AND検索3ワード、Chienomi全記事対象、記事要約ありで出力含め手元計測では0.18秒ほどだった。 これは相当速い。「遅いかもしれない」と覚悟していただけにびっくりした。

デザイン

Chienomiのデザインは従来、見た感じスタイリッシュだが、あまりよくはなかった。

WordPressテーマとして、もうしばらく更新されていない、というのもあるが、アクセシビリティが低いし、重い。また、画像の表示などに割と難がある。 また、Chienomiにとっては非常に重要なコード部分の表示が美しくない。

こうした問題を踏まえて最適化されたのが新しいChienomiのデザインである。

私の中のトレンドは、「サイドカラムすらない、究極にアクセシブルでリーダービューのようなデザイン」なのだが、Chienomiはナビゲーション要素が非常に多いためサイドカラムを採用している。 当初は「タブ切り替えで項目を表示できるように」とがんばっていたのだが、どうしてもDilloが意図したものを表示してくれなかったので、諦めてセレクトボックスで飛べるようにした。

このあたりは、Chienomiが「読み物として長いタイプのものは少なく、基本的に明確で簡潔な情報である記事が多い」ということを踏まえてのもので、私のサイトでは唯一本文フォントがサンセリフである。

コードが読みやすいよう、またChienomiを読みながらコードを書いたりしやすいように「なりで全幅を使う」仕様で、表示に手を加えている要素は非常に少ない。 当然ながらChienomiのユーザーはリテラシーが高い傾向にあるので、それぞれお好みの設定でうまく対処する可能性が高く、それを阻害することはしないようにしている。 ただ、monospaceフォントだけは、リテラシーが高くないユーザー、あるいは「monospaceフォントなんて指定しないよ」って人のためにある程度指定してある。 Firefoxではmonospaceフォントの設定は裏メニューだしね。

本当はもっともっとスタイリッシュなデザインのサイトを作りたいところではあるんだけど、Memorandaと比べてもデザイン要素は控えめで、また多分ボロクソ言われるんだろうなぁ、と思うとちょっと気が滅入る。 とはいえ、Chienomiの場合実用性優先なので、そこはぐっとこらえることにする。

ちなみに、Chienomiは初代〜3代目ではオレンジがテーマカラーだった。先代である4代目だけがモノトーンで、落ち着いたイメージになったという話もあった。 この5代目Chienomiも基本的にはモノトーンだけど、実はちょいちょいオレンジ要素が入れてあったりもする。わかりやすいところではサイトロゴ。

Twitterでシェア

SNSボタンはTwitterだけになった。

主な理由は、みんなアプリから共有するでしょ? ということなのだけど、Twitterを残したのは、Twitterはシェアボタンを使うとメンションにすることができるからだ。

このTwitterボタンを実装するために、PureBuilder Simply 1.6が開発された。

これまでずっと入れたかったいくつかの機能が追加されているが、従来は難しかった「URIエンコードされた文字列」を扱うためにシステム側でメタデータに含めるようになっている。 このため、テンプレート内に動的なリンクを書きやすくなった。

Twitterシェアが公式ウィジットでないのは、公式ウィジットはJavaScriptで動作し、アクセシビリティが悪いだけでなく、訪問者をトラッカー被害に晒すことになるからである。

コメント機能

コメント機能は、近いうちにつけるとは思うのでお待ちくださいな。

ConoHa WINGはそのままCGIが使える仕様なので、コメント機能くらいならとても簡単に書ける。 モデレーションなしだとPureBuilder Simplyとの組み合わせはちょっとトリックを使わないといけないのだけど、 モデレーションありなのでそのあたりは気にしない。

失われた機能

新着通知機能はWordPress.comの機能(JetPackの機能)なので、なくなった。 メールマガジンを運用するというのも微妙なので、結局この機能は廃止の方向。Mimir YokohamaのページではAtomフィードを配信しているが、フィードもロストテクノロジーになりつつあるらしいので、Chienomiではサポートしていない。

SlimStatを使ったアクセス解析機能は非常によかったが、これも廃止である。 新しいChienomiはConoHa WINGでホスティングされており、サーバーログが見えないためアクセス解析に関してはかなり後退した。 もちろん、静的HTMLであるPureBuilder Simplyサイトではアプリケーションで解析するようなこともない。 トラッカーを埋め込む気は(Google Analysticsであっても)ない。

JetPackで行っていたTwitterへの自動投稿機能もなくなった。 この手の機能は、そもそもアプリケーションによって処理しているわけではないことからPureBuilder Simplyとはあまり相性がよくない。hookのタイミングがズレるからだ。

なお、予約投稿に関してはat(1)でgit pullすればいいだけなので、別に難しいことではない。

改善

とにかく速くなったし、記事がちゃんと管理できるようになったし、更新が楽になった。

Chienomiは更新頻度が高いのでWordPressの更新が重いのはとてもしんどかった。

そして、ページロードが2MB近かった(これでもWordPressとしては平均的なサイズ)Chienomiの問題点が改善された。このページにおける転送量は今のところ21kBほどである。 これでモバイル容量を気にしながらChienomiを見る必要がなくなったし、例え速度制限を受けたとしても問題なく見ることができるだろう。

そして、デザインはダサくなったが、一方で非常に読みやすくなったはずだ。 柔軟性が上がり、印刷もしやすくなった。印刷プレビューで開いてもらうとわかるが、画面表示とは全く違う形式となり、かなり印刷物として読みやすいはずだ。 色も、グレースケールで印刷することを想定して印刷で出しやすいようにしている。 また、印刷版はセリフ体だ。

一時はPDF配信もしていたChienomiだが、もはやその必要もなく、そのまま印刷できるように調整してある。 Chienomiは、「印刷してじっくり読みたい」という要望が結構あるので、それは重要な点だ。 細かいところでは画像の途中で切るようなことはしないように調整もしてある。

Chienomiは「使える」サイトを目指しているので、これからはきっとより良い体験を提供できることだろう。