reading and coding ...

react-share にはてなブックマークを対応させた話

6/18/2020, 12:27:05 PM - 18 days ago

react-share にはてなブックマークのボタンを追加する PR を出しました。
まだマージされていないので「対応させた」と書くのは時期尚早なのですが、1 週間位たったら全てを忘れていそうなので、今のうちにやったことを書いておきます。


react-share は React 向けに Twitter や Facebook などのソーシャルボタンを提供しているライブラリです。

nygardk/react-share: Social media share buttons and share counts for React

スター数が 1k を超えておりかなり人気のようです。私も以前から存在は知っていました。

ところで、この react-share には、はてなブックマークのボタンが対応していませんでした。
日本においては、はてなのプレゼンスは(特に Web 系プログラマにおいて)強いですが、流石に海外のライブラリに採用されるほどではなかったようです。
とはいえ、はてブボタンの需要はずっとあったようです。自力で実装されている方もいます。

react-share風はてなブックマークボタンをCSSだけでゴリ押し実装する | ebiebievidence.comSNSシェアボタンの設置 3(はてブボタン) - 奇をてらったテクノロジー

以前は開発が停滞していたようですが、最近はメンテされている雰囲気があったので、PR を出してみることにしました。
実際、大規模なリファクタリングが行われていたようでコードは抽象化されていて分かりやすく、実装はとても楽でした。VTuber の配信を聴きながら作業していたらいつの間にか終わっていましたね。


まず、アイコンの SVG を定義する Component を書きました。これが一番大変だった。

import createIcon from './hocs/createIcon';

const HatenaIcon = createIcon({
  color: '#009ad9',
  networkName: 'hatena',
  path:
    'M 36.164062 33.554688 C 34.988281 32.234375 33.347656 31.5 31.253906 31.34375 C 33.125 30.835938 34.476562 30.09375 35.335938 29.09375 C 36.191406 28.09375 36.609375 26.78125 36.609375 25.101562 C 36.628906 23.875 36.332031 22.660156 35.75 21.578125 C 35.160156 20.558594 34.292969 19.71875 33.253906 19.160156 C 32.304688 18.640625 31.175781 18.265625 29.847656 18.042969 C 28.523438 17.824219 26.195312 17.730469 22.867188 17.730469 L 14.769531 17.730469 L 14.769531 47.269531 L 23.113281 47.269531 C 26.46875 47.269531 28.886719 47.15625 30.367188 46.929688 C 31.851562 46.695312 33.085938 46.304688 34.085938 45.773438 C 35.289062 45.148438 36.28125 44.179688 36.933594 42.992188 C 37.597656 41.796875 37.933594 40.402344 37.933594 38.816406 C 37.933594 36.621094 37.347656 34.867188 36.164062 33.554688 Z M 22.257812 24.269531 L 23.984375 24.269531 C 25.988281 24.269531 27.332031 24.496094 28.015625 24.945312 C 28.703125 25.402344 29.042969 26.183594 29.042969 27.285156 C 29.042969 28.390625 28.664062 29.105469 27.9375 29.550781 C 27.210938 29.992188 25.84375 30.199219 23.855469 30.199219 L 22.257812 30.199219 Z M 29.121094 41.210938 C 28.328125 41.691406 26.976562 41.925781 25.078125 41.925781 L 22.257812 41.925781 L 22.257812 35.488281 L 25.195312 35.488281 C 27.144531 35.488281 28.496094 35.738281 29.210938 36.230469 C 29.925781 36.726562 30.304688 37.582031 30.304688 38.832031 C 30.304688 40.078125 29.914062 40.742188 29.105469 41.222656 Z M 29.121094 41.210938 M 46.488281 39.792969 C 44.421875 39.792969 42.742188 41.46875 42.742188 43.535156 C 42.742188 45.605469 44.421875 47.28125 46.488281 47.28125 C 48.554688 47.28125 50.230469 45.605469 50.230469 43.535156 C 50.230469 41.46875 48.554688 39.792969 46.488281 39.792969 Z M 46.488281 39.792969 M 43.238281 17.730469 L 49.738281 17.730469 L 49.738281 37.429688 L 43.238281 37.429688 Z M 43.238281 17.730469 ',
});

export default HatenaIcon;

会社の公式の素材集から SVG を得て、ボタンサイズに合うように「B!」の文字を縮小させてみましたが、本家に比べると文字のサイズが微妙に大きいような気がしています。

pic1
実装したボタン(右端)。B! の文字が大きい

SVG の path の規格をよく知らないので、微調整まではできませんでした。なので、うまく文字を小さくできる人がいたら小さくしてほしいなぁと思います。

次に、Share Button を定義する Component を書きました。

import assert from 'assert';

import createShareButton from './hocs/createShareButton';

function hatenaLink(url: string, { title }: { title?: string }) {
  assert(url, 'hatena.url');

  return `http://b.hatena.ne.jp/add?mode=confirm&url=${url}&title=${title}`;
}

const HatenaShareButton = createShareButton<{ title?: string }>(
  'hatena',
  hatenaLink,
  props => ({
    title: props.title,
  }),
  {
    windowWidth: 660,
    windowHeight: 460,
    windowPosition: 'windowCenter',
  },
);

export default HatenaShareButton;

クエリパラメータは url 以外は取り敢えず title だけ付けておきましたが、正直ブックマークに必要なのは url だけのような気がします。

また、react-share では、物によっては share count を表示させることができるので、ブックマーク数を取得する Component も用意しました。

import jsonp from 'jsonp';

import objectToGetParams from './utils/objectToGetParams';
import createShareCount from './hocs/createShareCount';

function getHatenaShareCount(shareUrl: string, callback: (shareCount?: number) => void) {
  const url = 'https://bookmark.hatenaapis.com/count/entry';

  jsonp(
    url +
      objectToGetParams({
        url: shareUrl,
      }),
    (err, data) => {
      callback(data ? data : undefined);
    },
  );
}

export default createShareCount(getHatenaShareCount);

こちらは特に言うことなし。

あとは、デモ用のコードに実装したはてなブックマークの Component を追加して、上手くいっていることを確かめました。
このように、ボタンの追加は非常に単純なので、もし対応させたい SNS が react-share にまだ存在していない場合は PR を出してみるのも良いのではないかと思います。