Sphinx docs: How to activate tabs for your OS

On the Python Developer’s Guide and Pillow documentation we have some pages with tabs for different operating systems:

It’s possible to add some JavaScript so that the matching tab is activated based on the visitor’s operating system.

Here’s how!

Sphinx Inline Tabs

First add the Sphinx Inline Tabs extension to your docs’ requirements.txt:

# requirements.txt
sphinx-inline-tabs>=2023.4.21
# requirements.txt
sphinx-inline-tabs>=2023.4.21
# requirements.txt sphinx-inline-tabs>=2023.4.21

Enter fullscreen mode Exit fullscreen mode

JavaScript

Next, add activate_tab.js to your _static/ directory:

<span>// activate_tab.js</span>
<span>// Based on https://stackoverflow.com/a/38241481/724176</span>
<span>function</span> <span>getOS</span><span>()</span> <span>{</span>
<span>const</span> <span>userAgent</span> <span>=</span> <span>window</span><span>.</span><span>navigator</span><span>.</span><span>userAgent</span><span>,</span>
<span>platform</span> <span>=</span>
<span>window</span><span>.</span><span>navigator</span><span>?.</span><span>userAgentData</span><span>?.</span><span>platform</span> <span>||</span> <span>window</span><span>.</span><span>navigator</span><span>.</span><span>platform</span><span>,</span>
<span>macosPlatforms</span> <span>=</span> <span>[</span><span>"</span><span>macOS</span><span>"</span><span>,</span> <span>"</span><span>Macintosh</span><span>"</span><span>,</span> <span>"</span><span>MacIntel</span><span>"</span><span>,</span> <span>"</span><span>MacPPC</span><span>"</span><span>,</span> <span>"</span><span>Mac68K</span><span>"</span><span>],</span>
<span>windowsPlatforms</span> <span>=</span> <span>[</span><span>"</span><span>Win32</span><span>"</span><span>,</span> <span>"</span><span>Win64</span><span>"</span><span>,</span> <span>"</span><span>Windows</span><span>"</span><span>,</span> <span>"</span><span>WinCE</span><span>"</span><span>],</span>
<span>iosPlatforms</span> <span>=</span> <span>[</span><span>"</span><span>iPhone</span><span>"</span><span>,</span> <span>"</span><span>iPad</span><span>"</span><span>,</span> <span>"</span><span>iPod</span><span>"</span><span>];</span>
<span>if </span><span>(</span><span>macosPlatforms</span><span>.</span><span>includes</span><span>(</span><span>platform</span><span>))</span> <span>{</span>
<span>return</span> <span>"</span><span>macOS</span><span>"</span><span>;</span>
<span>}</span> <span>else</span> <span>if </span><span>(</span><span>iosPlatforms</span><span>.</span><span>includes</span><span>(</span><span>platform</span><span>))</span> <span>{</span>
<span>return</span> <span>"</span><span>iOS</span><span>"</span><span>;</span>
<span>}</span> <span>else</span> <span>if </span><span>(</span><span>windowsPlatforms</span><span>.</span><span>includes</span><span>(</span><span>platform</span><span>))</span> <span>{</span>
<span>return</span> <span>"</span><span>Windows</span><span>"</span><span>;</span>
<span>}</span> <span>else</span> <span>if </span><span>(</span><span>/Android/</span><span>.</span><span>test</span><span>(</span><span>userAgent</span><span>))</span> <span>{</span>
<span>return</span> <span>"</span><span>Android</span><span>"</span><span>;</span>
<span>}</span> <span>else</span> <span>if </span><span>(</span><span>/Linux/</span><span>.</span><span>test</span><span>(</span><span>platform</span><span>))</span> <span>{</span>
<span>return</span> <span>"</span><span>Unix</span><span>"</span><span>;</span>
<span>}</span>
<span>return</span> <span>"</span><span>unknown</span><span>"</span><span>;</span>
<span>}</span>
<span>function</span> <span>activateTab</span><span>(</span><span>tabName</span><span>)</span> <span>{</span>
<span>// Find all label elements containing the specified tab name</span>
<span>const</span> <span>labels</span> <span>=</span> <span>document</span><span>.</span><span>querySelectorAll</span><span>(</span><span>"</span><span>.tab-label</span><span>"</span><span>);</span>
<span>labels</span><span>.</span><span>forEach</span><span>((</span><span>label</span><span>)</span> <span>=></span> <span>{</span>
<span>if </span><span>(</span><span>label</span><span>.</span><span>textContent</span><span>.</span><span>includes</span><span>(</span><span>tabName</span><span>))</span> <span>{</span>
<span>// Find the associated input element using the 'for' attribute</span>
<span>const</span> <span>tabInputId</span> <span>=</span> <span>label</span><span>.</span><span>getAttribute</span><span>(</span><span>"</span><span>for</span><span>"</span><span>);</span>
<span>const</span> <span>tabInput</span> <span>=</span> <span>document</span><span>.</span><span>getElementById</span><span>(</span><span>tabInputId</span><span>);</span>
<span>// Check if the input element exists before attempting to set the "checked" attribute</span>
<span>if </span><span>(</span><span>tabInput</span><span>)</span> <span>{</span>
<span>// Activate the tab by setting its "checked" attribute to true</span>
<span>tabInput</span><span>.</span><span>checked</span> <span>=</span> <span>true</span><span>;</span>
<span>}</span>
<span>}</span>
<span>});</span>
<span>}</span>
<span>// activate_tab.js</span>
<span>// Based on https://stackoverflow.com/a/38241481/724176</span>
<span>function</span> <span>getOS</span><span>()</span> <span>{</span>
  <span>const</span> <span>userAgent</span> <span>=</span> <span>window</span><span>.</span><span>navigator</span><span>.</span><span>userAgent</span><span>,</span>
    <span>platform</span> <span>=</span>
      <span>window</span><span>.</span><span>navigator</span><span>?.</span><span>userAgentData</span><span>?.</span><span>platform</span> <span>||</span> <span>window</span><span>.</span><span>navigator</span><span>.</span><span>platform</span><span>,</span>
    <span>macosPlatforms</span> <span>=</span> <span>[</span><span>"</span><span>macOS</span><span>"</span><span>,</span> <span>"</span><span>Macintosh</span><span>"</span><span>,</span> <span>"</span><span>MacIntel</span><span>"</span><span>,</span> <span>"</span><span>MacPPC</span><span>"</span><span>,</span> <span>"</span><span>Mac68K</span><span>"</span><span>],</span>
    <span>windowsPlatforms</span> <span>=</span> <span>[</span><span>"</span><span>Win32</span><span>"</span><span>,</span> <span>"</span><span>Win64</span><span>"</span><span>,</span> <span>"</span><span>Windows</span><span>"</span><span>,</span> <span>"</span><span>WinCE</span><span>"</span><span>],</span>
    <span>iosPlatforms</span> <span>=</span> <span>[</span><span>"</span><span>iPhone</span><span>"</span><span>,</span> <span>"</span><span>iPad</span><span>"</span><span>,</span> <span>"</span><span>iPod</span><span>"</span><span>];</span>

  <span>if </span><span>(</span><span>macosPlatforms</span><span>.</span><span>includes</span><span>(</span><span>platform</span><span>))</span> <span>{</span>
    <span>return</span> <span>"</span><span>macOS</span><span>"</span><span>;</span>
  <span>}</span> <span>else</span> <span>if </span><span>(</span><span>iosPlatforms</span><span>.</span><span>includes</span><span>(</span><span>platform</span><span>))</span> <span>{</span>
    <span>return</span> <span>"</span><span>iOS</span><span>"</span><span>;</span>
  <span>}</span> <span>else</span> <span>if </span><span>(</span><span>windowsPlatforms</span><span>.</span><span>includes</span><span>(</span><span>platform</span><span>))</span> <span>{</span>
    <span>return</span> <span>"</span><span>Windows</span><span>"</span><span>;</span>
  <span>}</span> <span>else</span> <span>if </span><span>(</span><span>/Android/</span><span>.</span><span>test</span><span>(</span><span>userAgent</span><span>))</span> <span>{</span>
    <span>return</span> <span>"</span><span>Android</span><span>"</span><span>;</span>
  <span>}</span> <span>else</span> <span>if </span><span>(</span><span>/Linux/</span><span>.</span><span>test</span><span>(</span><span>platform</span><span>))</span> <span>{</span>
    <span>return</span> <span>"</span><span>Unix</span><span>"</span><span>;</span>
  <span>}</span>

  <span>return</span> <span>"</span><span>unknown</span><span>"</span><span>;</span>
<span>}</span>

