弊blog

弊blogはesaで記事を書き、esaのGitHub WebhookでGitHubにPushしてMiddlemanでHTML化している。
詳しくはQiitaに書いた。

esaで書いた記事をGitHub Pagesでブログとして公開する

この仕組みだとタイムスタンプまわりに少し問題があったので改善した。

タイムスタンプ

esaのGitHub Webhookは優秀で、PushするときはMiddlemanなどで扱いやすいように記事のMarkdownにfrontmatterを付与してくれる。

article.html.md
---
title: "たいとる"
category: かてごり
tags: 
created_at: 2016-07-28 00:56:48 +0900
updated_at: 2016-07-28 00:58:15 +0900
published: true
number: 123
---

# 記事本文

hogehoge

このうち、

  • created_atはesaでの記事作成日時
  • updated_atはesaでの記事更新日時

になっている。

Middlemanの場合はこれらの日時を自動で記事のタイムスタンプとして扱ってくれる。

問題点

何が問題かというとblog記事をWIPで下書きしたときである。下書きをWIPで保存したとき、

  • GitHubにはまだPushされない(blogには投稿されない)
  • esaでは記事が作成されたことになるのでcreated_atはそのときの日時となる

という動作になる。

その後blog投稿のためShip It!すると、

  • GitHubにPushされる(blogに投稿される)
  • updated_atは更新されるがcreated_atは更新されない

という動作になる。
そのため、下書き後にblogへ投稿するとcreated_atは実際のblog投稿日時より過去の日時となってしまう。

本来であればblogの投稿日時としてはblogに投稿された日時を使いたい。(当たり前)

解決策1

解決策その1はそもそもblogに投稿日時を表示しないことである。
弊blogも今まではcreated_atを使わずupdated_atのみを使っていた。

が、やはり昔の記事のタイポを修正しただけでトップに来るのはいただけないのでなんとかしたいと考えていた。

解決策2

現在採用しているのはGitのログから日時を取得する方法である。
GitHubにPushされたとき、はじめてblogに投稿される。
なので、記事ファイルが始めてGitにコミットされた日時を得ることができれば、blogに正しく投稿日時を表示することができる。

Gitの日時を使うためconfig.rbでMiddlemanに次のようなパッチをあてた。

config.rb
require "time"

module EsaFrontmatter
  WORK_DIR = File.expand_path("../", __FILE__).freeze

  def data
    return @page_data if @page_data
    super
    command = "cd #{WORK_DIR} && " \
      "git log --date=rfc --pretty=format:\"%ad\" source/#{@file_descriptor.relative_path}"
    created_at = Time.rfc2822(`#{command}`.lines.last)
    @page_data[:created_at] = created_at
    @page_data[:date] = created_at
    @page_data
  end
end

Middleman::Sitemap::Resource.prepend(EsaFrontmatter)

これで無事に記事のcreated_atとしてblogに投稿された日時を使うことができた。

おわりに

だんだん複雑になっていってあんまり好ましくはない… :sob: