monolithic kernel

Octopressではてなスターを使う

Octopressではてなスターを使うための情報が少ないので記事にしてみました。

まず、_config.ymlにトークンを記述しておきます。

hatena_star_token: ...

こちらがメインのコードです。

{{ "{% if site.hatena_star_token" }} %}
  <script type="text/javascript">
    (function() {
      var s = document.createElement('script');
      s.src = 'http://s.hatena.ne.jp/js/HatenaStar.js';
      s.async = true;
      s.onload = function () {
        (function() {
          var base = Hatena.Star.EntryLoader.getElementByConfigSelector;
          Hatena.Star.EntryLoader.getElementByConfigSelector = function(selector, parent) {
            var links, n, i, link, a;
            if (selector == 'link[rel="canonical"]') {
              links = document.getElementsByTagName('link');
              for (i = 0, n = links.length; i < n; ++i) {
                link = links[i];
                if (link.rel == 'canonical') {
                  a = document.createElement('a');
                  a.setAttribute('href', link.href);
                  return a.cloneNode(false);
                }
              }
            }
            else {
              return base(selector, parent);
            }
            return null;
          };
        })();
        Hatena.Star.Token = '{{ "{{ site.hatena_star_token" }} }}';
        Hatena.Star.SiteConfig = {
          entryNodes: {
            '#content article': {
              {{ "{% if page.single" }} %}
                uri: 'link[rel="canonical"]',
              {{ "{% else" }} %}
                uri: '.entry-title a',
              {{ "{% endif" }} %}
              title: '.entry-title',
              container: '.meta'
            }
          }
        };
      };
      document.getElementsByTagName('head')[0].appendChild(s);
    }());
  </script>
{{ "{% endif" }} %}

オフィシャルなのと比べるとやたら長いですね。長い理由は以下の2つのことをやっているからです。

  • JavaScriptの非同期ロード
  • rel=“canonical”を参照

非同期ロードはレンダリングのブロックを防いで高速化するのが狙いです。はてなスターのコードは公式だと非同期になっていませんが、実際には非同期で読み込んでも特に問題は起きないようなので非同期にしています。

rel=“canonical”を参照しているのは、Octopressのデフォルトのテーマでは個別の記事のページにpermalinkを指し示す要素が他にないからです。はてなスターはwindow.locationの値を記事のURLとして扱う機能も持っていますが、正規化されていなくて気持ち悪いのでrel=“canonical”を参照する機能を付け足すことにしました。

ベース部分はos0xさんのところを、rel=“canonical”を利用する手法はhail2uさんのところを参考にしています。

ヘッダ部分で先ほどのコードを組み込みます。

{{ "{% include custom/hatena_star.html" }} %}

最後に、CSSで見た目の微調整をしています。blockquoteタグにスタイルを設定していると引用のポップアップの表示がおかしくなるので調整は必須です。はてなスターは適切にクラスが設定されていないのでセレクタが酷いですし、そもそもページのスタイルシートの影響を受けすぎです。

.hatena-star-comment-container, .hatena-star-star-container {
  img {
    @include border-radius(0);
    @include box-shadow(none);
  }
}

body > div[style] > div[style] {
  background: inherit;
  border: 0;

  > blockquote[style] {
    border: 0;
  }
}

長い……。なんで1ウェブサービスのブログパーツを組み込むのにこんなに手間がかかるのか……。もっと筋のいいサービスに登場して欲しいところなのですが、あんまり儲かりそうじゃないですし、そういう意味でははてなにしかできないサービスなのかもしれないですね。