adiary-extendsを爆発的に改修している話

adiary置き換え計画は取りやめようと思ったでCMSの新製を取りやめ、adiary-extendsのアップデートをしたでその新製CMSからの機能バックポートを行ったことを書いたが、あれからさらなる機能バックポートを行っているため、現状やったことを書いていく。

現状行った機能改修

Lyndbaumからのバックポートしたものを含む様々な対応の話。

公開画面のテーマをLyndbaumの公開画面に合わせた

元々このブログではsatsuki2テーマを改造したlycoテーマを使っていたがレスポンシブデザインに対応していない問題があった。これはadiaryがそれを前提として作られておらず、PCかSPかをUAを見て振り分け、画面を出すシステムだったことや、表示処理の高速化のためにDOM構造を固定しJSで見た目をこねくり回す、良くも悪くもはてなダイアリーのような思想で作られていたことに起因する。

今回は一段階目でテーマのREADMEにResponsive: yesと書くと、UAによるスマホ表示の振り分けをしないように対応した。この機能はまだ試験導入中で、機能的に不足している個所が多々あるので、しばらく手入れしていく予定だ。

また画像ビューアをFancyboxからLythumb-viewerに置き換えることで、jQueryを廃止し、読み込み時のデータ量を削減している。他にもサイドバーやコメント欄のツリー開閉は従来JSで行っていたが、レイアウトシフトを起こす元凶だったため、<details>に変更し、HTMLとCSSで静的に切り替えるようにした。これによってレイアウトシフトとJSの削減を行っている。

他にもスクロール時に目次が追従する機能を今回作成したテーマ側に設けた。私は目次は追従してくれないと不便だと考えており、入れたかった機能の一つだ。この対応では逆にJSが増えているが、仕方がない。

今回の対応によりSPビューだけではなく、PCで画面を狭めたときにも画面が見やすくなり、個人的にはかなり利便性が上がった。何より2年半くらいあったこのサイトについてにある、「レスポンシブデザインにも対応予定ですが、現状は非対応です。」の説明を外すことが遂にできた。

旧画面 新画面

PCビューの新旧比較だとこんな感じ。SPビューはスクショが面倒なので省略。

公開画面と管理画面の分離

adiaryでは公開画面と管理画面を実質的に同じ画面として出すようになっているが、ここも実装上分離した。公開ページのテーマを変えると管理画面に波及したり、そもそも管理画面に公開画面の内容が混ざっていて使い勝手がよくなかった。現状は分離しただけなので画面は変わっていないが、将来的には管理画面らしいものに変えていきたい。

印刷用表示機能の削除

今回の対応で壊れてしまったので削除した機能。

元々はこんな感じで記事カラムの部分にフォーカスした表示がされていたが、Matomoを見ているとBOTが吸い込まれていくだけで使われていない機能だった。今時印刷する人もいない気がするので復活させるかは謎だが、恒久的に削除するかどうかも決めていない。気が向いたら復活させる可能性はある。

バックリンクの表示対応

記事について、別の記事からリンクされている場合に、そのリンクを参照元として表示する機能を足した。PukiwikiやMediaWikiなど、Wiki系のシステムではよくみられる機能だと思うが、ブログではなかなか見ない機能だと思う。

作りとしては記事にリンクを書いたり消したりするとバックリンクDBを書き換え、それを基にキャッシュHTMLを作り、ページが表示されたときにこのHTMLを画面に出しているだけだ。adiaryは画面のパーツをHTMLで持っておき、リクエストが来たときに繋げて表示する方式なのでこうしている。

YARPPのように毎回動的に生成しないため非常に高速に動作する。

対応しているのは今のところ記事のみで、ページには対応させていない。

記事更新時の衝突検知

Pukiwikiには同時に他の人が更新したときに更新の競合を検知し、それを表示する機能がある。これは誤って他人の更新を上書きするのを防止する機能だ。これを導入した。

私は以前から複数タブで同じ記事を開くことがよくあり、何ならスマホでも開いていることがあった。これによって更新内容を衝突させてしまうことがよくあったので、それが起きないように導入した。

