久々のLazy Blockネタにゃー
以前作ったBlog Cardをパワーアップしよう
ということで長らく適当なアイコンを使っていた箇所をサイトのスクリーンショットにするにゃー
本当に久しぶりですね
よくあの適当なやつを放置していましたね
失敬な!
あれはあれでリンクとわかりやすいアイコンだっただろーが!
そうなんですけど
ソレ以前にデザイン性がね
アレだからね
何を言いたいのかよくわからんが
久しぶりにLazy Blockの画面を開いたらビビったぞ!
CSSやJSの設定項目も追加されているぞ!
これでカスタムブロックに紐づいたCSSとJSも同時に管理できて最高じゃあないか!

アレ、本当だ!
テーマのCSSとの衝突までは考慮されないでしょうけど
配布する際に便利なので開発者の方には刺さる機能ですね!
今までは無理やり全部一つのコードの中に押し込めていたけどこれはイイね!
早速使おう!
いや、どうやらこれはPro版だけの機能みたいですね
なんだよ!
つまらん!
テーマ開発者とかのプロフェッショナル向け機能なのでまさにPro版で解放されるのでしょう
まあいい
話をもとに戻すとスクリーンショット機能だけど
元々Handlebarsだけで作り込んでいたのでこれだけで実現するのは不可能
Web APIを探索してスクリーンショットが取れるやつを見つけたにゃー
そういうAPIが公開されているのですね
いくつか同種のAPIがあったのだけどwordpress.comが提供しているmShotsというやつがあったのにゃー
非公式のサービスらしいけどほかでも動作実績があるらしいのでこれを採用したにゃー
大丈夫なのか?
大丈夫だろ
ダメだったらもとに戻すだけだし
不安だな
あとはAPIから戻ってきた画像を貼り付けるだけなんだけど
このAPI呼び出しがなかなか大変だったので実際のコードを見ながら解説していきたいにゃー
コードのポイント解説
{{#compare url '&&' string}}
{{#if newopen}}
<a class="bcv1-container1 bcv1-clay" href="{{url}}" target="_blank" rel="noopener noreferrer">
{{else}}
<a class="bcv1-container1 bcv1-clay" href="{{url}}">
{{/if}}
<div class="item1 bcv1-clay">
{{string}}
</div>
<picture class="item2 bcv1-clay">
<img loading="lazy" decoding="async" alt="{{truncate string 30 'true'}}" class="lazy" src="" onerror="this.onerror=null;this.dataset.src='https://s.wordpress.com/mshots/v1/' + encodeURIComponent('{{url}}') + '?w=150&h=150';this.src=this.dataset.src;" data-src="">
</picture>
</a>
{{/compare}}
これが実際のコードですね
うむ
ポイントとなるのはimgタグの部分にゃー
なにやら以前と比べて増えてますね
APIはhttps://s.wordpress.com/mshots/v1/[対象URL]の形で呼び出すにゃー
wとかhは画像サイズのパラメータにゃー
Lazy Blocksとしては対象URLを入力するブロックを作ればよい、ということですね
そうなのにゃー
だけど問題があって対象URLにパラメータが含まれているとAPIのパラメータと区別がつかなくなるにゃー
あー
APIのパラメータとして受け取ってしまって正しい対象URLにならないということですね
たまにパラメータ指定でしかコンテンツ生成しないサイトがあるからにゃー
でこの問題を回避するには対象URLの部分をエスケープ処理しないといけないのにゃー
Handlebarsにはその機能はないのですか?
HTMLのエスケープ処理はできるみたいだけどURLパラメータのエスケープ処理はないみたいにゃー
で、調べてみると標準関数でencodeURIComponent()というやつがあったのにゃー
なるほど
だからこれを使っているのですね
これってJavaScriptだから呼び出さないといけないのだけど
srcの部分に直接書いても呼び出してくれないのにゃー
普通にURLとして認識されてしまうということですね
うむ
普通はscriptタグとか使ったりが必要だけど実行するトリガーも考えないとダメにゃー
で、もう少し調べるとイベントハンドラの中だったら使えるということでonerrorの中で呼び出すことにしたのにゃー
onerrorのトリガーはどうやっているのでしょうか?
srcに画像のURLを指定せず空にすることでエラーを誘発しているにゃー
なるほど
それでエラーをトリガーとしてonerrorで関数を呼び出している、と
それでonerrorを呼んで
最初にthis.onerror=null;でもう一度呼ばれないようにonerrorをクリアしているにゃー
実際に画像を読み込んで失敗したら無限ループになりますからね
その次のthis.dataset.src=…..の部分がAPIで画像を拾ってくる部分にゃー
ここでencodeURIComponent()でエスケープ処理しているにゃー
this.dataset.srcってなんですか?
data-srcのことにゃー
どうやらWordPressはLazy loadingでdata-srcを見ているみたいなのでまずはここにURLをセットにゃー
なるほど
こちらも元々空でセットされていますね
その後にthis.src=this.dataset.src;で同じURLにしている、と
おそらくdata-srcだけセットすればLazy loadingの処理の中でsrcにも値をセットするのだろうけどよくわからんからこちらで指定しているにゃー
かなりトリッキーですね
まとめると
srcが空だからエラーが発生
onerrorでAPI向けのURLを組み立て(encodeURIComponentの実行)
this.dataset.srcにURLをセットして画像を読み込み
という流れにゃー
これ以上機能を増やすのならば素直にPHPで作ったほうがいいかもしれませんね
onerrorを使うのがなかなかのトリッキーだからね
これ自体XSSの心配があるけどonerror自体は非推奨ではないらしいのでいいかな、と
初回はちゃんと画像が出ないですね
サーバ側でキャッシュされてないと生成中画像しか出ないみたいにゃー
リロードすると画像が出るにゃー
取得失敗でもなんらかの画像は返してくれるのでそこの処理は考えなくてよかったですね
頑張ればHandlebarsでもなんとかなるということがわかったのでよかったにゃー
素直にPHPを使えばもう少し楽に実装できたのでは!?
それでは今回はこの辺で
Arrivederci
ミラノ・コルティナダンペッツォオリンピックの影響か!?
