Middleman+GitHub で構築したサイトの検索画面を作る

このブログは MiddlemanGitHub Pages で構築しています。

GitHub Pages は静的な資材をホスティングする機能しかないため、Movable Type でいうところの、mt-search.cgi みたいな、動的な検索画面は作れない制約があります。

そこで、GitHub API v3 を使って JavaScript で実装することにしました。

実際の動作は、サイドバー (モバイル画面では下部) にある、検索窓から、適当な文字列で検索してみて下さい。(例: Hubot)

実装コード

たった 34 行です。 search.slim on ngs/sources.ngs.io

個人ブログで、規模が小さいので、多少富豪的な実装になっています。

Search Code API

検索には GitHub の Search Code API を使っています。検索に使える修飾子は Advanced Search と共通しています。

Searching code on GitHub Help

Search term q に URI エンコードされた検索文字列と、ブログリポジトリ、記事資材を保存しているパスを指定します。

per_page には 100 を指定します。

"https://api.github.com/search/code?q=#{ encodeURIComponent q }+repo:ngs/sources.ngs.io+path:/source/#{lang}/&per_page=100"

サイトマップ・リソース

当たり前ですが、Search Code API は、記事のタイトル・日付など、Middleman 固有のデータ返せないので、サイトマップ・リソースのデータをパスをキーにするハッシュにぶら下げておきます。

ruby:
  sitemap = {}
  blog.articles.each{|a|
    sitemap[a.url] = a.data.merge url: a.url
  }
javascript:
  sitemap = #{sitemap.to_json}

API のコールバックの中で、上記のデータと付け合わせて、テンプレート内でイテレートするコレクションを集めます。

items = _.map res?.items, ({name}) ->
  m = name.match /^(\d{4})\-(\d{2})\-(\d{2})\-(.+)\.md(?:\.erb)?/
  permalink = "/#{m[1]}/#{m[2]}/#{m[3]}/#{m[4]}/"
  sitemap[permalink]

SEO 問題

今回はウェブ検索に引っかかる必要がないので、対策していませんが、GitHub API v3 は robots.txt の制約により、クローラーのアクセスを許可していません。

(上は、Google ウェブマスターツールの Fetch as Google で確認した画面です。)

https://api.github.com/robots.txt

もし、Single Page Application などで活用し、SEO も行いたいのであれば、Heroku に迂回用のアプリを作るなどして対応する必要があります。