Jekyllの Markdownで目次を作る ことはできるですが、テンプレートで追加している見出しを目次に含めることは できません。そこで、JavaScriptで目次を生成するライブラリを試してみました。

今回、使用したライブラリのバージョンは下記のとおりです。

  • tocbot (4.11.1)

目次

上の目次はJekyllのMarkdownを使って生成しています、このページの下部にある 「関連投稿」はテンプレートで下記のように書かれていますが見出しには含まれていません。

<h3>関連投稿</h3>

また、ページ上部の「Tocbotを使って目次を作ってみる」も<h1>1 ですが目次には含まれていません。

これは目次の収集対象がページ内のコンテンツに限定されているためです。

上記のようなテンプレートで生成している見出しを目次に含める方法はないのでしょうか。

Jekyll プラグインを見てみる

目次を生成するJekyllプラグインはどうでしょうか。

いくつかのJekyllプラグインをみると、

目次の生成部分を各ページに記載するのではなく、テンプレートに記載できるようにする

が主目的のようで、その使い方はcontent2 に対してフィルタとして適用する ことで目次を生成しており、目次の収集対象がページ内のコンテンツに限定されているのは 変らないようです。

jekyll-toc 3 の使い方

{{ content | toc }}

jekyll-toc-generator 4 の使い方

{{ content | toc_generate }}

JavaScriptを試してみる

そこで、JavaScriptで目次を生成するライブラリを試してみます。

JavaScriptで目次を生成するライブラリは、いくつもあるようですが、 評価が良いTocbotを使ってみます。

Tocbot 5

他のライブラリに依存していないのでjs, cssの2つのファイルをリンクするだけで 利用でき、オプションも豊富なので良さそうです。

使い方

2つのファイルをリンクして初期化するだけです。

CSS:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.11.1/tocbot.css">

JavaScript:

<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.11.1/tocbot.min.js"></script>

初期化:

<script type="text/javascript">
tocbot.init({
  // 目次を表示する場所
  tocSelector: '.js-toc',
  // 目次を作成するために見出しを収集する範囲
  contentSelector: '.js-toc-content',
  // contentSelector 要素内で取得する見出し
  headingSelector: 'h1, h2, h3',
  // コンテンツ内の相対または絶対配置コンテナー内の見出し
  hasInnerContainers: true,
});
<script>

上記で初期化した場合、js-toc-contentクラスが指定されている要素と見出し (H1, H2, H3) が目次を生成する対象になる。 特定の要素を目次から除外したい場合は、js-toc-ignoreクラスを付与する。

追加したオプション

ターゲットは移動するがスクロールされない時があったために tocbot.initに以下を追加しました。

// スムーズスクロールが有効
scrollSmooth: false,

以下も追加しました。

// リストを縮小する必要があるときに追加されるクラス
isCollapsedClass: '',

// アクティブなリンクに追加するクラス
activeLinkClass: '',

// 順序付きリストの代わり(ol)
orderedList: false,

まとめ

Tocbotは本来、

サイドに目次を表示し本文のスクロールに目次のマーカーが追随する

といった使い方をするのでしょう。JekyllのMarkdown風に上部に固定して表示する というのはかなり限定的な使い方なのかもしれませんが、こんなに簡単に実現できる、 のは十分有用だと思いました。

このサイトにも気が向いたら導入するかもしれません。

参考にしたサイト

  1. Minimaに限らず大抵のブログテーマではレイアウトを統一するために <h1>をテンプレートで生成しています 

  2. テンプレートでページ内のコンテンツは{{ content }}}と 書かれています 

  3. toshimaru / jekyll-toc 

  4. dafi / jekyll-toc-generator 

  5. tscanlin / tocbot 動作デモは Tocbot で確認できる