source: flex_extract.git/for_developers/Sphinx/source/_static/python/hidden_code_block.py @ 0b00607

ctbtodev
Last change on this file since 0b00607 was 0b00607, checked in by Anne Philipp <anne.philipp@…>, 5 years ago

Documentation status version 0

  • Property mode set to 100644
File size: 3.6 KB
Line 
1"""Simple, inelegant Sphinx extension which adds a directive for a
2highlighted code-block that may be toggled hidden and shown in HTML. 
3This is possibly useful for teaching courses.
4
5The directive, like the standard code-block directive, takes
6a language argument and an optional linenos parameter.  The
7hidden-code-block adds starthidden and label as optional
8parameters.
9
10Examples:
11
12.. hidden-code-block:: python
13    :starthidden: False
14
15    a = 10
16    b = a + 5
17
18.. hidden-code-block:: python
19    :label: --- SHOW/HIDE ---
20
21    x = 10
22    y = x + 5
23
24Thanks to http://www.javascriptkit.com/javatutors/dom3.shtml for
25inspiration on the javascript. 
26
27Thanks to Milad 'animal' Fatenejad for suggesting this extension
28in the first place.
29
30Written by Anthony 'el Scopz' Scopatz, January 2012.
31
32Released under the WTFPL (http://sam.zoy.org/wtfpl/).
33"""
34
35from docutils import nodes
36from docutils.parsers.rst import directives
37from sphinx.directives.code import CodeBlock
38
39HCB_COUNTER = 0
40
41js_showhide = """\
42<script type="text/javascript">
43    function showhide(element){
44        if (!document.getElementById)
45            return
46
47        if (element.style.display == "block")
48            element.style.display = "none"
49        else
50            element.style.display = "block"
51    };
52</script>
53"""
54
55def nice_bool(arg):
56    tvalues = ('true',  't', 'yes', 'y')
57    fvalues = ('false', 'f', 'no',  'n')
58    arg = directives.choice(arg, tvalues + fvalues)
59    return arg in tvalues
60
61
62class hidden_code_block(nodes.General, nodes.FixedTextElement):
63    pass
64
65
66class HiddenCodeBlock(CodeBlock):
67    """Hidden code block is Hidden"""
68
69    option_spec = dict(starthidden=nice_bool, 
70                       label=str,
71                       **CodeBlock.option_spec)
72
73    def run(self):
74        # Body of the method is more or less copied from CodeBlock
75        code = u'\n'.join(self.content)
76        hcb = hidden_code_block(code, code)
77        hcb['language'] = self.arguments[0]
78        hcb['linenos'] = 'linenos' in self.options
79        hcb['starthidden'] = self.options.get('starthidden', True)
80        hcb['label'] = self.options.get('label', '+ show/hide code')
81        hcb.line = self.lineno
82        return [hcb]
83
84
85def visit_hcb_html(self, node):
86    """Visit hidden code block"""
87    global HCB_COUNTER
88    HCB_COUNTER += 1
89
90    # We want to use the original highlighter so that we don't
91    # have to reimplement it.  However it raises a SkipNode
92    # error at the end of the function call.  Thus we intercept
93    # it and raise it again later.
94    try: 
95        self.visit_literal_block(node)
96    except nodes.SkipNode:
97        pass
98
99    # The last element of the body should be the literal code
100    # block that was just made.
101    code_block = self.body[-1]
102
103    fill_header = {'divname': 'hiddencodeblock{0}'.format(HCB_COUNTER), 
104                   'startdisplay': 'none' if node['starthidden'] else 'block', 
105                   'label': node.get('label'), 
106                   }
107
108    divheader = ("""<a href="javascript:showhide(document.getElementById('{divname}'))">"""
109                 """{label}</a><br />"""
110                 '''<div id="{divname}" style="display: {startdisplay}">'''
111                 ).format(**fill_header)
112
113    code_block = js_showhide + divheader + code_block + "</div>"
114
115    # reassign and exit
116    self.body[-1] = code_block
117    raise nodes.SkipNode
118
119
120def depart_hcb_html(self, node):
121    """Depart hidden code block"""
122    # Stub because of SkipNode in visit
123
124
125def setup(app):
126    app.add_directive('hidden-code-block', HiddenCodeBlock)
127    app.add_node(hidden_code_block, html=(visit_hcb_html, depart_hcb_html))
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG