LoginSignup
5
6

More than 5 years have passed since last update.

Jekyll Generator の作り方

Posted at

Generator とは

Jekyll で独自のファイルを生成するためのプラグインの一つである。Jekyll::Generator を継承して作成する。

Jekyll は以下の順序でサイトをビルドする。

  1. 処理対象のファイル(Page/Post/Static File)を探す
  2. Generator を実行する
  3. Page と Post を Converter で変換する
  4. 出力先ディレクトリをクリアする
  5. 出力先ディレクトリに Page と Post の変換結果を出力し、Static File をコピーする

全ての Generator は手順 2. で実行される。

Generator という名前から、Generator 自身に何らかのファイルを生成させてしまいそうになるが、生成したファイルは上記の手順 4 で Jekyll によって削除されてしまう(ただし _config.ymlkeep_files に指定したファイルは削除されない)ので、作成されたはずのファイルが見つからず、頭を捻ることになる。

したがって、Generator は直接ファイルを生成するのではなく、独自の Page や StaticFile を生成し、処理対象に追加する。実際のファイル生成は Jekyll の通常の処理に任せるのがよい。

Generator の使用例

  • 処理対象のファイルが存在せず、他の情報から出力ファイルを生成する場合。例えば、他の Post からカテゴリ一覧ページや月別アーカイブページを生成する場合など。

  • 処理対象のファイルを変換したいが、YAML front-matter を書くことができない場合。例えば、画像ファイルを圧縮したり、sass ファイルや AltJS ファイルを変換したりする場合など。

Generator の実装例

Sass の変換を Jekyll のビルドに統合する場合を考える。今回は _scss ディレクトリに Sass のソースファイルを配置し、出力先の css ディレクトリに出力する。

まず、.scss ファイルを表す StaticFile のサブクラス SassStaticFile を作成する。Jekyll は、Static File を出力する際、StaticFile#write を呼ぶので、write をオーバーライドし、出力時に CSS に変換する。

_plugins/sass.rb
require 'pathname'
require 'sass'

module Jekyll

  class SassStaticFile < ::Jekyll::StaticFile

    def initialize(site, base, dir, name)
      super
    end

    def destination(dest)
      (Pathname.new(dest) + 'css' + @name).sub_ext('.css').to_s
    end

    def write(dest)
      dest_path = destination(dest)

      return false if File.exist?(dest_path) && !modified?
      @@mtimes[path] = mtime

      FileUtils.mkdir_p(File.dirname(dest_path))
      template = File.read(path)
      sass = ::Sass::Engine.new(template, syntax: :scss)
      File.write(dest_path, sass.render)

      true
    end
  end

end

次に、.scss を探して SassStaticFile を作成し、Jekyll の処理対象に追加する SassGenerator を作成する。

_plugins/sass.rb
module Jekyll

  class SassGenerator < ::Jekyll::Generator

    def generate(site)
      sass_files(site.source).each do |sass|
        site.static_files << SassStaticFile.new(site,
                                                site.source,
                                                File.dirname(sass),
                                                File.basename(sass))
      end
    end

    def sass_files(source)
      sass_dir = File.join(source, '_scss')
      return [] unless File.directory?(sass_dir)
      files = Dir.chdir(sass_dir) { Dir['**/*.{sass,scss}'] }
      files.map { |file| File.join('_scss', file) }
    end
  end

end

上記の内容を _plugins/sass.rb など、_plugins ディレクトリ以下に配置すれば、Jekyll がビルド時に自動でロードし、_scss/*.scss を CSS ファイルに変換して css/*.css に出力してくれる。

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6