仕組みとしては編集画面にハッシュを埋め込んでおき、このハッシュの差で判定している。衝突時にはいい感じに差分を出してくれるので便利だ。

ページにできない名前を、ページの名前に使えないようにした

adiaryでページを作ると基本的にページタイトルがURLになるが、仮に「pub/lycolia/rss.xml」と言うページを作るとhttps://example.com/pub/lycolia/rss.xmlというURLのページが出来てしまう。

こういったページができるとページではなく実際のファイルが表示されてしまう。これでは困るので、衝突するページを作れないようにバリデーションを追加した。

その他

  • ログインセッションの有効期限の初期値を180日から14日にし、パスワード変更時などにセッションを消すようにした
  • テキストDBのトランザクションの不具合を修正した。途中でエラーが起きると、その後の書き込みが消えることがあったため
  • 初期セットアップ用のindex.htmlを復活させた。nginxでうまく表示できる設定を作れたため
  • バージョン表記をadiary本家と同じx.yy方式にした。現在はv4.08。内部の処理が数字の大小に依存しており、これに対応するのが主な目的。桁の増減もなんか微妙かなと言うので固定長にしたのもある

この他にも細々とした対応をあれこれ。

あとがき

結構な変更を加えたが、コアの処理は変えていないため処理速度は1ms増えたくらいで体感では誤差の範疇である。

まだバックポートできていない機能も多くあるし、SEOやUX的にも不足の部分があり、管理画面もまだ途上だったり、既存テーマをどうするか問題、セキュリティ対応など、様々な課題があるので、ぼちぼち進めていきたいところだ。

と言うか本来書くべき記事も書かないといけないし、adiary以外にもやりたいことがあるので一日の時間が全く足りていない…。

ひとまずadiaryをベースにやっているためLyndbaumの時のように仕様漏れやパフォーマンスについて考慮することが少なく済み、またLyndbaum側で入れた機能についても基本はadiaryの構造に合わせてバックポートするだけなので実装コストが低いのが楽だ。

adiary-extendsのアップデートをした

普段はアップデートしても書いてないのだが、今回は前回の事情とかもあるのでちょっと書く。

adiary-extendsと言うのは今このサイトで使っているCMSで、adiaryをフォークして開発しているものだ。

やったこと

Markdownパーサーの改善

Lycolia/lyndbaumで実装したMarkdownパーサーからExtendsにないものを移植し、ついでに移植元でバグっていた部分を直した。主に直した不具合は次の通り。

  • 2 * 3 * 4や*.txt、日本語に挟まれた_が強調として扱われてしまう問題を修正
  • リンクの文字に角括弧を、URLに入れ子の括弧を書けるようにした
  • <M>のようなHTMLにないタグ名を、文字として表示するようにした
  • コードスパンの中の\が消える問題を修正
  • 番号付きリストが書いた番号から始まるようにし、リスト内の<p>の付き方や引用も直した
  • 表でコードスパン内の\|と、1列目の左寄せが効くようにした
  • 脚注で複数の段落と、同じ脚注を複数回参照する書き方に対応した
  • 画像や添付ファイルの代替テキスト・titleの扱いを整理した

またほかにも、新しいパーサーでは見出し構文のアンカーをPukiwikiの見出し構文に準ずるものに変更しており# hoge [#anchor_id]形式で生成するようにしている。これはアンカーIDを固定する記法で、見出し本文が変わってもアンカーを変えずに済むようにしている。アンカーIDがなければ自動付与、あれば付与しない、IDは手動指定も可能としている。過去記事については見出し本文をID指定することで、過去のアンカーリンクが壊れないように対応した。あわせて、段を飛ばした見出しが目次に出ない問題も直している。

Lycolia/lyndbaumについて先の記事でも言及しているが、これまでadiaryの代替CMSとして開発していたCMSだ。adiaryにある幅広い機能の網羅的再現が出来ず開発を中断したが、成果物はあり、本来adiaryに欲しい機能ではあったためバックポートを実施した。

かなり機能を入れているため、バックポートは今後もちまちまやっていく予定だ。Lyndbaumの開発のように五日で作りましたという勢いでLLM任せにやると何が何だか分からなくなるため、今回は理解可能な速度でレビューしながら進めてゆく。

