Jekyll TeXt Themeのアーカイブページにポスト以外のページとタグを表示する

JekyllとGitHub pagesを使って、個人的な技術メモサイトをつくりました(がんばって記事を書こう...)。

ページのテーマはTeXt themeを使っています。
シンプルな見た目のウェブサイトで、サイドバーや目次をページに追加できるなど見やすいメモサイトができると考えて使っています。

ちょっと改善したい所

Text themeにはアーカイブページというページが用意されています。デモサイトではこのようなページとなっています。

このアーカイブページは、ポスト記事(日付で整理される記事、_postフォルダ下のファイル)の一覧とポスト記事についているタグを集めて表示してくれます。また、タグが付いているページ数をカウントし、それも合わせて表示します。さらにタグを選択すると、そのタグが付いているページだけが表示されます。

しかしながら、アーカイブページは ポスト以外のページ の表示やタグの収集はおこないません。今回の私のサイトは日付で管理するブログ的なサイトというより、勉強したことを追記するメモサイトなので、ポスト以外のページも対象にしたいところです。

対応したこと・できていないこと

上記の困りごとのため、ソースコードを改変し、ざっくりと以下の内容に対応しました。

  • Text themeのアーカイブページにポスト以外のページを一覧表示させる
  • Text themeのアーカイブページにポスト以外のページに付いているタグを収集させる
      - 収集したタグを選択するとそのタグが付いているページのみ一覧表示される
    

できていないことは以下です。

  • タグがついているページ数をカウントする

改変後のアーカイブページはこちらです。

改変したこと

先に設定の変更とソースコードの改変部分を挙げておきます。

  • Jekyllのコレクションを使ってページを管理するように_config.xmlを変更
    • コレクションをまとめるディレクトリ(collection_dir)を利用する
  • archive.htmlでポスト以外のページも一覧にする
  • tags.htmlでポスト以外のページのタグを収集し、表示させる

_config.xmlの変更

Jekyllのコレクション(collections)とは、ページをまとめた配列を作成してくれるJekyll標準機能です。

<source>/_hogeという形式でフォルダを作成し、そのフォルダ以下にページを作成すると、site.collections.hogeという配列になります。

<source>はデフォルトではトップページとなりますが、_config.xmlcollection_dirというプロパティを使用することで別のフォルダにすることができます。collection_dirを使った場合には、ポスト記事のフォルダ(_post)や下書きのフォルダ(_draft)もcollection_dirで指定したフォルダ以下に配置する必要があります。

今回は_config.xmlに以下の設定のような設定を追加します。
articlesフォルダ以下にコレクションとなるフォルダを用意します。下のような場合、_java_nodejsというフォルダを用意することになります。

collections_dir: articles
collections:
  java:
    output: true
  nodejs:
    output: true

archive.htmlの改変

archive.htmlは、元々は全てのポスト記事を一覧にして表示してくれるページです。

ここでは、先述のように設定したコレクションを用い、ポスト記事以外のページもこのアーカイブページに表示させます。

具体的には、archive.htmlを以下のように変更します。

変更前

    {% assign my_list = site.posts | concat: site.nodejs | concat: site.oidc_oauth %}
    {%- include article-list.html articles=my_list type='brief' show_info=true reverse=true group_by='year' -%}

変更後

    {%- assign page_list = "" | split: ',' -%}
    {%- for coll in site.collections -%}
      {%- assign page_list = page_list | concat: coll.docs -%}
    {%- endfor -%}
    {%- include article-list.html articles=page_list type='brief' show_info=true reverse=true group_by='year' -%}

tags.htmlの改変

tags.htmlは元々アーカイブページ(archive.html)に読み込まれ、全てのポスト記事から収集したタグの一覧を表示します。タグをクリックすると、そのタグが付いているページのみ表示されるようになります。

今回は修正をおこない、ポスト記事以外の全てのページからタグを収集するように変更します。 最終的に_tagsという変数にタグ情報を格納することで、アーカイブページにタグ機能を利用できるようになります。もともと、変数_tagsにはJekyllに用意されているsite.tagsを格納しています。このsite.tagsはポスト記事についているタグだけが入っています。そこで、全てのページのタグを集め、site.tagsの代わりに同じ構造のオブジェクトを作成してそれを渡せばよいはずです。

site.tagsの構造を説明します。site.tagsは配列になっています。配列の各要素は、さらに配列となっています。この要素の配列の先頭はタグの名称です。配列の2番目はそのタグがつけられているページ情報の配列です。

全てのページのタグから作成したタグ情報のオブジェクトの配列(site.tagsの代替、以下では「タグ情報オブジェクト配列」と呼称)を作成するため、コレクションを使います。 全てのコレクションを取り出し、各コレクションからページを取り出し、ページに付いているタグを取り出します。これらはfor文によるループで実行します。取得したタグは、作成するタグ情報オブジェクト配列に同じ名称のタグがなければ新規に追加し、反対に既に存在すればページ情報の配列に追加します。

変更内容

tags.htmlの先頭に追加します。

{%- assign page_tags = "" | split: ',' -%}

{%- for coll in site.collections -%}
  {%- for page in coll.docs -%}
    {%- for tagname in page.tags -%}
      {%- assign found = false -%}
      {%- for target in page_tags -%}
        {%- if target[0] == tagname -%}
          {%- comment -%}
          下の行がうまく実行できていない
          {%- endcomment -%}
          {%- assign target[1] = target[1] | push: page -%}
          {%- assign found = true -%}
          {%- break -%}
        {%- endif -%}
      {%- endfor -%}
      {%- if found == false -%}
        {%- assign tagstruct = "" | split: ',' -%}
        {%- assign tagstruct = tagstruct | push: tagname -%}
        {%- assign page_list = "" | split: ',' -%}
        {%- assign page_list = page_list | push: page -%}
        {%- assign tagstruct = tagstruct | push: page_list -%}
        {%- assign page_tags = page_tags | push: tagstruct -%}
      {%- endif -%}
    {%- endfor -%}
  {%- endfor -%}
{%- endfor -%}

下のコードを、

{%- assign _tags = site.tags | sort -%}

以下のように変更します。

{%- assign _tags = page_tags | sort -%}

残っている課題

記事の先頭にも記載していますが、上のコードではできていないことがあります。

tags.htmlは元々タグが付いているページ数を表示するようになっていますが、今回の改修をおこなうとページ数が正しく表示できません。tags.htmlの実装コードにもコメントとして書いていますが、対象のタグが付いているページの配列に要素を追加することができていないです。 これは私がLiquid言語の配列の仕様を理解していないため、正しい実装をできていないことが原因のようです。

また、このページの配列が正しくセットされていなくとも、タグをクリックすることでページが絞り込まれる機能は動作しました。 アーカイブページはこちらです。

参考