Jekyllはカスタムプラグインを使うと色々できるよという話

この記事では、静的サイトジェネレーター「[Jekyll](https://jekyllrb.com/)」のカスタムプラグインで柔軟にサイトをいじる方法を紹介します。

もうちょっとピンポイントな記事もあります: [JekyllでパーマリンクにFront Matterのカスタム変数を使う方法](https://qiita.com/yuki384/items/4b04b866b475fb8b1de9)

## そもそもJekyllとは？
[Jekyll](https://jekyllrb.com/)は、Ruby製のシンプルな静的サイトジェネレーターです。ブログなどを書けるような機能が備わっています(便利！)。.mdファイルや.htmlファイルなどを、Webサイトの表示に必要なファイル一式にして書き出してくれます。共通部分のレイアウトをまとめてかけたり、記事をマークダウン形式で書けたりと、そのままでもとても便利に使えます。

しかし、Rubyで書かれたプラグインを活用することで、**さらに**様々な実装ができます。

### プラグインについて
プラグインは、gemやローカルの.rbファイルを読み込むことで、機能拡張ができるものです。
[プラグインのインストール方法](https://jekyllrb.com/docs/plugins/installation/)
[プラグインのインストール方法(日本語)](http://jekyllrb-ja.github.io/docs/plugins/installation/)

"[jekyll-multiple-languages-plugin](https://github.com/kurtsson/jekyll-multiple-languages-plugin)"(多言語対応に便利なプラグイン) や 公式の"[jekyll-sitemap](https://github.com/jekyll/jekyll-sitemap)"(サイトマップ生成に便利なプラグイン)など、公開されているプラグインを使うことができます。

今回は、自分で実装する「カスタムプラグイン」について紹介します。

## カスタムプラグインの動かし方
ルートディレクトリに、`_plugins`ディレクトリを作り、その下に`.rb`(カスタムプラグインの中身)を置くことで使用できます。
※ちなみに、GitHub Pagesではカスタムプラグインが動きません orz

## カスタムプラグインの種類
Generators、Converters、Commands、Tags、Filters、Hooks の6つがあります。

|種類 |カスタムするところ  |
|---|---|
|[Generators](https://jekyllrb.com/docs/plugins/generators/)  | Webサイトのファイル一式を書き出す前の部分  |
|[Converters](https://jekyllrb.com/docs/plugins/converters/)  |mdファイルなどを変換する部分 |
|[Commands](https://jekyllrb.com/docs/plugins/commands/)  |Jekyllコマンドのサブコマンド|
|[Tags](https://jekyllrb.com/docs/plugins/tags/)  |[Liquid](https://shopify.github.io/liquid/)タグ|
|[Filters](https://jekyllrb.com/docs/plugins/filters/)  |[Liquid](https://shopify.github.io/liquid/)フィルタ|
|[Hooks](https://jekyllrb.com/docs/plugins/hooks/)  |Jekyllでサイトを生成する際の各プロセス|

Jekyllでは`{% if statement %}`のようにして生成処理時にLiquidタグを実行できます。また、`{{ content | filter }}` のようにしてフィルターが使えます。

各プラグインの詳しい書き方は公式サイトに載っているので参考にしてもらえればと思います。

## 実際に書いてみる
実際に、カスタムプラグイン(Hooks)を書いてみました。きれいなコードが書けなくてすみません([プルリクはこちらから](https://github.com/Mekurun/mekurun.com/blob/development/_plugins/usecloudinary.rb))。https://mekurun.com/ という、子ども向けのプログラミング学習サイトを作る際に使用しているコードです。

ここでは、レンダリング後のimgタグのsrcを設定しています。今回は単純に正規表現でマッチした部分を置き換えているだけの単純な処理ですが、普通にRubyが書けるので様々な応用が効きそうです。

ちなみに、サイト高速化を目指し[Cloudinary](https://cloudinary.com/)というCDNを利用するために、画像パスを場合に応じて置き換えているというコード内容になっています。

サイト高速化についての記事は、友人が書いたこちらの記事をぜひ: [【打倒！阿部寛のサイト】高校生が本気でサイト読み込み速度の最適化に取り組んでみた](https://qiita.com/nztm/items/6785a97f02fffa4d5c1f)

要するに、各ページのレンダリング後のHTML(`doc.output`)を読んで、文字列の置き換え処理(素直に`gsub`)をしています。

```ruby
Jekyll::Hooks.register [:pages, :documents], :post_render do |doc|
  # レンダリング後に実行

  out = doc.output
  if ENV["JEKYLL_ENV"] == "production" #本番環境の場合
    # 幅設定がないcloudinaryパス
    src = '\& src="https://res.cloudinary.com/nztm/image/fetch/c_fit,q_auto,f_auto/\1"'
    # 幅設定があるcloudinaryパス
    srcw = 'src="https://res.cloudinary.com/nztm/image/fetch/w_\2,c_fit,q_auto,f_auto,dpr_2/\1" \&'

    # data-srcをもとにパス設定
    out.gsub!(/data-src=[\"|\'](.*?)[\"|\']/, src)
    out.gsub!(/data-src=[\"|\'](.*?)[\"|\'].*data-width=[\"|\'](.*?)[\"|\']/, srcw)
  else #本番環境ではない場合
    src = '\& src="\1"'
    out.gsub!(/data-src=[\"|\'](.*?)[\"|\']/, src)
  end
  puts "#{doc.data["title"]}の画像パスを設定しました"
  doc.output = out
end
```

#### 難しいところ
データ構造がわからないので、Jekyllのコードや他の方のプラグインを見ながら試行錯誤していました。今もあまり完全理解できていないため、ここでの説明は省かせていただきます。

## まとめ
静的サイトジェネレーター「Jekyll」はRubyで様々な拡張ができて楽しいです。とはいえ、サイトビルド時のみいじれるので、インタラクティブなぬるぬるコンテンツは作れないです。そういう実装は素直にJavaScriptを触りましょう。

参考:
[Jekyll](https://jekyllrb.com/)
[Jekyllで作るシンプルWebサイト 第1回 Jekyllとはなにか](https://app.codegrid.net/entry/jekyll-introduction)
[Plugins | Jekyll](https://jekyllrb.com/docs/plugins/)