adiary extends v4.17アップデート

adiary置き換え計画始動から連なる、adiary-extendsにLyndbaumの機能を多数バックポートしたり、機能の削除祭りを敢行したの続き。

Claudeのトークン消費量が激しすぎて上限を超えそうだったため、契約をProからMax x5に切り替えたくらい爆発的に開発を続けている。土曜の夕方に切り替えて既に16%使っているためProだと80%使ったことになる。到底次の土曜までは持たない計算だ。

今回はv4.15からv4.17への0.2バージョン分上げた。結果は追加4,956行、削除2,391行で削除の倍以上追加が起きている。今回はUXの改善やバグ潰しを中心に行っている。

主なUX改善

地味なものから大きなものまでいろいろ。ここに挙げていない細かな改善もたくさんしている。

ヘルプアイコンの廃止

adiaryにはヘルプアイコンと言うマウスオーバーでヘルプが見れる仕組みがあったが、これを辞めた。

理由として出たまま消えないことがあり、消えないと凄い邪魔だったからだ。他にも一々見ないといけないので、見るのが面倒と言うのがあった。

とはいえ、説明文は必要なので常時表示にすることにした。これはWordPressの実装方式から着想を得ている。ついでに進次郎構文化しているヘルプを削除したり、具体性がないヘルプの記述を見直すなども行った。今までまともに見たことがなかったから、意外な発見も多くあった。

変更前のコメント欄のヘルプ、ヘルプボタンにマウスオーバーしないと注意書きが見えない変更後のコメント欄のヘルプ、注意書きが標準で表示されていて解り易い

特にコメント欄についてはこのヘルプを読む人がいったいどれほどいるのか?と考えていたため、大きな改善になったと思っている。但しヒートマップの収集はしていないので効果は不明だ。

記事のソーシャルボタンに汎用の共有ボタンを追加

前回ソーシャルボタンの最新化を行い、ボタンデザインを最新化したり、サ終していたPocketを消したりしたがMastodonなどのFediverseにシェアできない問題があった。

そこでどうするか考えた。まずFediverseに限ればFediverse用のシェアボタンサービスがあるのがあるのでそれを使うことを考えたが、Fediverseはシェアする先を設定しないといけないためどう考えても手間だった。そこで思いついたのが汎用的なシェアボタンだ。

ひとまず参考になる実装を探そうと思ったが、こういう時に限って中々思い浮かばなかった。そんな時に助けになったのがこぶりーを運営されているsilverbirderさんのブログ、ジブンノートだった。

確認するとWindows EdgeとAndroid Edgeではブラウザ標準の共有機能が起動するようだったので、この方式にすることにした。

結果として右にボタンが一つ増え、ブラウザ標準の共有機能が立ち上がるようになった。

添付動画とYoutubeのポップアップ再生

これまで本ブログでは動画やYoutubeはHTMLに埋め込んで表示していた。そのため動画やYoutubeは主の文章に対して従にせざるを得ずサイズを大きくできない問題があった。また動画を直に入れているためHTMLのロードが遅くなるのもネックだった。動画は個人的に正直気にならなかったがYoutubeが凄く重かった。PageSpeed Insightsでも動画があると激烈にスコアが落ちていた。

そこでlythumb-viewerを改修して画像の拡大同様に動画とYoutubeをポップアップ(モーダル)で出せるようにした。ページには動画やiframeを出さず静止画を出し、クリックするとモーダルがポップアップされて動画やiframeが出てくるためページのロード負荷が低くなり、またモーダルで開くため大サイズの動画が開けるようになった。ついでにadiaryの組み込みだとフルウィンドウボタンが押せなかったのが押せるようになっている。画像と同じ仕組みなのでスライドショーにも出てくる。

動画のサムネイルをどうするかは悩んだが、アップロード時にブラウザ側で生成することにした。最初はサーバーサイドでffmpegを叩くことを考えていたが、この方式だとレンタルサーバーで動かせないうえに、コマンドを叩くので任意コマンドが実行されるリスクがある。ブラウザ内で完結させることができれば、そのリスクを避けられるため、ブラウザでサムネイルを作り、それを画像として動画とともにアップロードするようにした。