バージョンを0.x系から4.x系に転換

adiaryにはデータマイグレーションの仕組みがあるのだが、これがバージョンの数字の大きさによって管理されていた。ざっくりいうと(前回マイグレーションしたバージョン - 新バージョン > 0)の条件が真であればマイグレーションを実施するもので、前回マイグレーションしたバージョンは管理画面で後退させることができ、マイグレーションをやり直す機能がある。

ここでバージョンが0.xだと都合が悪いため、3.x系である本家を追い抜いて4.x系をつけることで解決した。

マイグレーション管理用のバージョンと表に出すバージョンが分離しているため、別に0.x系のままでも成り立つのだが、本家では表のバージョンとマイグレーション管理用のバージョンは同期していたため、運用の都合で合わせることにした。そっちの方が解り易いし、綺麗だからだ。

あとがき

この記事とは直接関係ない話だが、フィードアグリゲーターのrururuがLyndbaumのフィードURLを拾っているようで少し困った。

実はLyndbaumは12時間ほど本番環境に上げて切り戻した経緯があり、その時にRSSについては302リダイレクトを入れていた。恐らくそれが起因となって書き換わっているのだと思う。

現在はadiary-extendsに切り戻しているためLyndbaumは使っていないのだが、動いていないRSSフィードやアイコンを参照されているのが悩みどころだ。

試しにadiary-extendsでも同様の302リダイレクトを掛けてみたが特に更新されなかった。恐らく手動で更新しているのかもしれない。以前、フィードURLが変わると宣言したのが影響している可能性を考えた。ひとまず管理者に連絡する術がないので、rururuの利用者で連絡が付きそうな人でかつ、rururuの運営者と関係がある人物に連絡してみたので、変わるといいなと思っている。

なおrururuくらいしかフィードの読み替えをしてなさそうに見えたため、Lyndbaum→adiary-extendsで生じたRSSフィードURL切り戻しに対する302リダイレクトは既に取りやめている。adiary-extends→Lyndbaumで302して、切り戻しでその逆をして、ややこしい二日間だった。

幾つかの変更は本家にもPRしているが、スパムみたいになってしまったので今後は考えようと思った。

adiaryのローカル開発環境をnginxで構築する方法

前に書いたローカルにadiaryの開発環境を作るがApache2前提だったので、そのnginx版。

常駐させると開発に支障がある*1ためFCGIモードではなく、普通のCGIとして動かす。

確認環境

Env Ver
adiary 3.52b
fcgiwrap 1.1.0
nginx 1.24.0

リポジトリのクローンと設置

/var/www/に展開すると仮定する。

git clone git@github.com:nabe-abk/adiary.git
cd adiary
cp adiary.conf.cgi.sample adiary.conf.cgi
sudo chown -R www-data:www-data .

設定例

IPv6でSSL化済の設定。fcgiwrapはデーモンとして動いているものとする。

server {
  listen [::]:443 ssl;
  server_name adiary.example.com;

  ssl_certificate     /path/to/fullchain.pem;
  ssl_certificate_key /path/to/privkey.pem;

  client_max_body_size 100M;

  root /var/www/adiary;

  # 実在するファイルはそのまま返し、なければ404
  location /pub/ { try_files $uri =404; }
  location /pub-dist/ { try_files $uri =404; }
  location /index.html { try_files $uri =404; }
  # favicon
  #  システム設定があればそちらを優先、なければデフォルト
  location = /favicon.ico { try_files /pub/lycolia/image/@system/sys-iconfile.png /pub-dist/default-icon.png =404; }
  # adiaryに飛ばす用
  #  /でCGI、/index.htmlでセットアップページに飛ばすための分岐を実現するために、こうしている
  location / {
    try_files $uri @adiary;
  }

  location @adiary {
    fastcgi_pass unix:/var/run/fcgiwrap.socket;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root/adiary.cgi;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_param HTTPS on;
    fastcgi_param SERVER_PORT 443;
    fastcgi_param ModRewrite 1;
    fastcgi_param Basepath   /;
  }
}

トラブルシュート

ログイン時にhttps://hogeに飛ばされる

