Hexoの記事とLemmyのコメント欄を連動させた。
例 https://earphones.juggler.jp/2021/Moondrop-SSP/
- blog記事に拡張タグをつけてclean-deployを2回行うと、自動的にLemmyサイトに投稿を作成する。
- blog記事の「コメントを投稿する」リンクからlemmyの投稿に飛んでコメントできる。
- コメントはblog記事に表示される。
おおむねHexo側のカスタマイズで実現している。Lemmy側は何も変更しておらずAPIを普通に呼びだしてるだけだ。
Lemmyにした理由
- マイクロブログと違い、後から投稿を編集できる。ブログからLemmy側へ自動転載した後、手動で記事を調節できる。
- リンクアグリゲータなので、URLでの記事検索がやりやすい。自動転載する前に既存記事を検索することで、重複ポストを防止できる。
- 近い将来にActivityPub対応予定がある。
1: 拡張タグの実装
記事データの最後に {% lemmyComment %}
を書いておく。記事ごとにタグを書くのは面倒くさいが、現状Hexoのサイト生成処理でasyncできるのは拡張タグだけだ。HTTPリクエストなどを行う必要上、他の手はない。
hexoの作業フォルダの下にscripts/lemmyCommentTag.js
を用意する。hexoは初期化時にそれを読むので拡張タグを実装できる。
拡張タグの登録。
hexo.extend.tag.register('lemmyComment', function(args){
const self = decycle(this);
for( const key of ["date", "updated", "raw","tags","content","categories","site"] ){
self[key]=`(${typeof self[key]})`;
}
if(verbose) console.log(`self=${ JSON.stringify(self, null, 2)}`)
return lemmyCommentImpl(self,args);
}, {async: true});
呼び出された関数のthis
オブジェクトに記事の情報が色々入っている。args
には拡張タグの引数が渡される。サイト設定 _config.yml
の内容は hexo.config
で参照できる。
async function lemmyCommentImpl()
の内容を大雑把に書くと:
- assets folder に lemmyComment.png があるか確認する。記事だと誤認識されないように拡張子をpngに偽装しているが、中身はjsonだ。
- json中に
postId
(lemmyサイトの投稿ID)がなければ検索したりログインして投稿したりしてpostId
を用意する。用意したら lemmyComment.png に保存しておく。 - 関数の返り値は拡張タグの展開結果のHTML断片で、今回は空のdiv要素と関数呼び出しを行うscript要素だ。
2: lemmyサイトからデータを取得するプロクシAPI
lemmy側を改造せずにオリジン間リソース共有(CORS)の制約を突破するため、単純な中継APIを用意する。
(A)ブログのサーバにnodejsで簡単なHTTPサーバを書く。 postIdを指定すると GET https://lemmy.juggler.jp/api/v2/post?id=xxx してその内容を返す。
(B)ブログのサーバのnginxを設定して /api/ へのアクセスを上記HTTPサーバに中継する。
3: ブラウザ側スクリプト
hexo のtheme/{themeName}/layout/_partial/head.ejs
の下の方に以下の内容を追記する。
<script src="/markdownToHtml.js"></script>
<script src="/hexo-comment-lemmy.js"></script>
<link rel="stylesheet" href="/hexo-comment-lemmy.css">
hexoのsourceフォルダに以下のファイルを追加する。
- source/hexo-comment-lemmy.css
- source/hexo-comment-lemmy.js
- source/markdownToHtml.js
markdownToHtml.js
は npmのmarkedモジュールをbrowserifyで適当にブラウザ用スクリプトに変換したもの。
hexo-comment-lemmy.css
はコメント表示部分のスタイルを適当に。
hexo-comment-lemmy.js
に定義した関数は拡張タグの変換結果から呼び出される。
(2)で用意したプロクシAPIを非同期に呼び出して、応答に含まれるコメントデータをDIV要素に追加する。
4: 動作状況
まだちゃんと動作確認していない。
5: その他
もし自動投稿が不要なら拡張タグは必要ない。記事のfront matterにlemmyPostIdを定義して、theme中のejsでそれを見てDOM要素を追加すれば済む。