2018-07-04

tobijibu

Pugで作成日時と更新日時を生成して埋め込む

GulpでPugをコンパイルする際に、ファイルの更新日時(gitのコミット日時)を埋め込む方法は無いかと考えていました。 模索した結果、埋め込む方法がありましたので紹介します。

まず、examples.puggit logからコミット日を取得する方法を考えてみましょう。

更新日時(最新のコミット日)

更新日時の場合はファイルを指定して、1件だけ取得すれば良いでしょう。 取得時に日付フォーマットも指定すると処理しやすいと思います。

git log -1 --format=%cd --date=format:"%Y年%m月%d日 %H時%M分%S秒" examples.pug

作成日時

作成日時は少し複雑です。

指定したファイルの最古のコミットを取得するには、 指定したファイルのコミットから一番古いハッシュを取得します。そしてハッシュを指定してその中の最新の1件を取得するという方法になります。

少し複雑ですが、ワンライナーで書くと以下のようになります。

git log -1 --format=%cd --date=format:"%Y年%m月%d日 %H時%M分%S秒" `git rev-list HEAD examples.pug | tail -1`

git rev-list HEAD examples.pugexamples.pugのコミットハッシュを取得し、 |tail -1で末尾(最古)のハッシュを取得します。このコマンドは``で囲っているので外側のコマンドのネストとして機能します。 そうすることで、git log -1 --format=%cd ~の引数としてコミットハッシュを渡すことができます。

git logはコミットハッシュを渡すと、指定したハッシュより前のコミットログを取得できますので、 -1を指定して最新のコミットログ、つまり指定したファイルの最古のコミットログを取得することができます。


コマンドで日時を取得するイメージができたので、GulpとPugの準備をします。

必要なパッケージをインストール

今回の処理に必要なパッケージをインストールします。

$ npm install --save-dev gulp gulp-pug gulp-data

gilpfile.jsを生成

次にgilpfile.jsを編集します。

モジュール

const gulp     = require('gulp');
const pug      = require('gulp-pug');
const data     = require('gulp-data');
const execSync = require('child_process').execSync;

更新日生成

/* 更新日時生成 */
let update_cmd = 'git log -1 --format=%cd --date=format:"%Y年%m月%d日 %H時%M分%S秒" ' + file.relative;
let update = execSync(update_cmd, {
  cwd: file.base
}).toString();

作成日時生成

作成日時は先程のワンライナーは使えませんでした。 execSyncでは``$()を使ってネストしたコマンドは使えないようです。

そのため、1.コミットハッシュを取得、2.コミットハッシュでログを取得の2ステップで取得します。

/* 作成日時生成 */
// 1.コミットハッシュ取得
let hash_cmd = 'git rev-list HEAD ' + file.relative + ' | tail -1';
let githash = execSync(hash_cmd, {
  cwd: file.base
}).toString();

// 2.コミットハッシュからログを取得
let create_cmd = 'git log -1 --format=%cd  --date=format:"%Y年%m月%d日 %H時%M分%S秒" ' + githash;
let create = execSync(create_cmd, {
  cwd: file.base
}).toString();

オブジェクトを返す

生成したデータをオブジェクト形式で返します。 この時のキーは、Pugテンプレート内で使う変数名になります。

return {
  'create': create,
  'update': update
};

最終的にgulpfile.jsの全体像は以下のようになります。

'use strict';

const gulp     = require('gulp');
const pug      = require('gulp-pug');
const data     = require('gulp-data');
const execSync = require('child_process').execSync;

gulp.task('pug', function(){
  gulp.src('src/*.pug')
    .pipe(data(function(file) {
      /* 更新日時生成 */
      let update_cmd = 'git log -1 --format=%cd --date=format:"%Y年%m月%d日 %H時%M分%S秒" ' + file.relative;
      let update = execSync(update_cmd, {
        cwd: file.base
      }).toString();

      /* 作成日時生成 */
      // 1.コミットハッシュ取得
      let hash_cmd = 'git rev-list HEAD ' + file.relative + ' | tail -1';
      let githash = execSync(hash_cmd, {
        cwd: file.base
      }).toString();

      // 2.コミットハッシュからログを取得
      let create_cmd = 'git log -1 --format=%cd  --date=format:"%Y年%m月%d日 %H時%M分%S秒" ' + githash;
      let create = execSync(create_cmd, {
        cwd: file.base
      }).toString();

      return {
        'create': create,
        'update': update
      };
    }))
    .pipe(pug())
    .pipe(gulp.dest('build/'))
});

テンプレート

とても簡単な形ですが、以下のテンプレートを用意しました。

date.pug

div
  span 更新: #{update}
  br
  span 作成: #{create}

結果

<div><span>更新: 2018年07月03日 13時32分00秒
</span><br/><span>作成: 2018年07月03日 13時18分11秒
</span></div>

このように、gitで管理されているPugテンプレートであれば、日付を生成することができます。 工夫すれば、staticなブログも作成できるかもしれません。