上の設定にしたら行ける。公式の設定をコピペしても上手く行かない。

adiary置き換え計画は取りやめようと思った

adiary置き換え計画始動から着手した、adiaryに代わるCMS開発の続き。前回はadiary置き換え計画 進捗その3。

前回初版リリースまでに実装する予定の機能メモとして挙げたものは、大半を実装し終えた。果てしなく爆発的に実装した。取り敢えず運用のベースに乗せるだけのものは出来たくらいだ。しかしそこで一つの葛藤が生まれた。

生まれた葛藤

実装を進めるうちに「本当にこれでいいのか」という迷いが生まれてきた。そして、いったん立ち止まって考え直した方がいいのではないか、と思うようになった。

  • LLMに丸投げで作らせた、正しいかどうかも分からないまま何となく動いているだけの代物。それでいいのか?
  • パフォーマンスはadiaryに劣り、LLMに指摘して直させても、言われた通りにベンチを取ればかえって遅くなっている。それでいいのか?
  • なぜ動いているのか自分でも説明できない。それでいいのか?
  • そんなものがadiaryの後継を名乗るのは、さすがに無理があるのではないか?

そんな葛藤が湧いてきた。

正直なところ、LLMに色々やらせた結果、表面上は動いている。けれど、きちんと要件定義や設計をしていなかったこともあって、細かい部分はうまくいっていない。LLMはコンテキストが膨らむにつれて文句を言い出したり、明らかに誤った判断をし始めたりもする。長く使っていくものを作るにしては、あまりにも拙速な開発だったのではないかと感じている。

今回の変更点

とはいえ作るものは作ったのでそこだけ出していく。

メディアブラウザが実用レベルになった

今回一番手を入れたのがここで、記事に画像を貼るためのモーダルだったものが、ファイルマネージャーに近しいレベルになった。

大分それっぽい見た目だ。フォルダの作成やリネーム、削除にも対応した。

ファイル情報やどこに添付されているかも出せる。

複数選択してD&Dで移動させることもできる。Shiftキーを押しながら一括選択だって可能だ。

ダブルクリックでサムネイルビューワが立ち上がるところも再現したし、サムネイルビューワもFancyboxではなく、自作品にした。

画像以外のファイルのアップロードに対応

これまでは画像と動画しか上げられなかったが、mp3、txt、md、csv、tsv、json、zip、7z、pdfも上げられるようにした。

例えばテキストファイルをアップロードしてプレビューも出来るようになった。

記事中に[file:mp3:~~~~]と書けば<audio>で出力されるようにし、音楽も流せるようにした。

一方でHTMLやSVG、XMLなど、ブラウザがこのサイトのオリジンでスクリプトを動かせるとのことで、これらのアップロードは許容しないようにした。

またTIFFなどサムネイル生成時に任意のコマンドが実行される可能性があるものについてもアップロードさせない対応をした。

追従する目次の作成

Wiki.jsやGitHubにある追従する目次も作った。

うちは3カラムサイトというのもあり、やり方は少し悩んだが、GitHubとWiki.jsの間の子的なUIにして解決した。

執筆まわりの改修

これまではアイキャッチのモード選択と言う煩雑なものがあったが、今回の改修ではモード選択をなくし、WordPressのUIを採用した上で、アイキャッチにする画像選択についてはadiaryの自動選択アルゴリズムと、手動選択の二つを暗黙的に選択できるようにした。

手動で選択すればそれがアイキャッチとなり、それをしなければ最初の画像がアイキャッチとなり、画像がなければ既定の画像がアイキャッチとなる仕組みだ。

本番デプロイの準備

本番デプロイにあたり、必要なドキュメントの整理や、FCGI対応も行った。

さくらのレンタルサーバーでも動作し、家のサーバーでもFCGIとして高速に動作した。

しかしadiaryを超える速度にはならなかった。

その他の細かい変更

他にもこまごまとした対応をしたが、結局のところ虚無になってきた。

アクセス解析を入れられるようにしたり、カウンターを挿入できるブロックを追加できるようにしたりもした。

この記事も、既に使わなくなったことについて書いているので虚無である。

得られたこと