<span>function</span> <span>activateTab</span><span>(</span><span>tabName</span><span>)</span> <span>{</span>
  <span>// Find all label elements containing the specified tab name</span>
  <span>const</span> <span>labels</span> <span>=</span> <span>document</span><span>.</span><span>querySelectorAll</span><span>(</span><span>"</span><span>.tab-label</span><span>"</span><span>);</span>

  <span>labels</span><span>.</span><span>forEach</span><span>((</span><span>label</span><span>)</span> <span>=></span> <span>{</span>
    <span>if </span><span>(</span><span>label</span><span>.</span><span>textContent</span><span>.</span><span>includes</span><span>(</span><span>tabName</span><span>))</span> <span>{</span>
      <span>// Find the associated input element using the 'for' attribute</span>
      <span>const</span> <span>tabInputId</span> <span>=</span> <span>label</span><span>.</span><span>getAttribute</span><span>(</span><span>"</span><span>for</span><span>"</span><span>);</span>
      <span>const</span> <span>tabInput</span> <span>=</span> <span>document</span><span>.</span><span>getElementById</span><span>(</span><span>tabInputId</span><span>);</span>

      <span>// Check if the input element exists before attempting to set the "checked" attribute</span>
      <span>if </span><span>(</span><span>tabInput</span><span>)</span> <span>{</span>
        <span>// Activate the tab by setting its "checked" attribute to true</span>
        <span>tabInput</span><span>.</span><span>checked</span> <span>=</span> <span>true</span><span>;</span>
      <span>}</span>
    <span>}</span>
  <span>});</span>
<span>}</span>
// activate_tab.js // Based on https://stackoverflow.com/a/38241481/724176 function getOS() { const userAgent = window.navigator.userAgent, platform = window.navigator?.userAgentData?.platform || window.navigator.platform, macosPlatforms = ["macOS", "Macintosh", "MacIntel", "MacPPC", "Mac68K"], windowsPlatforms = ["Win32", "Win64", "Windows", "WinCE"], iosPlatforms = ["iPhone", "iPad", "iPod"]; if (macosPlatforms.includes(platform)) { return "macOS"; } else if (iosPlatforms.includes(platform)) { return "iOS"; } else if (windowsPlatforms.includes(platform)) { return "Windows"; } else if (/Android/.test(userAgent)) { return "Android"; } else if (/Linux/.test(platform)) { return "Unix"; } return "unknown"; } function activateTab(tabName) { // Find all label elements containing the specified tab name const labels = document.querySelectorAll(".tab-label"); labels.forEach((label) => { if (label.textContent.includes(tabName)) { // Find the associated input element using the 'for' attribute const tabInputId = label.getAttribute("for"); const tabInput = document.getElementById(tabInputId); // Check if the input element exists before attempting to set the "checked" attribute if (tabInput) { // Activate the tab by setting its "checked" attribute to true tabInput.checked = true; } } }); }

