Sphinx, reStructuredText show/hide code snippets
Asked Answered
L

10

34

I've been documenting a software package using Sphinx and reStructuredText.

Within my documents, there are some long code snippets. I want to be able to have them hidden as default, with a little "Show/Hide" button that would expand them (Example).

Is there a standard way to do that?

Looney answered 16/3, 2010 at 13:19 Comment(0)
R
6

I think the easiest way to do this would be to create a custom Sphinx theme in which you tell certain html elements to have this functionality. A little JQuery would go a long way here.

If, however you want to be able to specify this in your reStructuredText markup, you would need to either

  • get such a thing included in Sphinx itself or
  • implement it in a Sphinx/docutils extension...and then create a Sphinx theme which knew about this functionality.

This would be a bit more work, but would give you more flexibility.

Rawalpindi answered 1/4, 2010 at 22:49 Comment(1)
Can you share how and what you've develop for show/hide facility on sphinx documentation?Dc
F
52

You don't need a custom theme. Use the built-in directive container that allows you to add custom css-classes to blocks and override the existsting theme to add some javascript to add the show/hide-functionality.

This is _templates/page.html:

{% extends "!page.html" %}

{% block footer %}
 <script type="text/javascript">
    $(document).ready(function() {
        $(".toggle > *").hide();
        $(".toggle .header").show();
        $(".toggle .header").click(function() {
            $(this).parent().children().not(".header").toggle(400);
            $(this).parent().children(".header").toggleClass("open");
        })
    });
</script>
{% endblock %}

This is _static/custom.css:

.toggle .header {
    display: block;
    clear: both;
}

.toggle .header:after {
    content: " ▶";
}

.toggle .header.open:after {
    content: " ▼";
}

This is added to conf.py:

def setup(app):
    app.add_css_file('custom.css')

Now you can show/hide a block of code.

.. container:: toggle

    .. container:: header

        **Show/Hide Code**

    .. code-block:: xml
       :linenos:

       from plone import api
       ...

I use something very similar for exercises here: https://training.plone.org/5/mastering-plone/about_mastering.html#exercises

Finnougric answered 28/8, 2014 at 8:1 Comment(8)
Beautiful! Would be nice if the toggle solutions showed up as clickable links in vimperator/cvim/pentadactyl though.Ifill
I think that using ▶ and ▼ makes it more intuitive to use. (See Confluence as an example). Get the unicode values here.Domoniquedomph
This snippet {% set css_files = css_files + ["_static/custom.css"] %} results in a Sphinx warning: RemovedinSphinx20Warning: builder.css_files is deprecated. Please use app.add_stylesheet() instead. See this answer for a work around.Domoniquedomph
Would you mind posting the detailed instructions for the example from your plone course, which is using an admonition?Actinism
How to get the arrow in the same line as the header?Angeliqueangelis
@Angeliqueangelis to keep the arrow on the same line you can simply set .toggle .header {display: inline;} in css fileVerlinevermeer
@Verlinevermeer Unfortunately, that doesn't change anything for me either. The arrow is still in the next line.Angeliqueangelis
Change .toggle .header:after to .toggle .header p:after and .toggle .header.open:after to .toggle .header.open p:after to avoid this issue @AngeliqueangelisElbrus
R
26

You can use the built-in HTML collapsible details tag by wrapping the code in two raw HTML directives

.. raw:: html

   <details>
   <summary><a>big code</a></summary>

.. code-block:: python

   lots_of_code = "this text block"

.. raw:: html

   </details>

Produces:

<details>
<summary><a>big code</a></summary>
<pre>lots_of_code = "this text block"</pre>
</details>
Reproof answered 25/2, 2020 at 11:55 Comment(1)
Since version 0.20 (2023-05-09), the Docutils HTML5 writer supports "details lists" which may be used instead of "raw" HTML <details>.Meteoritics
U
7

There is a very simplistic extension providing exactly that feature: https://github.com/scopatz/hiddencode

It works rather well for me.

Underwing answered 11/9, 2018 at 23:25 Comment(0)
R
6

I think the easiest way to do this would be to create a custom Sphinx theme in which you tell certain html elements to have this functionality. A little JQuery would go a long way here.

If, however you want to be able to specify this in your reStructuredText markup, you would need to either

  • get such a thing included in Sphinx itself or
  • implement it in a Sphinx/docutils extension...and then create a Sphinx theme which knew about this functionality.

This would be a bit more work, but would give you more flexibility.

Rawalpindi answered 1/4, 2010 at 22:49 Comment(1)
Can you share how and what you've develop for show/hide facility on sphinx documentation?Dc
F
5

The cloud sphinx theme has custom directive html-toggle that provides toggleable sections. To quote from their web page:

You can mark sections with .. rst-class:: html-toggle, which will make the section default to being collapsed under html, with a “show section” toggle link to the right of the title.

Here is a link to their test demonstration page.

Faires answered 12/9, 2014 at 16:49 Comment(0)
C
3

sphinx-togglebutton

Looks like a new sphinx extension has been made to do just this since this question has been answered.


Run: pip install sphinx-togglebutton

Add to conf.py

extensions = [
...
'sphinx_togglebutton'
...
]

In rst source file:

.. admonition:: Show/Hide
  :class: dropdown

  hidden message
Conyers answered 18/10, 2022 at 16:33 Comment(0)
E
2

since none of the above methods seem to work for me, here's how I solved it in the end:

  1. create a file substitutions.rst in your source-directory with the following content:

    .. |toggleStart| raw:: html
    
       <details>
       <summary><a> the title of the collapse-block </a></summary>
    
    .. |toggleEnd| raw:: html
    
       </details>
       <br/>
    
  2. add the following line at the beginning of every file you want to use add collapsible blocks

    ..include:: substitutions.rst
    
  3. now, to make a part of the code collapsible simply use:

    |toggleStart|
    
    the text you want to collapse
    ..code-block:: python 
        x=1
    
    |toggleEnd|
    
Exurb answered 20/11, 2021 at 10:40 Comment(2)
This is basically the same as https://mcmap.net/q/433837/-sphinx-restructuredtext-show-hide-code-snippetsCatabolite
@Catabolite yes It is... but I thought using substitutions makes it a bit more compact and readable (especially if you have a lot of collapsible segments with the same title-text)Exurb
C
1

Another option is the dropdown directive in the sphinx-design extension. From the docs:

  1. Install sphinx-design
pip install sphinx-design
  1. Add the extension to conf.py in the extensions list
extensions = ["sphinx_design"]
  1. Use the dropdown directive in your rst file:
.. dropdown::

    Dropdown content
Carbine answered 9/11, 2022 at 21:20 Comment(0)
M
0

Since version 0.20 (2023-05-09), the Docutils HTML5 writer supports details disclosure elements.

.. rst-class:: details

big code block's caption
    .. code:: python

        lots_of_code = "this text block"

produces

<div class="details">
<details>
<summary>big code block’s caption</summary>
<pre class="code literal-block"><code>lots_of_code = &quot;this text block&quot;</code></pre>
</details>
</div>
Meteoritics answered 26/11, 2023 at 21:41 Comment(0)
E
0

TL;DR

You can use jsphinx for this. Check the demo/examples.

Methodology is well explained in the documentation.

Advantages over existing solutions:

  • Your code sippets are always complete. You can test them.
  • It's a JavaScript library. It adds a very small footprint to your existing documentation.
Ediva answered 15/5 at 7:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.