過去の動画についてもブログに過去の動画のサムネイルを作る機能を実装し、過去の動画をすべてブラウザに読ませサムネイルを生成してサムネイルをアップロードさせる処理を入れたので、手間なく対応できた。動画の埋め込み自体は[file:mp4:posts/2026/09/:20260822_093123812.mp4]のような記法で埋め込んでいるため、単純に記法から生成するHTMLを書き換えるだけで対応している。Youtubeも[youtube:PRUQ2XtJqDo]と言う感じで専用の構文がある。

参考までに以下に動画とYoutubeの実際の表示を置いている。動画はまだ表に出してない下書き記事から引っ張って来てるので未公開分である()

NSFW記事・NSFWサイト表示に対応

これは今回最大の変更と言っても過言ではない内容だ。これはLyndbaumにも乗せようとしていた機能だが、当時はOpus 5.5に却下されて辞めていた。しかし今回は鋼の意思で実装しきった。

昨今は創作の見方だと思っていたpixivですら厳しい態度をとっているということで、セルフホストで分散可能なCMSと言うのは非常に重要な立場にあると考えている。私自身もpixivで飽きるほど警告を受けてうんざりしているので、自主公開するのにもこの機能が必要だった。

これまで数件のエロゲ関係の記事をあげているのに、その全てが全年齢とか、明らかに健全な目的で利用していない技術を健全に見せかける記事を書いたりだとか、だいぶ無理があったので、その辺りを見直す切っ掛けには充分なり得ると考えている。

内容としてはブログ全体をNSFW指定して、サイト表示時に年齢確認を求める機能と、それとは別に記事単位にNSFW指定し、記事単体に年齢確認を求める機能、そして年齢確認を記憶して毎回出さない機能、その記憶の解除、検索エンジンへのレーティング通知機能、RSSフィードでの本文削除機能を実装している。

実際の画面としては以下のような感じ。

サイト表示に年齢確認が表示され、一度押すと以降は出てこない。SPAではないため毎回出してると面倒だからだ。セッションCookieに持たせるのも手だとは思うが、管理が面倒なのでlocalStorageに放り込んでいる。

設定の解除は設定画面を設けるのもあれなので記事のナビゲーションUIの辺りに置いている。

記事をNSFWにする場合は投稿画面でチェックを入れると設定でき、記事単位のNSFW設定が可能になる。記事単位の場合は今後確認しない場合のチェックボックスをつけている。これは一時的に見たい場合があると思うからだ。

記事別の場合も設定解除ボタンは用意してあり、これは記事の頭の方に出している。

またレーティング用のメタタグは以下を設定しているが、サイト全体の場合は常時、記事だけの場合はその記事だけ出るようにしている。

<meta name="rating" content="adult">

管理者が公開ページにいるときに画面上部に管理バーを追加

こういう画面上部のバーを追加した。同様の機能はLyndbaumにも実装していたが、アンカーリンクを踏むとバーとアンカーの頭がバーにオーバーラップしてしまい、一行目あたりが読めない問題があった。今回の実装ではそうならないようフローティングUIにせず、画面上部にバーを差し込み、そこから下をバーより下げる実装にすることでアンカーを踏んだ時にバーに記事本文が重ならないように調整している。

以前の版にも似た機能はあったのだが、ヘッダーロゴの一行上に出てレイアウト的に良くなかったのと、スクロール時に追従しない問題があり、今回の形にした。

今回の形はアイコンがあり、見た目的にもメリハリがあるので気に入っている。

ログインリンクも元々は二行になっていたが、これを一行にした(下記)

こちらが改修後で、一行に収めることでタイトルロゴが下にズレて不格好になるのを解決している。また収まらない場合ログインリンク側をカラム落ちさせることにしている。どう考えてもタイトル側が落ちるのはおかしい。サイト自身の存在を示すタイトルこそが主でログインリンクなんて管理人の便利要素は従属要素である。