Enter fullscreen mode Exit fullscreen mode

conf.py

Add the extension and JavaScript to your conf.py:

<span># conf.py </span><span>extensions</span> <span>=</span> <span>[</span>
<span>"</span><span>sphinx_inline_tabs</span><span>"</span><span>,</span>
<span>]</span>
<span>html_js_files</span> <span>=</span> <span>[</span>
<span>"</span><span>activate_tab.js</span><span>"</span><span>,</span>
<span>]</span>
<span># conf.py </span><span>extensions</span> <span>=</span> <span>[</span>
    <span>"</span><span>sphinx_inline_tabs</span><span>"</span><span>,</span>
<span>]</span>

<span>html_js_files</span> <span>=</span> <span>[</span>
    <span>"</span><span>activate_tab.js</span><span>"</span><span>,</span>
<span>]</span>
# conf.py extensions = [ "sphinx_inline_tabs", ] html_js_files = [ "activate_tab.js", ]

Enter fullscreen mode Exit fullscreen mode

reStructuredText

Almost there!

Add tabs to the reStructuredText files.

For example, here we have three different commands; one for Unix, one for macOS, and one for Windows:

.. tab:: Unix
.. code-block:: shell
./python -m test -h
.. tab:: macOS
.. code-block:: shell
./python.exe -m test -h
.. tab:: Windows
.. code-block:: dosbatch
.\python.bat -m test -h
.. tab:: Unix

    .. code-block:: shell

        ./python -m test -h

.. tab:: macOS

    .. code-block:: shell

        ./python.exe -m test -h

.. tab:: Windows

    .. code-block:: dosbatch

        .\python.bat -m test -h
.. tab:: Unix .. code-block:: shell ./python -m test -h .. tab:: macOS .. code-block:: shell ./python.exe -m test -h .. tab:: Windows .. code-block:: dosbatch .\python.bat -m test -h

Enter fullscreen mode Exit fullscreen mode

Finally, add the JavaScript to the same reST page to activate the correct tab:

.. raw:: html
<script>
document.addEventListener('DOMContentLoaded', function() {
activateTab(getOS());
});
</script>
.. raw:: html

    <script>
    document.addEventListener('DOMContentLoaded', function() {
      activateTab(getOS());
    });
    </script>
.. raw:: html <script> document.addEventListener('DOMContentLoaded', function() { activateTab(getOS()); }); </script>

Enter fullscreen mode Exit fullscreen mode

You can see the results here. When the page loads, the browser finds the browser name, and activates the tabs with a matching name.

If you have many sets of tabs on a page, the corresponding OS tab will be activated for all. And if you click on another OS tab, all the others with the same name are activated.

Happy tabbing!


Header photo: “The Great Pyramid and the Sphinx” by National Galleries of Scotland, with no known copyright restrictions.

原文链接:Sphinx docs: How to activate tabs for your OS

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享
Aim for the moon. If you miss, you may hit a star.
把月亮作为你的目标。如果你没打中,也许你还能打中星星
评论 抢沙发

请登录后发表评论

    暂无评论内容