Jekyllに目次バーを追加する

Jekyllとは

JekyllはGitHub Pagesにてデフォルトで利用できる静的サイトジェネレータ(SSG)です。
このブログも現時点ではGitHub Pages上で動いており、Jekyllを用いて構築してます。

静的サイトと動的サイトについて

ところで静的サイトジェネレータとは静的サイトを生成するためのツールのことです。

で、静的サイトとは、ブラウザでアクセスする(リクエストする)ごとにサーバ側(バックエンド側)で処理せずに予めサーバに用意しているHTML、CSS、JSなどをそのまま返すだけのサイトです。
すなわち、その逆は動的サイトであり、リクエストするごとにバックエンド側で処理して出力したものを返します。

例えば、静的サイトは「リクエストされると既に用意してあるプリントを渡す」、動的サイトは「リクエストされてからプリントを印刷して渡す」かの違いといえばわかりやすいでしょうか。

ブログの多くは基本的には動的サイトで例えばWordPressといったPHP言語製のCMS(コンテンツ管理システム)などのソフトウェアが使われています。

それに対して静的サイトはGo言語製のHugoやRuby言語製のJekyllががあります。
どちらもMarkdownや一部のHTMLといった記法を用いて記事を作成できます。

目次の追加

allejo/jekyll-toc - GitHub

A GitHub Pages compatible Table of Contents gen...

上記のjekyll-tocリポジトリにある _includes/toc.html を構築したjekyllの_includesフォルダにtoc.htmlとして保存します。

右に目次用のバーを追加する

電研のdenken-jekyllリポジトリの layouts/default.html は下記の通りである。
_includes/rightbar.html として右の目次バー用のhtmlを作成してもよかったが、取り合えず、default.htmlにて追加しておく。

  • default.html
<!DOCTYPE html>
<html lang="{{ page.lang | default: site.lang | default: "ja" }}">

  {%- include head.html -%}

  <body>
    
    {% include navbar.html %}

    <div class="container">
      <main class="page-content" aria-label="Content">
        <div class="wrapper">
          <h1>{{ page.title }}</h1>
          {{ content }}
        </div>
      </main>
      <aside class="rightbar">{%- include toc.html html=content sanitize=true -%}</aside>
    </div>

    {%- include footer.html -%}

  </body>

</html>

aside.rightbarタグ内の {%- include toc.html html=content sanitize=true -%} は目次そのものである。
_includesに保存しておいたtoc.htmlをincludeし、htmlパラメータにcontent(html変換後の記事の内容)を指定し、sanitizeをtrueにすることで二重アンカにならないようにプレーンテキストにサニタイズしておく。

これで右バーへ目次を追加できた。

cssは以下の通りだ。

.container {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
}

.page-content {
  flex: 1 1 0%;
  min-width: 0;
}

.rightbar {
  width: 300px;
  max-width: 30vw;
  margin-left: 2rem;
  background: #f8f9fa;
  border-left: 1px solid #e0e0e0;
  padding: 1rem;
  overflow-y: auto;
  height: auto;
  position: sticky;
  top: 50px;
  box-sizing: border-box;
}

.rightbar:empty {
  display: none !important;
}

.rightbar:empty はタグ内にまったく要素がない、空であるときdisplay: noneにする、つまり何も入っていない、目次がない場合は右バーrightbarを非表示にする。

目次を生成しているのにも関わらず、空にならない

rightbar内には謎の改行が入っていました
後ほどいろいろと確認してみると _includes/toc.html に原因でした。

まず、先頭行の{% capture tocWorkspace %}、最終行の{% endcapture %}{% assign tocWorkspace = '' %}{{ deprecation_warnings }}{{ jekyll_toc -}}をそれぞれ{%- capture tocWorkspace -%}{%- endcapture -%}{%- assign tocWorkspace = '' -%}{{ deprecation_warnings }}{{ jekyll_toc -}} にします。
つまり {% ... %}{%- ... -%} のようにハイフンを付け加えます。

何をしているのか (空白制御)

ハイフンを付け加えることでWhitespace Control (空白制御) ができます。
これは改行や空白を除去できる機能です。

表記をまとめると

フォーマット 説明
{% ... %} デフォルト
{%- ... %} 前の空白を除去
{% ... -%} 後の空白を除去
{%- ... -%} 前後の空白を除去

これで正常に空となり、.rightbar:emptyが機能するようになりました。