なおログインリンクをなくすというのは選択しなかった。不便なので。

またLyndbaumではWordPrssに合わせて要素を左に寄せていたが、マウスを左に持っていくのが面倒なので右寄せにした。adiary本家も右寄せである。

但し管理画面は左寄せ気味にしている。これはナビバーを左に置いてる関係で目線が左に行くためだ。公開ページと比べた場合に位置が異なっているが画面の目的が異なるため意図的にこうしている。

記事ページにコメントと参照元に飛ぶためのナビを追加

私のサイトはサイドバーが長く、記事も長いことが多いが、大抵の場合記事はサイドバーより短いため、Endキーなどでページ最下部に移動してもあるのはコメント欄や参照元ではなく、単なる空白である。

これが不便なので一発で移動するためのリンクを足した。単にページ内アンカーに飛ぶだけである。

ハンバーガーメニューのスクロール追従

Lyndbaumではハンバーガーメニューの追従は方式が定まらず実装できていなかったが、今回 extends v4.16で実装した。

ページ最上部ではハンバーガーメニューはフローティングしているスクロールするとハンバーガメニューが追従する目次より下にスクロールするとハンバーガーメニューの下に目次が追従してくるスクロール追従する目次を開いたところ

ページ最上部・スクロール追従・目次スタック・目次開放の一連の流れはこんな感じだ。

管理画面の設定を常時開放

以前は設定にアクセスするには一度設定を開く操作が必要だったが、面倒だし何があるか分からないので常に開くようにした。そもそも下ががら空きなのでこれで良い。

脚注・注釈記法で内容をポップアップで表示するように

これまで脚注や注釈を見るにはマウスホバーしてブラウザ標準のツールチップを見るか、クリックして下の方にある原文を見る必要があった。スマホではツールチップが見れないため原文まで移動し、読んだらバックリンクを使って元の位置に戻る必要があり、大変な手間だった。しかもツールチップには文字装飾が付かないためハイパーリンクがあっても無意味だった。

そこでWikipediaのようにマウスホバーしたときに小さなポップアップを出すようにし、そこに表示するようにした。このポップアップは文字装飾が載せられるほか、マウスを載せて選択したりクリックすることができるため、心置きなくハイパーリンクを設置することも出来るようになり、大変利便性が良くなった。

本サイトでは脚注を多用していたため、その効果は絶大だと言える。注釈はバグがあったため、ほとんど使っていなかったが、後述するように今回対応したので、今後は使っていくと思う。

公開ページに使われていたjQueryの根絶

jQueryに依存していた360度写真プラグイン・時計・Cookieメモが動作することを人間である私が確認したので公開ページ側のJavaScript系の整備の大半は終了した。残りは管理画面側に重厚なのがいるので、こいつらを倒せば終わり。

もうAI任せでほとんどコードを読まないとはいえ、CJSやESMに慣れている私にとってjQueryは読むのしんどいので消え去ってほしい思いがある。

バグ潰し

テーマデザイナでモジュールウィンドウにアイコンがないボタンがある問題を解消

これはadiary 3.52bの画面だが、テーマデザイナで画像の通りボタンにアイコンが出ていないものがあった。押せばわかるので別にいいが、もしアイコンのないボタンが複数あると解らなくなる。

という訳で今回アイコンを設けることにした。2018年にインストール*1したっきりほとんど起動した記憶のなかったGraphicsGaleを立ち上げてドット絵を作成して実装した。

GraphicsGaleは無料のドット絵エディタで投下色も扱える優秀なツールだ。ドット絵と言うとEDGEが有名だと思うが、透過を扱えるEDGE2はシェアウェアで、最新版のEdge3 *2も有料ソフトになっている。

