自作 Hexo タグ作成のトリック

以前のブログは WordPress のプラグインによる拡張タグや HTML タグの直打ちで作っているページが多く、 Hexo でそれを同じように実現するには自作の Tag プラグインを作成する必要がありました。
複雑なものではなかったので、作成に慣れてしまえば問題無く量産できてしまえますが、最初はわからないことが多かったので忘備録として残します。

タグ内でサイト設定などを利用する

この問題はとても簡単なように思えますが、実際は一工夫を必要とします。デフォルトである “landscape” テーマには fancybox タグが最初から入っていますが、この書き方ではできないことが結構多くあります。

1
2
3
4
hexo.extend.tag.register('fancybox', function (args) {
// 省略
// this !== hexo
});

実際のサイト設定情報は hexo.extend.?? と使われている hexo オブジェクトに格納されているので、これを取得すればよいのですが、一時的に別の変数に代入しておくだけでは上手くいかないので、 Hexo 本体の codeblock タグなどで使用されている方法を参考に利用してみます。

1
2
3
4
5
6
7
8
9
10
function fuga(ctx) {
return function(args) {
// 省略
// ctx === hexo
const html = ctx.render.renderSync({text: args.join(' '), engine: 'markdown'});
const isDark = ctx.config.foo.bar.dark
};
}

hexo.extend.tag.register('hoge', fuga(hexo));

このような関数を返す関数を定義することで、 hexo オブジェクトをキャプチャして、それを経由してアクセスします。

{%???%}hoge{%end???%} で囲むような “block” タグにする

hexo.extend.tag.register にタグ名と関数だけを渡すの場合、 Hexo は自動的にインライン(?)のタグとして認識します。

1
2
hexo.extend.tag.register('fancybox', function (args) {/*略*/});
// {% fancybox /image.png Foo Bar %}

プロックタグにしたい場合、関数渡しの次の引数に、 {ends: true} を渡します。加えて、渡す関数が受け取る引数も、タグで囲まれたものを示す content というものが増えます。

1
2
3
4
hexo.extend.tag.register('blockquote', function (args, content) {/*略*/}, {ends: true});
// {% blockquote Hoge Taro, http://example.com %}
// This is a pen.
// {% endblockquote %}

タグ内で国際化( i18n )の機能を利用する

Hexo のテーマでは languages フォルダ内に対応する ‘.yml’ の言語設定ファイルを置くことで、比較的簡単に多言語対応ができます。
こちらも ctx をキャプチャする方法により、 ‘layout/_partial/*.ejs’ などで使われているような呼び出し方による対応が実現できます。

1
2
3
4
5
6
7
8
9
10
11
function fuga(ctx) {
// This declaration not works here!
// const __ = ctx.theme.i18n.__(ctx.theme.i18n.languages);
return function(args) {
const __ = ctx.theme.i18n.__(ctx.theme.i18n.languages); // i18n
const a = __("archive_a"); // Maybe 「アーカイブ」
const b = __("archive_b", "Second"); // Maybe 「アーカイブ: Second」
};
}

hexo.extend.tag.register('hoge', fuga(hexo));

Markdown が HTML に出力された後で静的に変更を加えたい

特定の class を対象に処理をしたい場合、普通は ‘.js’ も配布してクライアントサイドで jQuery 等を使って改変するのが平易な方法ですが、 Hexo ではサーバーでの記事生成時のプロセスである after_post_render に手を加えることで、静的に実現できます。
私のおすすめライブラリは Cheerio です。 jQuery の操作をサーバー側で高速に行えるという認識です。

1
2
3
4
5
6
7
8
9
const cheerio = require('cheerio');

hexo.extend.filter.register('after_post_render', function (data) {
var $ = cheerio.load(data.content, {decodeEntities: true});

// modify like jQuery...

data.content = $.html(); // apply it to the final result
});

おわりに

個人の感覚では、 WordPress よりも柔軟で簡単に機能の拡張できる気がします。
好きなようにカスタマイズして良き Hexo ライフを…