今回の開発は一旦中断することにしたが、セキュリティ周りの対策の知見や、FCGIの作り方など、幾つかの技術的な知識が手に入ったのは有益だったと思う。

また外部のフィードアグリゲーターから画像が直リンクされていることを把握できるなど、中々新しいことが分かった。そんくらいサーバーログ見てろよって話だが…w

あとがき

また今回のCMSは一旦お蔵入りさせるが、作ったものの一部はExtendsにバックポートし、必要に応じて本家にもPRを出しバグの改善が出来たらよいと思っている。

adiary自体の資産が大きすぎて全てを再発明するのは無理があるし、それをするくらいなら必要な部分を直した方が早い。

何故なら私が一番欲しかったものはレスポンシブデザインで、その次が理想のMarkdownパーサー、後はバックリンクくらいで、その他は既に実装してしまっている気がするからだ。

ひとまず作ったCMSであるLycolia/lyndbaumと、FancyboxもどきのLycolia/lythumb-viewerはこの記事で供養しておこうと思う。因みにサムネイルビューワについてはFancyboxに戻してある。理由は単純で、lythumb-viewerより拡張性があり、操作性もいいからだ。

何はともあれ今回の開発はいい勉強と経験になったので、今後に生かしていきたい。

あとこれは下心なのだが、adiary利用者のページからのアクセスが馬鹿にならないほどあり、これも新製CMSへの移行をためらった理由の一つである。

そしてExtendsの方はこれまで通りのんびり育てていこうと思う。

しかしこのネタだけでちょうど新着5件が埋まってしまったのは面白い。

Opus 5.5のトークン使用量はProプランで前週73%、今週24%に収めることができたので、単に作るだけであればProで足りた。もうちょっと、ちゃんと作る場合はやり取りが増えるので溢れたかもしれない。

adiary置き換え計画 進捗その3

adiary置き換え計画始動より着手した、adiaryに代わるCMSの開発について、adiary置き換え計画 進捗その2からの続き。

前回の記事から変わった部分

ログイン中に管理バーを出すようにした

adiaryやWordPressはログイン中に管理バーが出てくるが、それを実装した。

一々ダッシュボード開きたくないし、記事開いてる時はその場で編集画面に飛びたいためだ。

adiaryに乗り換えたときに放棄したWordPressのアーカイブをまだ残していたため、それを参考にUIを作った。中々イケてると思う。

なお当時のWordPressは既にあれこれ壊れており、ほぼ機能していない。

管理画面のリッチ化

流石に以前の管理画面は殺風景すぎたし、なんか使いづらかったのでWordPressリスペクトで作った。

表形式の画面は奇数行と偶数行で色分けしているし、記事編集画面もテキストエリアと背景色の色を差別化して見やすくした。アイキャッチや公開のセクションボックスも色を変えるとより良くなりそうだ。

他にも編集中に間違えて離脱しそうになったとき、確認のダイアログを出して誤った離脱を防げるようにもしている。そこを超えて万一離脱した場合もページそのものは単純なHTMLであるため閉じたタブを戻したり、ブラウザで戻る・進む操作で戻ってくれば基本的に状態は保持されている。

JSフロントでやろうとすると状態管理が偉いことになるが、ここはブラウザの機能に丸投げして楽をしている。因みにadiaryも同じ仕様である。

公開画面のセクション分けと、トップの全文表示対応と、その他諸々

背景が単色で各セクションの境目が見えなかったので、背景色と前景色を分けて見やすくした。

またトップページを抜粋表示から一覧表示に変更した。

他にも記事ページのスタイリングを調整し、現在のスタイリングに近いものにした。近いだけでそこまで似てない。

公開画面のレスポンシブデザイン対応

2024-02-01にCMSをWordPressからadiaryに乗り換えて以来、ずっと達成できていなかったレスポンシブデザインについに悲願の対応をした。

これで遂にこのサイトについてにある、「レスポンシブデザインにも対応予定ですが、現状は非対応です。」の説明を外すことができる。

バックリンク機能の追加

記事から被リンクを受けている記事は、そのリンク元を示せるようにした。これはPukiwikiにもある機能だ。

これでもう手作業で関連記事を書いたり、その更新のせいで無駄に更新日時がアップデートされることもなくなる…。