GraphicsGaleではこのように定番のサイズに応じたグリッドを表示することができ、adiaryのアイコンに利用されているようなチップセットを作るのに非常に重宝する。因みにこの機能が存在することは知らなかったが、あるだろうと思ったらあった。クリスタを起動して不便さにうなだれていたが、すぐにGraphicsGaleへ切り替えた。

そんなこんなで80x32のチップセットのキャンバスを96x32に拡大し、横に伸ばした16x32pxの上半分を新規アイコンブロックとして描いていくことにした。

こんな感じでドット絵を打っていき、人間の力、息吹を込めながら新しいアイコンを描いていた。

この画像だと拡大したエリアと元のエリアで下地の色が異なるが、最終的にはちゃんと揃えて直している。

そして無事アイコンが完成したので組み込んだ。アイコンはPNGのチップセットで作られており、それを2色に落としたうえでDataURI形式にしてCSSに埋め込むという実装だったため、Opus 5.5に変換ツールを書いてもらって作成したPNGをコードに落として実装した。

画像アップロード時に同名ファイルがあるときにリネームして保存しているのに上書きしていた

adiaryでは同名ファイルがる場合確か上書きしていたと思うのだが、これが嫌で私は同名ファイルがある場合、ファイル名にタイムスタンプを生やして別名で保存するように実装していた。

しかしこの処理にはバグがあり、元ファイルを上書きした上で、別名のファイルを生成するという間抜けな実装になっていた。恐らくadiaryのファイルハンドリング処理を余り理解できないまま実装していたからだろう。

今回の修正では元ファイルをきちんと残し、衝突するファイルは別名で保存されるようにした。また同名で中身が同じっぽい場合はアップロード自体しないようにしているが、このときにエラーになるのか、暗黙的に既にあるファイルが本文に挿入されるのかまではLLMが書いたコードを見ていないため、確認していない。そのうちしようと思うが、まぁ実運用で支障があればその時にやるだろう、きっと。

Satsuki記法の注釈記法(())で、注釈の一覧が出ない問題と、Markdownモードで一行に複数の注釈を書くと**で強調が成立し、強調に化けてしまう問題、記事を更新するたびに注釈番号がインクリメントされていた問題を直した

注釈の一覧が出ない問題と、Markdownモードで一行に複数の注釈を書くと注釈記号のアスタリスクが連なり、強調構文が成立し、強調に化けてしまう問題は本家にもある不具合で、インクリメントされるのは恐らくextendsだけにあった不具合。

これを直して注釈構文がまともに機能するようになった。またLLMの言い分を眺めていた感じだとSatsuki構文からパージしてMarkdown構文として取り込んだような気がしていたが、コミット差分を見る限り双方に跨っているようだ。差分的に元からこういう実装だったと思われる。本家も確認したがそうっぽく、Satsuki記法とMarkdown記法は不可分の関係にあるようだ。

自分のユーザー名を変更しようとするとエラーで変更できない問題を修正した

本家でも起きるかは確認していないが、少なくともextendsでは起きていたバグ。理論上は本家にもあると思う。

内容としては公開ページなどに表示するアカウントのユーザー名(アカウント名)を変更できない問題があった。どうやら関数を呼ぶときに必要なパラメーター(ID)を渡しておらず、誰の情報を変更するか特定できないために起きていたようだ。単にパラメーターを追加するだけで治った。

プライベートモードにしても、閲覧できない人に記事、コメント、タグが見えていた問題と、ファイルパスの秘匿化が解除されていた問題を修正

extends 4.09で発生したらしいバグ。恐らく4.10でマルチサイト対応を削除したときにセキュリティ系の実装に穴が開いてしまい発生したものと思われる。

後者については秘匿化の必要がないと判断したが、URLを一度秘匿化していた方が意義があると思い、削除した実装を戻した。これは以前のURLを知っている人がファイルを見続けることができるため。adiaryのプライベートモードはファイルパスをランダムな英数のパスに変更することで保護するだけなので、物理的にはアクセスできてしまう。

