In a companion post we talked about how to create a custom theme for Sphinx, like the one we made for the new NetEye online user guide.
Sometimes just a basic customization is not enough and you want to create something much more advanced. In this article, we’ll look at some more detailed custom parts.
By default, the home page in a Sphinx project is represented by the index.rst
file which can contain for instance a title and a ToC tree directive.
Certainly for a basic home page, having just a default index.rst
is enough, but in our case we wanted to add some HTML code to create a richer landing page.
Anyone can achieve the same type of result simply by following these steps:
1. In the custom theme structure, create an index.html
file inside a folder called templates
/ like this:
neteye
├── footer.html
├── globaltoc.html
├── layout.html
├── templates
│ └── index.html
└── theme.conf
2. Customize the new index page:
The index.html
is basically like the layout.html
page. We can change any block we want. For example, to avoid starting from scratch we can extend our theme’s layout.html
file:
{% extends "layout.html" %}
Then we can create a CSS file for the landing page and link to it:
{% set css_files = css_files + ['_static/neteye-home.css'] %}
At this point, say we’d like to add a banner, so let’s override the sidebar1
block:
{%- block sidebar1 %}
<div id="menu" class="col-md-3 col-xl-2">
{{ sidebar() }}
</div>
<div id="content" class="col">
<div id="index-banner" class="jumbotron jumbotron-fluid">
<h1 class="display-4">{{ title|striptags|e }}</h1>
<p>System Management with NetEye is your answer to the challenges of digital transformation.</p>
</div>
<div class="row" id="document">
<div class="col">
{% endblock %}
And we want to remove the right column with the local ToC:
{% block leftColumn %}{% endblock %}
3. At this point the only thing missing is to point to index.html
in the conf.py
file:
html_additional_pages = {'index': 'index.html'}
Another advanced section that we want in our documentation is a local ToC that highlights the current chapter, and that changes as the user scrolls.
To build this element, Bootstrap can help us with its scroll spy functionality.
Unfortunately, the default ToC on Sphinx is made up of ul
and li
elements, while Bootstrap supports the scroll spy only on the nav
element or group list. It’s clear that we need to replace the HTML structure of the local ToC:
localtoc.html
filenav
component. For this purpose we decided to use the replace function:{% set tocNav = toc
| replace("<li>", "")
| replace("</li>", "")
| replace("<ul>", "<nav class='nav flex-column'>")
| replace("</ul>", "</nav>")
| replace("<a", "<a class='nav-link' ")%}
3. At this point the variable tocNav
contains the right HTML structure, so the next step is to display it:
<div id="local-toc-nav" class="sticky-top">
{{tocNav}}
</div>
4. The last step is to include the localtoc.html
file inside the layout.html
file:
{%- include "localtoc.html" %}
In our user guide we wanted to have the copy button next to each code block but without creating or using a Sphinx plugin, because we needed to have more control around this functionality. We decided to do it via JavaScript:
neteye.js
file and we linked it to the layout.html
file by extending the block script:{%- block scripts %}
<script src="{{pathto('_static/neteye.js', 1)|e}}" async></script>
{{ super() }}
{%- endblock %}
2. Then in the JS file, we injected the necessary HTML for the button into each code block:
var codeHighlightNodes = $('.document .highlight');
if (codeHighlightNodes.length === 0) {
return;
}
codeHighlightNodes.prepend('<div class="copy"></div>');
3. In the CSS file we added the style, for example we added the copy icon like this:
.document .highlight .copy {
background-image: url('./icons/copy.svg');
border-left: solid 1px #f2f2f2;
}
4. And finally in the JS file we create the click event:
function copyToClipboard(textToCopy) {
document.addEventListener('copy', function(e) {
e.clipboardData.setData('text/plain', textToCopy);
e.preventDefault();
}, true);
document.execCommand('copy');
}
/* Copy */
$('.document .highlight .copy').click((e) => {
var el = $(e.target).parent().find('pre');
if (el.length === 0) {
return;
}
var textToCopy = el.text();
copyToClipboard(textToCopy);
});
Last but not least, we want to cover layout responsiveness in this article.
It’s very important to build a responsive layout that fits the large variety of device screen sizes out there.
Fortunately, Bootstrap helps us a lot here, for example with a powerful grid system and with some display helpers.
Most of the time it’s enough to put the various responsive classes into the HTML code and write some CSS. For this purpose we suggest keeping in mind different screen sizes during the development of the HTML to avoid having to adapt it later, where you risking having to rewrite your code.
From our experience, we have found that Sphinx is a truly powerful and flexible tool. It’s suitable both for creating basic documentation thanks to the presence of many themes already available, and for creating a more advanced product thanks to the possibility of easily extending and customizing it.
We hope this article will help you create spectacular documentation, so give it a try yourself!