Toc.js
ページ内の見出しから目次(Table of Contents)をクライアントサイドのJavaScriptで自動生成するモジュール。
toc_js
インストール
composer require 'drupal/toc_js:^3.3'
概要
Toc.jsモジュールは、ページ内の見出し要素(h2, h3など)を検出し、クライアントサイドで自動的に目次(Table of Contents)を生成するJavaScriptライブラリを提供します。サーバーサイドでの処理を必要とせず、軽量で高速な目次生成を実現します。
このモジュールは複数の方法で目次を表示できます。ノードの追加フィールドとして表示する方法、ブロックとして任意のページに配置する方法、そしてテキストフィルターを使用して[toc]ショートコードを目次に変換する方法があります。スムーズスクロール、スクロール時のハイライト、トップへ戻るリンク、スティッキー表示など豊富な機能を備えています。
同一ページに異なる設定の複数の目次を配置することも可能で、アクセシビリティに配慮したARIA属性のサポートや、Ajaxによるページ更新への対応機能も実装されています。
Features
- クライアントサイドJavaScriptによる高速な目次自動生成
- ノードの追加フィールドとして目次を表示(コンテンツタイプごとに設定可能)
- ブロックによる任意ページへの目次配置
- テキストフィルターによる[toc]ショートコードのサポート
- スムーズスクロール機能によるスムーズなページ内移動
- スクロール時の現在位置ハイライト表示
- 見出しごとの「トップへ戻る」リンクの自動挿入
- 「目次へ戻る」リンクの挿入(キーボードナビゲーション対応)
- 目次のスティッキー(固定)表示
- 折りたたみ可能な階層構造の目次項目(実験的機能)
- CSSセレクターによる柔軟なコンテナと見出し要素の指定
- CSS変数によるスクロールオフセットとスティッキーオフセットの設定
- 不可視の見出しをスキップするオプション
- 見出しからCSSクラスを継承する機能
- Ajaxページ更新時の目次自動更新(実験的機能)
- アクセシビリティに配慮したARIA属性と画面リーダー対応
Use Cases
長いドキュメントページの目次
ヘルプドキュメントやFAQなど、長いコンテンツを持つページに自動で目次を生成します。コンテンツタイプの設定で「Enable Table of contents」を有効にし、「表示管理」でTocフィールドをコンテンツの上部に配置します。見出しh2とh3を対象にし、スムーズスクロールとスクロール時ハイライトを有効にすることで、ユーザーが目的のセクションに素早くアクセスできます。
サイドバーに固定表示する目次
ブログ記事やチュートリアルページのサイドバーに、スクロールしても追従する目次を表示します。Toc.jsブロックをサイドバーリージョンに配置し、「Sticky」オプションを有効化します。「Sticky offset」でヘッダーの高さを考慮したオフセットを設定し、「Highlight on scroll」で現在読んでいるセクションをハイライト表示します。
ナレッジベースの記事ごとに目次の有無を制御
ナレッジベースサイトで、短い記事には目次を表示せず、長い記事にのみ目次を表示します。toc_js_per_nodeサブモジュールを有効化し、コンテンツタイプで「Permit to enable/disable toc per node」をオンにします。「Default state」を「Enabled」に設定しておき、短い記事の編集時に「Display a table of contents」チェックを外します。また、「Minimum elements」設定で見出しが一定数以上ある場合のみ表示することも可能です。
エディタが記事内に目次を挿入
CKEditorやその他のリッチテキストエディタで、記事の任意の位置に目次を挿入できるようにします。toc_js_filterサブモジュールを有効化し、該当するテキストフォーマットの設定で「TOC.js shortcode: [toc]」フィルターを有効にします。エディタは記事本文に[toc]と入力するだけで、その位置に目次が自動生成されます。
複数言語サイトでの目次ラベルのカスタマイズ
多言語サイトで目次のタイトルや「トップへ戻る」リンクのラベルを各言語に合わせて設定します。コンテンツタイプの設定で「Title」に日本語で「目次」と入力し、「Back to top link label」に「ページトップへ」と設定します。翻訳可能なラベルフィールドにより、各言語版で適切なラベルが表示されます。
アクセシビリティ対応の目次ナビゲーション
スクリーンリーダーユーザーやキーボードナビゲーションユーザーに配慮した目次を実装します。「Heading focus」を有効にして目次リンククリック時に見出しにフォーカスを設定し、「Show back to toc links」を有効にして見出しから目次への戻りリンクを提供します。「Back to toc link CSS classes」に「visually-hidden-focusable」を設定することで、通常は非表示ですがフォーカス時に表示されるリンクになります。
Ajaxで動的に更新されるコンテンツの目次
Views Infinite ScrollやLoad Moreなど、Ajaxでコンテンツが動的に追加されるページの目次を自動更新します。「Ajax page updates handling」オプションを有効にし、必要に応じて「Custom observable container selector」でAjax更新を監視するコンテナを指定します。MutationObserverにより、コンテンツの追加・削除時に目次が自動的に再生成されます。
Tips
- CSSカスタム変数を活用: scroll-to-offsetやsticky-offsetでvar()構文を使用すると、テーマのCSS変数と連携した柔軟な設定が可能です。
- テンプレートのカスタマイズ: toc-js.html.twigをテーマにコピーし、toc-js--node--article.html.twigのような名前で保存すると、コンテンツタイプごとに異なるマークアップを適用できます。
- パフォーマンス最適化: 大量の見出しがあるページでは「Skip invisible headings」を有効にし、不要な見出しを除外することでパフォーマンスを向上できます。
- 見出しのクリーンアップ: 見出しにアイコンや装飾的な要素が含まれる場合、「Heading cleanup selector」に該当するセレクター(例: .icon, .decoration)を指定して目次から除外できます。
- アクセシビリティ: 「Back to toc links」を有効にし、CSSクラスに「visually-hidden-focusable」を設定すると、キーボードユーザーにとって便利なナビゲーションを提供しつつ、視覚的には目立たないリンクを実装できます。
- Ajaxコンテンツ: Views Infinite Scrollなどと組み合わせる場合は「Ajax page updates handling」を有効にし、適切なobservable_selectorを設定してください。
- 最小要素数の活用: 「Minimum elements」を2や3に設定すると、見出しが少ない短い記事では目次が表示されず、長い記事のみに表示されるようになります。
Technical Details
Admin Pages 3
/admin/structure/types/manage/{node_type}
各コンテンツタイプに対してToc.jsの目次機能を有効化し、詳細な設定を行います。設定はコンテンツタイプの編集画面内の「Table of contents」セクションで行います。
/admin/structure/types/manage/{node_type}/display
コンテンツタイプの表示管理画面で、Toc(目次)追加フィールドの表示位置を設定します。目次機能を有効にした後、この画面で「Toc」フィールドを目的の位置にドラッグします。
/admin/structure/block
Toc.jsブロックを任意のリージョンに配置します。「ブロックを配置」から「Toc js」カテゴリ内の「Toc.js block」を選択して設定します。
権限 2
Hooks 5
hook_theme
toc_jsテーマフックを定義。目次のHTMLレンダリングをカスタマイズ可能にします。
hook_theme_suggestions_toc_js_alter
エンティティタイプ、バンドル、エンティティIDに基づいたテーマサジェスチョンを追加。より詳細なテンプレートオーバーライドが可能。
hook_entity_extra_field_info
Toc.jsが有効なコンテンツタイプに「Toc」追加フィールドを登録
hook_node_view
ノード表示時に目次をレンダー配列に追加
hook_form_node_type_form_alter
コンテンツタイプ編集フォームにToc.js設定セクションを追加
Troubleshooting 6
1) コンテンツタイプの「Table of contents」で「Enable Table of contents」がチェックされているか確認。2) 「表示管理」でTocフィールドが有効なリージョンに配置されているか確認(「無効」エリアにないこと)。3) 「Selectors」設定が実際のコンテンツの見出しタグと一致しているか確認。4) 「Container」設定が正しいセレクターか確認(デフォルトは.node)。5) 「Minimum elements」が実際の見出し数以下か確認。
1) 「Sticky offset」に適切な値が設定されているか確認(固定ヘッダーがある場合はその高さを指定)。2) CSS変数構文を使用している場合、その変数がテーマで定義されているか確認。3) 目次の親要素に position: relative や overflow: hidden が設定されていないか確認。4) 「Toc container selector」で適切な親要素を指定しているか確認。
「Scroll offset」に固定ヘッダーやツールバーの高さを考慮した値を設定します。例: 「100px」や「var(--header-height, 80px)」。また、見出しにscroll-margin-topを適用するCSSをテーマに追加することも有効です。
1) ページ内に同じIDを持つ要素が存在しないか確認。2) JavaScriptエラーがブラウザコンソールに出ていないか確認。3) jQueryとonceライブラリが正しく読み込まれているか確認。
1) toc_js_per_nodeサブモジュールが有効化されているか確認。2) コンテンツタイプの設定で「Permit to enable/disable toc per node」がチェックされているか確認。3) 「Administer Toc.js per node」または「Administer nodes」パーミッションがあるか確認。
1) toc_js_filterサブモジュールが有効化されているか確認。2) 使用しているテキストフォーマットで「TOC.js shortcode: [toc]」フィルターが有効か確認。3) フィルターの処理順序が適切か確認(HTMLを生成するフィルターの後に配置)。
Security Notes 3
- Toc.jsの設定フィールドではXSSフィルタリングが適用されています。特にタイトルやラベルフィールドではXss::filter()を使用し、許可されたHTMLタグ(spanのみ)以外は除去されます。
- CSSセレクターやクラス名の入力値はHtml::cleanCssIdentifier()で処理され、不正な文字が除去されます。
- ユーザー入力値がdata-*属性として出力される際にもXSSフィルタリングが適用されています。