当然記事そのものには認証を前提としたロックが掛かっているが、マルチサイトを解除したときに認証周りが壊れたものとみられる。一旦この機能が動作することは確認している。機能していなかったことは確認していない。

検索した語の強調が動いていなかった問題を修正

Fancyboxを入れたときに関数を消し飛ばしていたらしいのを戻した。

クリップボードから貼り付けた画像がposts/ではなくadiary/にアップロードされていたのを修正

ディレクトリ構造を変更したときにクリップボードからのアップロード処理が追従できていなかった。理由は共通アップロード関数を使わずに自前実装していたため漏れていた。

このクリップボードからのファイルアップロード処理こそがadiary-extendsを生み出した発端で、ここから独自機能を発展させてゆくことになった。

*1 : 端末は代替わりしており、単にexeをストレージに突っ込んでいるだけなのでインストールと呼べるかどうかは怪しい

*2 : AIパワーなのか随分リッチになってしまって…

改善系

存在しない記事が参照されたときに200を返す問題の修正

/99のように0で始まらない数字だけのURLで、記事が無くても200を返していた問題を修正。404を返すようにした。

ブログの基本設定でブログ名や紹介を変えたときに、RSSを作り直すようにした

ブログの再構築からブログを再構築すれば反映されたが、普通に設定変更時に反映されて欲しかったのでそうした。

画面・操作・権限の回帰テストを追加した

中身見てないので実効性のほどは不明だが、Opus 5.5が書いたので6割くらいはまともだと信じている。

ぶつかったら人間が再誘導するためのガードレール替わりなので困ったらそん時に直せばいい精神。

関連PR

v4.16 / v4.17

あとがき

先週時点でClaude Proの使用量が上限ギリギリだったためMax x5にアップグレードしたが、既に16%も使っておりProなら80%換算なので物凄い勢いで実装を進められていると思う。果てしない勢いを感じる。

v4.16は極めて膨大な機能追加・変更・削除を伴っており、正直全部は把握できていない。まぁ何かあればその時に対応すればよいのではないかと言う勢いになっている。それよりも開発速度に理がありすぎるし、実際問題大体動いており、たまにバグが出る程度だからである。

残件は後述のリストくらいなので、この辺りが片付けば概ねFix出来ると考えている。普通に使う分には現状でも不満はほとんどない。10/19のLyndbaum開発切り上げから、僅か7日という短期間でよくやったと思う。

なお実装にはLLMをガンガン使っているが、本記事は100%人間の手書きである。

実装残件

取り敢えずこれがやれたら追われるよねリスト。増やさないようにしたい。

  • コメントの折り畳みをやめる
  • 記事編集画面の詳細設定の奴をチェックボックスから折り畳みUIに変える
  • 記事・ページをそれぞれ記事一覧、ページ一覧とする
  • 記事一覧のリンクを編集リンクにする
  • コンテンツと言う名前をページに名寄せする
  • dynatree(jquery.dynatree)を置き換える
  • 編集画面の画像の挿入の既定値を設定できるようにする
  • 画像アルバム
    • デフォルトで日付降順にしたい
      • 縦長や横長の画像のサムネイルがクリック、視認しづらい
  • 設定ファイルの設定値の幾つかを管理画面に移す
    • 同時ログインセッションとかあんな所にあっても気づかない!!!
  • デザインテンプレートのクラス名を変える。hatena〜とあるが全部普通の名前に変えたい
  • 既存テーマのレスポンシブ移行
    • 著作者の意に沿わない可能性が多分にあるので、移行でなくバリエーションを増やすだけくらいがいいかもしれない
  • 記法のマニュアルなど、ユーザーガイドを作る
  • adiary本家にある記法説明だけは最低限内部のHTMLで持っておくと良い気がする、外部サイトに飛ぶのも変な話なので

adiary-extendsにLyndbaumの機能を多数バックポートしたり、機能の削除祭りを敢行した

adiary置き換え計画始動から連なる、adiary-extendsを爆発的に改修している話の続き。

