Github Pagesで、ディレクトリのファイル一覧を自動生成する

# はじめに

Github Pagesというものがあります。GithubにpushしたリポジトリをWebページとして公開する、というものです。Webサーバを建ててとか面倒だけど自由にいろいろページを作り込みたい、みたいなときに多分役立ちます。

で、少し使ってみて気がついたのは、Apacheなどでよくある、「`index.html`を置いていない時、そのディレクトリに置かれているファイル一覧を見ることが出来る」という機能が提供されていないことです。これをやりたい。やれるんだろうか? やってみました。というメモになります。

# 下準備

Jekyllというツールを使います。これは静的サイトジェネレータと呼ばれるもので、テンプレートや変数などを駆使して記述したファイルからWebページのファイルを生成するというものです。ふつうはサーバ上でなくローカルマシンで動かすものです。が、Github Pagesは生成前のファイルをリポジトリに置くとバックエンドとしてJekyllが走って、サーバー上でWebページを生成してくれます。これをうまく使えばディレクトリのファイル一覧を自動生成できるという理屈です。

Github Pagesのサーバ上でJekyllを動かすには、ローカルマシン上で作業するのと同様のファイルがサーバに置かれている必要があります。つまるところ、リポジトリ上でJekyllを使う準備をして、そのファイルをまるっと`git push`してしまえばいいということになります。

公式の手順説明は下記です。

- [Jekyll を使用して GitHub Pages サイトを作成する](https://docs.github.com/ja/enterprise-server@3.5/pages/setting-up-a-github-pages-site-with-jekyll/creating-a-github-pages-site-with-jekyll)

サマリーを下記に並べますが、ちゃんと公式の手順に従うほうが正確で間違えないと思います。

## Github上での作業

1. リポジトリを作る (ファイルは置かない)
1. リポジトリに降りて`Settings`
1. サイドバーにある`Github Pages`
1. `main`あるいは`master`を選択肢て`Save`

## ローカルマシンでの作業

1. 作ったリポジトリを`git clone`する
1. Jekyllをインストール
1. cloneしたリポジトリのトップディレクトリで `jekyll new --skip-bundle`
1. `Gemfile`を編集。`gem jekyll`の行をコメントアウト、`gem github-pages,"~>228",group以下略`を有効に(`"~>228"`は追加)。
1. `bundle install`
1. `git add .`
1. `git commit -m "Initial commie"` (コミットメッセージは適宜)
1. `git push origin main` (あるいは`master`)

Github上で「ここでみれます」のリンクをたどると、Welcome Jekyll! というPostへのリンクが表示されると思います。

# ファイル一覧を生成するテンプレートを書く

リポジトリ先頭に `contents.md` を置いてみます。内容は下記。

```markdown:contents.md
---
layout: none
title: Contents
---

{% assign doclist = site.pages | sort: 'url'  %}
  {% for doc in doclist %}
-     [{{ doc.name }}]({{ site.baseurl }}{{ doc.url }})
  {% endfor %}
```

書けたら、そのまま`git add`して`git commit`、`git push`までやってしまいましょう。

# 閲覧してみる

Github Pagesでトップページを開くと、右肩のところ `About` の隣に `Contents` というリンクが現れてると思います。リンクをたどれば、一覧が出てくるはずです。

# 出てくるもの、出てこないものの調整

`site.pages` のところをどう指定するかでいろいろ変わります。

## `site.pages`

`site.pages`を指定すると、Jekyllで処理される対象のページだけが一覧に出ます。

具体的には、`front matter`と呼ばれる、ファイル先頭の`---`で区切られた情報です。これが書かれてないファイルは対象外となります。

## `site.static_files`

`site.static_files`を指定すると、Jekyllでの処理対象でないファイルも一覧に含まれます。

## その他

`site.html_files`や`site.html_pages`はそれぞれの中で`.html`と着いたファイルだけに限定します。

具体的な変数の解説は[こちら](https://jekyllrb.com/docs/variables/)。

# サブディレクトリ?

サイト(リポジトリ)のファイルが全部先頭に集まっていればこれでOKですが。サブディレクトリを用意している場合はもうひと工夫必要です。

`site.pages`や`site.files`は、そのサイトの中にあるすべてを引っ張り出してくるからです。

たとえば`contents`サブディレクトリの中だけを一覧にしたい場合は判定文を増やしてフィルタします。単純な例を書きますが、ちゃんとやらないと思わぬファイルが引っかかることがあるかと思いますのでご注意を。

```markdown:contents.md
---
layout: none
title: Contents
---

{% assign doclist = site.static_files | sort: 'url'  %}
  {% for doc in doclist %}
    {& if doc.url contains 'contents/' &}
-     [{{ doc.name }}]({{ site.baseurl }}{{ doc.url }})
    {& endif &}
  {% endfor %}
```

サブディレクトリの`index.md`として配置すれば、ファイル名のみですがディレクトリリスティングが動いているかのように表示できます。

いろいろ追加情報を載せたい場合はご随意に。

# おわりに

まずJekyllがどうなのってあたりがよくわからず謎めいてました。ローカルマシンで作業するの? しないの? ったあたり。次に、`site.pages`を指定していて、生成じゃなくふつうに生で置いたHTMLが一覧に現れず頭を抱えていました。

あとこれPythonでおなじみのJinja2っぽいですけど、Rubyで使えるテンプレートエンジン[Liquid](https://shopify.github.io/liquid/)だそうです。複雑な処理を書きたい場合は公式サイトをご参照ください。

# 参考
- [How to enable automatic directory indexing/listing on GitHub Pages](https://ongclement.com/blog/github-pages-indexing-directory-copy)