livedoor Reader のテンプレートをカスタマイズ

LDR では、フィード一覧や記事など、あらゆるデータの表示が JavaScript+HTML のテンプレート・システムによって行われます。

この HTML 側のテンプレートを変更することで、表示を自在にカスタマイズすることが可能になります。

ldr-template1

ldr-template2


全てのテンプレートは TEXTAREA 内に文字列として格納されています。

単純な変更であれば

$("TEMPLATE_ID").innerHTML = $("TEMPLATE_ID").innerHTML.replace(search, replace);

のようにすれば良いんですが、一からセットし直す場合は、"<" ">" 等の特殊文字エスケープする必要があります:

$("TEMPLATE_ID").innerHTML = 'HTML コード'.escapeHTML();
/* Greasemonkey の場合は
 * new unsafeWindow.String('HTML コード').escapeHTML()
 * として LDR の escapeHTML が利用できるかと思います。
 */
/* もしくは
 * $("TEMPLATE_ID").appendChild(document.createTextNode('HTML コード'))
 */


カスタムの一例として、はてブ・エントリーへのリンクを記事に埋め込んでみましょう:

$("inbox_items").innerHTML = [
  '...',
  '<a id="hatebu_[[id]]" href="http://b.hatena.ne.jp/entry/[[#{ link.replace(/#/,"%23") }]]">?B</a>',
  '...'
].join("").escapeHTML();

(全体を示していないのは、とにかくソースをよく読んでからでないと難しいですよ、というメッセージとご理解ください…)

ポイントは #{ ... } の部分です。livedoor clip との連携機能が導入された辺りからだと思うんですが、テンプレートに

[[#{ }]]

の記法で JavaScript 式が埋め込めるようになっています。

この中では変数のようにしてキーを参照することが出来ます (上の例では link)。式全体がデータ・オブジェクトのコンテキストで eval されるため、そんなことが可能なんですね。


さて、ここで注意点なんですが、文字列を変更するだけでは上手くいかない場合があります: テンプレートが動的に評価されない (ロード時に一度だけ評価される) 場合です。

例えば記事のテンプレートであれば、カスタム後に

ItemFormatter.TMPL = Template.get("inbox_items");

の一文を実行しないと変更が反映されません。


また、テンプレートはデータの表示だけに関わるものではないという点にも注意する必要があります。

つまり、テンプレートに基づいて生成された DOM の上に、表示以外の様々な機能 (記事であれば移動、クリッピングなど) が被さってくるわけです。

ですから、特定の DOM 構造や ID の存在に依拠した処理が (GM スクリプトも含め) どこかで行われている、ということを考えながら慎重に変更する必要があるのです。

LDR 側の仕様変更によって動作がおかしくなったり、新しい機能が利用できなかったり、といったリスクも当然理解しておかなければならないでしょう。