adiary置き換え計画は取りやめようと思ったで開発を取りやめた新製CMSLyndbaumだが、実装した機能そのものは便利なものだったためadiary-extendsに機能のバックポートを行っており、同時にLyndbaumに寄せるための機能削除も行っている。

バージョンは前回の記事を書いた時点ではv4.08だったが、あれから0.7上がり、現在はv4.15になっている。この間の変更を合計すると約5,800行の追加に対して約14,500行の削除で、バックポートより機能削除の方が多いかもしれない。

取り敢えず大まかなことを以下に挙げていく。細々としたことまでは書いてられないのでそこは省略するが、参考程度にPRのリンクもつけておく。

削除した機能

マルチサイト機能の削除

元々レンタルブログを運用するために開発された機能に見えるが個人的に使っていない事や、保守が大変なことがあり消すことにした。

マルチサイトはWordPressにもある機能だが運用が面倒であり、正直個人的には要らないと考えている。欲しいサイトの数分個別に置いた方が楽だと思う。

Dockerなどでのシングルテナント運営が流行りの今の風潮で考えるならなおのことそうだろう。バラバラにしていた方がカスタマイズなどもしやすいし、権限管理やセキュリティ回りなどでも利点があると考えている。

この対応によりRSSフィードのURLがLyndbaumの時と同じになっている。このため以前のRSS切り戻し問題が再燃しそうである。extends→Lyndbaumの変更でRSSのURLが変わり、Lyndbaum→extendsの切り戻しで戻り、今回はextendsの改修によってRSSのURLがLyndbaumの頃に戻ったとかいう…w

リダイレクトは入れてあるが購読者の方などにおかれては反復横飛びの様になってしまい恐れ入る…。

サブドメイン機能の削除

adiaryにはサブドメインモードと言う機能があり、マルチサイトを運営するときに各サイトをサブドメインに割り振れる機能だったと記憶しているが、マルチサイト機能を消したので道連れになった。

と言うのは建前で、過去にサブドメインモードを試したときにまともに使えなかった記憶があり、バグが眠っていると考えていたので消したという方が正しく、マルチサイト機能の削除はこの機能を消すことが目的の一つになっていた。何が問題だったかは記憶が残っていないので定かではない。

公開画像アルバムと全ページ一覧の削除

本質的に管理機能であるため、管理機能側に寄せた。

全ページ一覧を舐めてみたい人もいない気がするし、アルバムもUIが管理機能感満載で、一般ユーザーが見れて嬉しいと思えなかったため。

スマートフォン向け画像アルバムの削除

レスポンシブ対応にしたため、UAを見てPC/SPに分岐し、スマートフォン向けのアルバムを表示する機能を削除した。

前に作ったOGP選択機能の削除

adiaryを爆発的に改造したで開発した機能だが、画像が増えると微妙なのと、記事外の画像を選ぶのが面倒なのと、サムネイルが拡大できないなど色々面倒だったので、削除して作り直した。