Fancyboxを廃止し、独自ライブラリに置き換え

FancyboxはjQueryで動いていて、jQueryで動いてるのがこいつだけなので排除したい思いが常々あったが、GPT-6.1 Solにドラフトを書かせ、Opus 5.5に仕上げさせることで形にした。

GPT-6.1 Solを使っていて思ったのは5ターンもすると最初の指示を忘れて暴走し始めることで、これはもう駄目だなと思った。コンテキストが長くなると、その場の指示すらまともに聞き入れてくれないので脱帽ものだった。

この独自ライブラリは既に今のadiaryで動いているブログにも取り込んでいて、fancyboxの排除はCMS移行をせずとも既に達成されている。

fancyboxにはURLにハッシュが付いた状態でページをスクロールしてモーダルを閉じるとハッシュの場所に戻る不具合があるが、これは新製ライブラリでは起きないようにしている。

初版リリースまでに実装する予定の機能メモ

  • 記事編集画面もテキストエリアと背景色の色を差別化して見やすくしたが、アイキャッチや公開のセクションボックスも同様に色を変えたい
  • テーブルの中身が折れてそうなので確認する
  • ページ作成
    • slugはデフォルトでタイトルにする
      • 手打ちした場合のみ変更可能にする
      • 更新時にタイトルが変わった場合も、そのタイトルをslugにする
  • メディアブラウザ
    • 複数選択して一括で記事に挿入
    • 選択しているものをD&Dで別のフォルダへ移動
      • 記事のアップデートまではしない予定
        • 記事を書いてそのあとにパスを考えるのはあり得ないオペレーションだと考えている
  • タグ
    • 選択しているものをD&Dで別の階層へ移動
      • これは記事側も更新される
  • インストールマニュアル
  • ハンバーガーメニューの追従
    • 今は追従しないのでスクロールすると消える
  • 目次の追従
  • favicon設定
    • 自動で各サイズのアイコンを作る
    • 既定はpub/assets/logoにある奴を使う
  • Ping通知
    • 管理画面からtextareaで宛先を行単位に登録可能
  • HTTP CLIENT
    • 基本的にHTTP通信はこいつを通す
      • 例外が必要な場合は検討する
    • UAにはソフトウェアバージョンやサイトドメインなどを含める
      • 例:Lyndbaum/0.1-beta5 (+https://blog.example.com)
  • 画像以外のアップロード
    • 現状テキストやHTMLとかはアップロードできない気がするため
      • 画像以外はサムネなしでファイル種別の分かるアイコン出せれば良さそう?
      • 初期では単純にファイルアイコンに拡張子書いたSVGでもいいかも
    • アップロード可能な拡張子は設定可能にする
  • 記事のフラグ機能
    • 任意のフラグを設定して記事の表示時に何かをする機能、例えばNSFWフラグを立ててブラーや検索エンジン向けのメタ通知をレンダリングできるとよい
  • 記法の管理
    • adiaryでは任意のSatsuki構文を追加できるが、新CMSではまだできない
    • WordPressのshortcodeは色々面倒なのでSatsuki構文で行きたい

あとがき

ここに書いていない事でも細々とした修正を重ねていて、既にCMSの新規作成と言うよりは、細かい詰めのフェーズに入っている感じだ。早ければ今月中、遅くとも年内には切り替えられるのではないかと考えている。

切り替えるとadiary利用者一覧に乗せられなくなるのが残念だが、その時点で利用者ではないため仕方がない。

また移行時にはRSSフィードのURLを変える予定なので、RSSを購読されている方々におかれては追々移行の対応をしていただけると幸いである。しばらくはリダイレクトをつける予定なので、すぐに読めなくなることはない。

そういえばLightboxで画像の拡大ができないのでFancyboxを導入していたのだが、Lightbox3が今年の8月に出ていたようで、なんと画像の拡大に対応していた。しかし画像に角丸が付いてたり、画像にUIがオーバーレイしまくりだったり、何とも言えない感じなので、採用は見送った。

かつて画像拡大モーダルの代名詞だったLightboxは、あの時のLightboxのままを記憶にとどめとこうと思った。