TOC(Table of Contents)を自動生成して表示させる
Translate to English
https://translate.google.com/translate?sl=auto&tl=en&u=https%3A%2F%2Fksby.hatenablog.com%2Fentry%2F2021%2F01%2F16%2F180857
概要
記事一覧はこちらです。
AsciiDoc で作成されたドキュメントを見ると右か左に TOC(Table of Contents)が表示されています。Spring Boot や JUnit 5 のドキュメントだと下にスクロールさせると TOC が自動的に展開されて現在見ている section が分かるようになっています。TOC(Table of Contents)があるとドキュメントが見やすいので、同じように表示させてみます。
- AsciiDoc Writer’s Guide
- Asciidoctor Gradle Plugin Suite
- Spring Boot Reference Documentation
- JUnit 5 User Guide
- Draw.io Integration for IntelliJ
個人的には以下のドキュメントの TOC(Table of Contents)の方が好みなので、この TOC の実現方法も調べてみます。
参照したサイト・書籍
Automatic Table of Contents
https://docs.asciidoctor.org/asciidoc/latest/toc/unit-team / junit5/documentation/src/docs/asciidoc/
https://github.com/junit-team/junit5/tree/main/documentation/src/docs/asciidocAdd expandable/collapsable TOC
https://github.com/asciidoctor/asciidoctor/issues/699copyfiles
https://www.npmjs.com/package/copyfilesAsciidoctor Gradle Examples
https://asciidoctor.github.io/asciidoctor-gradle-examples/- 今回の記事とは直接関係がありませんが、見つけたのでメモとして書いておきます。
目次
- document header に
:toc: left
、:toclevels: 4
を追加して TOC を表示させる - Tocbot を導入して TOC が自動展開される+参照中の section が分かるようにする
- AsciiDoc Language Documentation、Asciidoctor Documentation と同じ TOC の実現は次回へ
手順
document header に :toc: left
、:toclevels: 4
を追加して TOC を表示させる
Spring Boot Reference Documentation の adoc ファイルを参考に document header を追加する で追加しなかった :toc: left
、:toclevels: 4
を document header に追加して TOC を自動生成させてみます。
src/docs/asciidoc/02_include/index.adoc を以下のように変更します。
= include directive で章毎にファイルを分けてみる :lang: ja :doctype: book :idprefix: :idseparator: - :toc: left :toclevels: 4 :tabsize: 4 :sectanchors: :sectnums: :icons: font :hide-uri-scheme: :docinfo: shared,private :docinfodir: ../../docinfo include::01.adoc[leveloffset=+1] include::02.adoc[leveloffset=+1]
- 以下の2行を追加します。
:toc: left
:toclevels: 4
asciidoctor タスクを実行して html を表示させてみると左側に TOC が表示されましたが、TOC は展開済みの状態で、下にスクロールした時に TOC が自動的に展開されて現在見ている section が分かるようにはなっていませんでした。:toc:
を追加するだけでは実現できないようです。
Tocbot を導入して TOC が自動展開される+参照中の section が分かるようにする
TOC を自動的に展開して現在見ている section が分かるようにする方法を調べたところ、JUnit 5 のドキュメントのソース https://github.com/junit-team/junit5/tree/main/documentation/src/docs/asciidoc で Tocbot を使って実現していることが分かりました。
asciidoctor の GitHub にも Add expandable/collapsable TOC の Issue がありました。
同じようにすれば実現できそうです。
npm init -y
を実行する
Tocbot のファイルは npm でダウンロードするので、まずは npm init -y
を実行します(Node.js、npm のインストールは以下の記事参照)。
- Spring Boot + npm + Geb で入力フォームを作ってテストする ( その4 )( nodist + Node.js のインストール )
- Spring Boot + npm + Geb で入力フォームを作ってテストする ( その80 )( nodist を 0.8.8 → 0.9.1 へ、Node.js を 8.11.4 → 10.15.3 へ、npm を 6.2.0-next.1 → 6.9.0 へバージョンアップする )
- Spring Boot + npm + Geb で入力フォームを作ってテストする ( その85 )( Node.js を 10.15.3 → 12.16.3 へ、npm を 6.9.0 → 6.14.5 へバージョンアップする )
npm install --save tocbot
を実行する
npm install --save tocbot
を実行して Tocbot のファイルをダウンロードします。
node_modules ディレクトリが作成されたので .gitignore に無視するよう設定を追加します。
# Gradle .gradle/ build/ # Intellij project files *.iml *.ipr *.iws .idea/ # Node.js, npm node_modules/ npm-debug.log
src/docs/asciidoc/js ディレクトリを作成して Tocbot の js ファイルをコピーする
npm scripts でファイルをコピーするのに以前は cpx をインストールして使っていましたが、最近使われているモジュールを調べてみるとダウンロード数が多いのは ncp らしいです。
copy vs copyfiles vs cpx vs ncp vs npm-build-tools というサイトを見つけました。ncp は最後のリリースは 6年前ですが圧倒的にダウンロード数が多く、次の copyfiles は最後のリリースが2ヶ月前ですが ncp よりダウンロード数は少ない模様。
今回は copyfiles をインストールして使うことにします。また rimraf、npm-run-all もインストールしたいので、以下のコマンドを実行します。
npm install --save-dev copyfiles
npm install --save-dev rimraf
npm install --save-dev npm-run-all
package.json に postinstall
と copy:tocbot
の npm scripts を追加してから、
.......... "scripts": { "postinstall": "run-s copy:tocbot", "copy:tocbot": "copyfiles -f node_modules/tocbot/dist/*.js src/docs/asciidoc/js" }, ..........
npm ci
コマンドを実行すると、
src/docs/asciidoc/js ディレクトリが作成されて、その下に tocbot.js、tocbot.min.js がコピーされます。
asciidoctor タスク実行時に js ファイルが build ディレクトリにコピーされるようにする
build.gradle を以下のように変更します。
.......... asciidoctor { sourceDir file("src/docs/asciidoc") baseDirFollowsSourceFile() sources { include "**/index.adoc" } resources { from("${sourceDir}") { include "**/*.png", "**/*.js" } } } ..........
- asciidoctor block の resources の中に
"**/*.js"
を追加します。
docinfo.html、docinfo-footer.html に Tocbot を使用するために必要なコードを記述する
Add expandable/collapsable TOC に docinfo.html、docinfo-footer.html に記述するサンプルがありますので、それを流用して記述します(ほとんどコピーですが流用元の URL の追加と Tocbot の最新版 4.12.1 を使うための設定の追加をしています)。
まずは docinfo.html から。
<style> .......... /* Source: https://github.com/asciidoctor/asciidoctor/issues/699#issuecomment-321066006 */ #tocbot a.toc-link.node-name--H1{ font-style: italic } @media screen{ #tocbot > ul.toc-list{ margin-bottom: 0.5em; margin-left: 0.125em } #tocbot ul.sectlevel0, #tocbot a.toc-link.node-name--H1 + ul{ padding-left: 0 } #tocbot a.toc-link{ height:100% } .is-collapsible{ max-height:3000px; overflow:hidden; } .is-collapsed{ max-height:0 } .is-active-link{ font-weight:700 } } @media print{ #tocbot a.toc-link.node-name--H4{ display:none } } </style>
次に docinfo-footer.html。ファイル自体がないので src/docs/docinfo ディレクトリの下に新規作成してから以下の内容を記述します。こちらは Ctrl+Alt+L でフォーマットした後、先頭のコードを <script src="/assets/js/tocbot.js"></script>
→ <script src="../js/tocbot.min.js"></script>
へ、tocbot のバージョン番号を 3.0.2
→ 4.12.1
へ変更しています。
<!--Source: https://github.com/asciidoctor/asciidoctor/issues/699#issuecomment-321066006--> <script src="../js/tocbot.min.js"></script> <script> /* Tocbot dynamic TOC, works with tocbot 4.12.1 */ var oldtoc = document.getElementById('toctitle').nextElementSibling; var newtoc = document.createElement('div'); newtoc.setAttribute('id', 'tocbot'); newtoc.setAttribute('class', 'js-toc'); oldtoc.parentNode.replaceChild(newtoc, oldtoc); tocbot.init({ contentSelector: '#content', headingSelector: 'h1, h2, h3, h4', smoothScroll: false }); var handleTocOnResize = function () { var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; if (width < 768) { tocbot.refresh({ contentSelector: '#content', headingSelector: 'h1, h2, h3, h4', collapseDepth: 6, activeLinkClass: 'ignoreactive', throttleTimeout: 1000, smoothScroll: false }); } else { tocbot.refresh({ contentSelector: '#content', headingSelector: 'h1, h2, h3, h4', smoothScroll: false }); } }; window.addEventListener('resize', handleTocOnResize); handleTocOnResize(); </script>
asciidoctor タスクを実行して動作確認する
asciidoctor タスクを実行すると BUILD SUCCESSFUL のメッセージが出力されて、
build/docs/asciidoc/js が作成されて、その下に tocbot.js がコピーされており、
index.html を開くと左側に TOC が表示されて、下にスクロールすると TOC が自動的に展開されて現在見ている section が分かるようになりました。
実現できた!と思ったのですが、よく見ると一番上位の階層になぜか番号が余計に付いています。。。
http://tscanlin.github.io/tocbot/ の「API」-「Options」を見ると orderedList
という項目があり orderedList can be set to false to generate unordered lists (ul) instead of ordered lists (ol)
との記述がありました。おそらくこれを false に設定すれば番号は付かなくなるはず。
src/docs/docinfo/docinfo-footer.html を以下のように変更します。
<!--Source: https://github.com/asciidoctor/asciidoctor/issues/699#issuecomment-321066006--> <script src="../js/tocbot.min.js"></script> <script> /* Tocbot dynamic TOC, works with tocbot 4.12.1 */ var oldtoc = document.getElementById('toctitle').nextElementSibling; var newtoc = document.createElement('div'); newtoc.setAttribute('id', 'tocbot'); newtoc.setAttribute('class', 'js-toc'); oldtoc.parentNode.replaceChild(newtoc, oldtoc); tocbot.init({ contentSelector: '#content', headingSelector: 'h1, h2, h3, h4', smoothScroll: false }); var handleTocOnResize = function () { var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; if (width < 768) { tocbot.refresh({ contentSelector: '#content', headingSelector: 'h1, h2, h3, h4', collapseDepth: 6, activeLinkClass: 'ignoreactive', throttleTimeout: 1000, smoothScroll: false, orderedList: false }); } else { tocbot.refresh({ contentSelector: '#content', headingSelector: 'h1, h2, h3, h4', smoothScroll: false, orderedList: false }); } }; window.addEventListener('resize', handleTocOnResize); handleTocOnResize(); </script>
tocbot.refresh({ ... });
を呼び出しているところ(2ヶ所)にorderedList: false
を追加しました。
asciidoctor タスクを実行して index.html を開くと、今度は番号が付いていませんでした。
AsciiDoc Language Documentation、Asciidoctor Documentation と同じ TOC の実現は次回へ
AsciiDoc Language Documentation のソース https://github.com/asciidoctor/asciidoc-docs の記述を見るとと The documentation site is built using Antora.
の記述があり、Antora で構築されているとのこと。
Antora で検索すると以下のサイトが見つかりました。
今回はここで区切って Antora を使用するのは次回にします。
履歴
2021/01/16
初版発行。