死んだか使い勝手が悪くなったサービスとの連携を削除

  • Twitter通知プラグイン
    • Twitter APIは庶民が使えるものではなくなったため
  • OAuth機能
    • Twitterでしか使ってなかったため
  • Twitterウィジェット
    • Twitterにログインしているユーザーしか見れないため
  • Facebook関連のシェアボタン以外の機能
    • APIキーの必須化が随分前にあり、面倒なため
  • Pocketのシェアボタン
    • サービス終了
  • sitemapのping
    • ping先が既に死んでいた
  • Google Analyticsのユニバーサルアナリティクス
    • 数年前に滅んでGA4に移行したため
  • AMP
    • 最近見ないし多分数年前くらいに滅んでる
  • はてな系の記法
    • はてブとスター以外サービス終了していたため、これ以外は全部消した
  • ASIN記法
    • [asin:…]と書くとアフィリンクが貼れる機能だったが、商品名を手設定する必要があるなど自分でリンク張った方が楽で、存在意義が不明だったため削除
  • name記法
    • 「~たん」や「~たんハァハァ」みたいな出力を作れる記法だった
    • ネタだと思ったので消した
    • ついでに言うと表示に必要なファイルが存在せず、まともに動いてなかった
  • adiary v1, v2に関連するあらゆる実装
    • 互換記法、マイグレーション処理などを全て消した
    • 20年以上前のCMSからextendsに移行してくる人はいないと思うため
  • reStructuredText記法とSphinx連携
    • GitHubの.rstが書けるやつ
    • 観測範囲で使用者がいないのでサポートから落とした(知らない機能なので保守したくない)
  • URLのサムネイルを外部で作る記法
    • レンタルサーバーの容量が50M以下だった時代ならいざ知らず、今の世の中で外部サムネイルが必要なケースがあるとは思えなかったため
    • 今は無料サーバーでも10GBくらいはあるのでサムネイルで溢れることは早々ないだろう
    • さくらのレンサバならライトプランですら100GBある
  • WebPush
    • ニュースサイトとかで通知求められたとき基本拒否すると思うしEdgeはデフォルト拒否だしAdblock入れたら蹴られるものだと思うので消した
  • その他、およそ使わないであろう記法を独自判断でバッサリ消した

変えたこと

スパム対策

ベースはLyndbaumから持ってきているがadiaryの機能を生かすために一部は独自機能にしたもの。

curlのような単純なHTTPクライアントからコメントを投げられないように細工したり、ハニーポットを加えるなどしてBOT対策を強化した。adiaryは元々独自のスパム対策があるため、それに上乗せした形。

その他、IPアドレス指定による投稿禁止やNGワード、日本語を含むかどうかや連投防止など様々なチェックを追加。

管理人を名乗るコメントも出来ないように、管理人っぽい名前を入れてコメントするとエラーになるようにしたほか、管理人は管理人であることが表示で分かるようにした。従来からCSSにクラスはあったが、普通の人はそんなところ見ないので「管理人」と出るようにした(以前から一応文字の見た目は変えていた)

またコメントにリンクを貼られた場合もSEO的に評価されないように属性を付与するようにした。

ImageMagickのセキュリティ対策

LyndbaumではGDを採用したがImageMagickに対して機能面で劣るためextendsではセキュリティ対策をしたうえで、ImageMagickを継続することにした。

ImageMagickに渡す前にファイルヘッダから中身の形式を確かめ、JPEG、PNG、APNG、GIF、WebP、AVIFだけを読み込むようにした。これによってImageMagickが脆弱性を突かれ、任意のコマンドを発行できる可能性を減らした。

同時にアップロード可能拡張子の初期値からTIFFとICOを外した。これはTIFFは脆弱性を仕込みやすいと言われているため。ICOについてはLLMのアドバイスで外した。

Markdownパーサーの改修

Lyndbaumのパーサーをベースに、adiaryのパーサーをマージしていい感じにした。

CommonMarkやGFMには準拠しておらず、それっぽい方言にしている。

例えば改行は<br />、二連続改行は段落<p />としたり、見出し構文は# hogeと書くと# hoge [#l7a712f2]のように変換する。HTMLに出るときには[#l7a712f2]をアンカーリンクとして出すようにしている。これはPukiwikiと同じ仕様で、見出しを変えてもアンカーが変わらないようにしている。Pukiwiki同様アンカーID部分は好きな文字列を指定できるが、既定ではランダムな文字列である。

シェアボタンの最新化

全て最新化し、TwitterとFacebookは件数が取れなくなっていたので件数欄を消した。

変更前 変更後

HTTPクライアントのUAをサーバー管理者に優しくなるように変更

これもLyndbaumに乗っていた機能である。

