はてなブックマークにはブックマークコメントをブログなどに埋め込む機能が用意されています。
もう10年以上前の機能なんですねー。
で、たとえば、自分のブクマコメントをブログに引用したい!という時に、生成される埋め込みタグが長いんですよ。
どうにかしたいなー、というのがこのエントリの主旨。
分析
問題の埋め込みコードはこんな感じ。ながい。
<blockquote class="hatena-bookmark-comment"><a class="comment-info" href="http://b.hatena.ne.jp/entry/359425227/comment/yosio_ism" data-user-id="yosio_ism" data-entry-url="http://b.hatena.ne.jp/entry/s/note.mu/najeira/n/n8924408dd07b" data-original-href="https://note.mu/najeira/n/n8924408dd07b" data-entry-favicon="https://cdn-ak.favicon.st-hatena.com/?url=https%3A%2F%2Fnote.mu%2F" data-user-icon="/users/yosio_ism/profile.png">Android / iOS アプリの開発にクロスプラットフォームの Flutter を実戦投入した|najeira|note</a><br><p style="clear: left">Dartの言語仕様自体は難しくなさそうだったので試してみる価値はありそう。</p><a class="datetime" href="/yosio_ism/20180302#bookmark-359425227"><span class="datetime-body">2018/03/02 18:17</span></a></blockquote><script src="https://b.st-hatena.com/js/comment-widget.js" charset="utf-8" async></script>
ちなみにレンダリング具合はこう。
Android / iOS アプリの開発にクロスプラットフォームの Flutter を実戦投入した|najeira|noteDartの言語仕様自体は難しくなさそうだったので試してみる価値はありそう。
2018/03/02 18:17
https://b.st-hatena.com/js/comment-widget.js をてきとうに読んでみると、JSONPでデータを取ってきて上のblockquote内の内容をiframeに押し込めた上で置き換えてるっぽい。データ取得できるまでの間、引用文が表示されないための配慮なんですかねー。
逆にいうと、割り切ればJSONPだけでも良いような。(私的には自分のコメントが欲しいだけなので、なおのこと。)
JSONPのパラメタはこう。
https://b.hatena.ne.jp/api/bookmark.show?user_name=${uid}&url=${ourl}&callback=${f}
uid := コメント取得するユーザID(私のIDであれば"yosio_ism")
ourl := 元記事のURL
f := JSONPのコールバック先関数名
いずれも適切にurlエンコードしてください。
試しに実行してみる。
$ curl 'http://b.hatena.ne.jp/api/bookmark.show?user_name=yosio_ism&url=https%3A%2F%2Fnote.mu%2Fnajeira%2Fn%2Fn8924408dd07b&callback=p'
p({"bookmark":{"comment_raw":"Dartの言語仕様自体は難しくなさそうだったので試してみる価値はありそう。","epoch":1519982269,"private":null,"eid":"359425227","entry_id":"359425227","tags":[],"permalink":"http://b.hatena.ne.jp/yosio_ism/20180302#bookmark-359425227","comment":"Dartの言語仕様自体は難しくなさそうだったので試してみる価値はありそう。","timestamp":"2018/03/02","user":{"profile_icon_uri":"http://cdn.profile-image.st-hatena.com/users/yosio_ism/profile.png","can_plus_icon":false,"name":"yosio_ism"}}});
データ部を整形するとこんな感じ。
{
"bookmark": {
"comment_raw": "Dartの言語仕様自体は難しくなさそうだったので試してみる価値はありそう。",
"epoch": 1519982269,
"private": null,
"eid": "359425227",
"entry_id": "359425227",
"tags": [],
"permalink": "http://b.hatena.ne.jp/yosio_ism/20180302#bookmark-359425227",
"comment": "Dartの言語仕様自体は難しくなさそうだったので試してみる価値はありそう。",
"timestamp": "2018/03/02",
"user": {
"profile_icon_uri": "http://cdn.profile-image.st-hatena.com/users/yosio_ism/profile.png",
"can_plus_icon": false,
"name": "yosio_ism"
}
}
}
利用
最小構成で行くとこんな感じのマークアップで良いのではないかしら。
<blockquote class="hatena-bookmark-comment" data-user-id="yosio_ism"><a href="https://note.mu/najeira/n/n8924408dd07b">Android / iOS アプリの開発にクロスプラットフォームの Flutter を実戦投入した|najeira|note</a></blockquote>
Android / iOS アプリの開発にクロスプラットフォームの Flutter を実戦投入した|najeira|note
(() => {
let a = function(e, n){ return e.appendChild(n) };
let e = function(e, a){ let el = document.createElement(e); if(a){ Object.assign(el, a) }; return el };
let q = function(s){ return Array.prototype.slice.call(document.querySelectorAll(s)) };
let c = function(u){ return encodeURIComponent(u) };
let x = function(d){
let p = this;
let h = this.innerHTML;
this.innerHTML = '';
a(p, e('p', {textContent: d.bookmark.comment}))
a(p, e('div', {className: 'entry', innerHTML: h}))
};
let i = 0;
q('.hatena-bookmark-comment').map((el) => {
let a = el.querySelector('a');
let uid = c(el.getAttribute('data-user-id'));
let ourl = c(a.href);
return [el, uid, ourl];
}).forEach((arry) => {
let el = arry[0];
let s = document.createElement('script');
let f = '__jsonp' + i++;
window[f] = function(d){ x.call(el, d); delete window[f]; }
s.src = `https://b.hatena.ne.jp/api/bookmark.show?user_name=${arry[1]}&url=${arry[2]}&callback=${f}`;
a(document.getElementsByTagName('head')[0], s);
})
})();
ホントは
<q class="hatena-bookmark-comment" cite="http://b.hatena.ne.jp/entry/359425227/comment/yosio_ism"></q>
こんくらいシンプルにしたかった…。