Home Adding a page table of contents to mdBook
Post
Cancel

Adding a page table of contents to mdBook

Today, I describe how I added a page table of contents to my mdBook projects.

mdBook is an amazing little command-line tool written in Rust that lets you create a “book” from a collection of markdown files. It took inspiration from Gitbook, a platform for creating documentation for APIs and software.

Over the past few years, I have used mdBook in some of my projects to provide user guides and documentation for other developers. Notably, my CommandAPI documentation is compiled using mdBook. However, one thing I noticed with mdBook is that it is very annoying to read a page with lots of content - it is difficult to find exactly what you need. In other words, if each page had a table of contents, it would make navigation even more intuitive.

And many other documentation sources have a table of contents for pages. For example, the Visual Studio Code documentation has a sidebar on the right called In This Article which outlines the contents of the page. Other examples include the Redux documentation, or documentation created using Docusaurus.

So, with this idea in mind, I search the mdBook issues page to see if anyone else had this same idea. I ended up finding an issue from 2015, where someone requested a page table of contents. Unfortunately, the issue in 2019 due to being too old and the fact that the opinions of the issue may have changed in those 4 years. As a result, I opened my own issue reiterating over the main points and voicing ideas of potential implementations. It was just going to be a matter of time before the issue took off, so I waited.

And waited.

And waited.

Two weeks later, I find out that nobody has even begun to discuss it! A developer from another repository was glad to find that I opened the issue, but the point is no progress had been made in 2 weeks. Like, I understand that as a developer you are probably busy, but at least have the courtesy to respond! It was at this moment I realised I should probably try and add it myself.

Research

As with any mini-project, research comes first. I search around for other solutions but wasn’t able to find anything that specifically implements a page table of contents sidebar. That is until I stumbled upon a Stack Overflow question: Highlight active menu items as page scrolls divs (Sidebar onscroll menu). After looking at the top result, it appeared to have exactly what I was looking for! A sidebar that updates when you scroll. Unfortunately, their code was written in jQuery and mdBook does not natively come with jQuery. It would seem bloaty to include jQuery just to have a sidebar, right?

In my research to find a way to convert the jQuery code to straight up plain JavaScript, I come across a website called You might not need jQuery. It contains a collection of code snippets written in jQuery with the corresponding code in JavaScript that does the same thing. Fantastic!

Coding

With the research done, I seem to have all of the elements needed to create the mdBook sidebar. I convert the jQuery code into JavaScript and add a div to the handlebars template file index.hbs to include the sidebar on the page. I also write a sneaky bit of CSS that used media queries to display the sidebar only when the screen is big enough. Since I had never used media queries (I had only known of them prior to this mini-project), I had to figure out how to use them. Luckily, my friend happens to have a GitHub Gist with a responsive CSS template with media queries! Using this, I am able to make sure that the sidebar only appears when necessary and if there is enough room on the screen:

sidebar

Conclusion

Overall, I was able to implement a table of contents for individual pages successfully - albeit clunky and not perfect. Scrolling sometimes messes up and the sidebar sometimes doesn’t link to headers properly, but it works well enough to suit my needs. I created a repository for anyone else that wants to use my temporary solution - hopefully the developers at mdBook can implement this feature properly in the future.

This post is licensed under CC BY 4.0 by the author.

Making a better programming language

Simplifying Bukkit ProxiedCommandSenders