Coverage for pyquickhelper/sphinxext/sphinx_collapse_extension.py: 96%
75 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-03 02:21 +0200
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-03 02:21 +0200
1# -*- coding: utf-8 -*-
2"""
3@file
4@brief Defines a sphinx extension to hide / unhide
5section of the page.
6"""
7import logging
8from docutils import nodes
9from docutils.parsers.rst import directives
10import sphinx
11from docutils.parsers.rst import Directive
12from sphinx.util.nodes import nested_parse_with_titles
13from .sphinx_ext_helper import sphinx_lang
14from ..texthelper.texts_language import TITLES
17class collapse_node(nodes.admonition):
18 """
19 defines ``collapse`` node.
20 """
21 pass
24class CollapseDirective(Directive):
25 """
26 A ``collapse`` adds hide/unhide button
27 for a part of HTML page. It has no effect
28 in other formats.
30 * *legend*: legend for the button, if not precise,
31 it will be hide / unhide. Example: ``:legend: hide/unhide``.
32 * *hide*: the text is shown by default unless this option is set up.
34 Example::
36 .. collapse::
37 :legend: hide/unhide
39 some text to hide or unhide
41 Which gives:
43 .. collapse::
45 some text to hide or unhide
46 """
47 node_class = collapse_node
48 has_content = True
49 required_arguments = 0
50 optional_arguments = 0
51 final_argument_whitespace = False
52 option_spec = {
53 'class': directives.class_option,
54 'legend': directives.unchanged,
55 'hide': directives.unchanged,
56 }
58 def run(self):
59 """
60 Builds the collapse text.
61 """
62 env = getattr(self.state.document.settings, "env", None)
63 lang = sphinx_lang(env)
64 titles = TITLES.get(lang, TITLES['en'])
66 if 'legend' in self.options:
67 legend = self.options['legend']
68 if '/' not in legend:
69 logger = logging.getLogger("sphinx")
70 logger.warning(
71 "[CollapseDirective] unable to interpret parameter legend %r.", legend)
72 legend = None
73 spl = legend.split('/')
74 hide = spl[0].strip()
75 unhide = spl[1].strip()
76 else:
77 legend = None
79 if legend is None:
80 hide = titles['hide']
81 unhide = titles['unhide']
83 if 'hide' in self.options and self.options['hide'] not in (False, 'False', 'false', 0, '0'):
84 show = False
85 else:
86 show = True
87 node = collapse_node(hide=hide, unhide=unhide, show=show)
88 nested_parse_with_titles(self.state, self.content, node)
89 return [node]
92def visit_collapse_node(self, node):
93 """
94 visit collapse_node
95 """
96 pass # pragma: no cover
99def depart_collapse_node(self, node):
100 """
101 depart collapse_node
102 """
103 pass # pragma: no cover
106def visit_collapse_node_rst(self, node):
107 """
108 visit collapse_node
109 """
110 self.new_state(0)
111 legend = '/'.join([node['hide'], node['unhide']])
112 self.add_text('.. collapse::' + self.nl)
113 self.add_text(' :legend: ' + legend + self.nl)
114 if not node['show']:
115 self.add_text(' :hide:' + self.nl)
116 self.new_state(self.indent)
119def depart_collapse_node_rst(self, node):
120 """
121 depart collapse_node
122 """
123 self.end_state()
124 self.end_state(wrap=False)
127def visit_collapse_node_html(self, node):
128 """
129 visit collapse_node
130 """
131 nid = str(id(node))
132 hide, unhide = node['hide'], node['unhide']
134 script = """function myFunction__ID__() {
135 var x = document.getElementById("collapse__ID__");
136 var b = document.getElementById("colidb__ID__");
137 if (x.style.display === "none") { x.style.display = "block"; b.innerText = '__HIDE__'; }
138 else { x.style.display = "none"; b.innerText = '__UNHIDE__'; }
139 }""".replace(" ", "")
140 script = script.replace('__ID__', nid)
141 script = script.replace('__HIDE__', hide)
142 script = script.replace('__UNHIDE__', unhide)
144 self.body.append("<script>{0}{1}{0}</script>{0}".format("\n", script))
145 if node['show']:
146 content = f'<div id="collapse{nid}"">'
147 label = hide
148 else:
149 content = f'<div id="collapse{nid}" style="display:none;">'
150 label = unhide
151 self.body.append(
152 '<p style="margin-bottom:10px;"><button id="colidb{0}" onclick="myFunction{0}()">{1}</button></p>{2}'.format(nid, label, "\n"))
153 self.body.append(content)
156def depart_collapse_node_html(self, node):
157 """
158 depart collapse_node
159 """
160 self.body.append("</div>")
163def setup(app):
164 """
165 setup for ``collapse`` (sphinx)
166 """
167 app.add_node(collapse_node,
168 html=(visit_collapse_node_html, depart_collapse_node_html),
169 epub=(visit_collapse_node_html, depart_collapse_node_html),
170 elatex=(visit_collapse_node, depart_collapse_node),
171 latex=(visit_collapse_node, depart_collapse_node),
172 text=(visit_collapse_node, depart_collapse_node),
173 md=(visit_collapse_node, depart_collapse_node),
174 rst=(visit_collapse_node_rst, depart_collapse_node_rst))
176 app.add_directive('collapse', CollapseDirective)
177 return {'version': sphinx.__display_version__, 'parallel_read_safe': True}