adiary extends v4.15 (https://blog.lycolia.info)みたいなUAを吐くようにした。

Mastodonとかがこのタイプで、ログを見たときに出自が解り易い(いやまぁ詐称は容易にできるが…

adiaryには元からUAを設定する機能があったため、実装が楽だったのがありがたい。

360度写真の記法を追加

[image:360:…]と画像記法を書くことで360度写真用ビューアプラグインを使えるようにした。これまではファイル名で判定されており、無関係なファイルが巻き添えになっていた。

公開フォルダをpub/に集約

これもLyndbaumの思想を持ち込んだやつ。

公開フォルダは元々4つあり、ページ名と衝突していたほか、管理が煩雑だったためpub/に集約した。

これによりjs/、pub-dist/、theme/がpub/配下に移動した。

base.cssの容量削減

以前公開画面と管理画面を実装上分離したが、CSSはそのままだったため、CSSも分離した。これによって公開ページ向けのbase.cssは47.5KBから38.6KBに容量を削減できた。

管理画面のレイアウト変更

例によってWordPressっぽくしている。Lyndbaumをベースに作っているが結構変えているので、そんなに似ていない。

画像アルバム・タグ・ページツリー(コンテンツツリー)については元のUIが便利なので、ほぼそのまま残している。

タグ入力のインクリメンタルサーチも以前extendsに組み込んだものをそのまま残している。

PageSpeed Insightsのスコア改善

  • 記事に挿入した画像にwidth, heightを付与するように
  • RSSのバナーにもwidth, heightを付与
  • 動画・音声記法で出る動画へpreloadを付与
  • Prism.jsにdefer追加
  • nginxの設定サンプルを追加し、静的資材にキャッシュヘッダを生やす設定サンプルを追加

RSSのフォーマットをRSS 2.0の仕様に準拠するようにした

Lyndbaum開発時のadiary置き換え計画 進捗その2でやったことをそのままバックポートしただけ。

記事の編集で、保存していない変更があるまま離れるときに確認するようにした(誤操作による離脱防止)

Lyndbaum開発時のadiary置き換え計画 進捗その3でやったことをそのままバックポートしただけ。

関連PR

v4.09 / v4.10 / v4.11 / v4.12 / v4.13 / v4.14 / v4.15

あとがき

Lyndbaumから相当量の機能をバックポートしたので、だいぶ使い勝手がよくなり、機能的にもLyndbaumっぽくなってきた。そのうち名前をLyndbaumにしてもいいかもしれない。

作っていて思ったのは0から同じものを作るより、既にあるものを改造した方が遥かに楽で心配事もなく、運用にも問題が生じなかったことだ。

コアについてはほぼ触っていないので、恐らく実行時間は誤差の範疇でしか変わっていないと思う。adiary-extendsを爆発的に改修している話で1ms増えた気がしていたが、計測回数が少ないので誤差だったかもしれない。この辺りのベンチマークも落ち着いた頃に取っていきたい。

なおここまでの開発で破壊的変更をがっつり入れているが、adiary Version 3.52devからExtends Version 4.15まで移行するためのマイグレーション処理は組み込んでいるため、adiaryを使っている人であれば移行することができる。但し記法などを一部切り捨てているため、それらを使っている場合は支障が出ることもあるとは思う。

また今回変更になったパスについてはリダイレクトをかけているため、基本的に支障になることはないと思われるものの、世のRSSリーダーがどれほどリダイレクトによるURLの自動変更に対応しているか不明なため、先行きは不明である…。

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年半くらいあったこのサイトについてにある、「レスポンシブデザインにも対応予定ですが、現状は非対応です。」の説明を外すことが遂にできた。恐らくこれによってadiaryサイトの中で見た目が最もモダンなサイトになったと思う。何故ならadiaryはレスポンスデザインに対応しておらず、対応させるのが大変だからだ。HTMLを書き換えれば済むとかそんな次元の話ではなく、テンプレートエンジンとその周囲のエコシステムそのものに手入れをしないといけない。

旧画面 新画面

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置き換え計画は取りやめようと思った

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で足りた。もうちょっと、ちゃんと作る場合はやり取りが増えるので溢れたかもしれない。