import os.path from docutils import nodes from docutils.parsers.rst import Directive from pygments.lexers import get_lexer_by_name def setup(app): app.add_directive('switcher', SwitcherDirective) app.add_directive('case', CaseDirective) app.connect('env-updated', add_statics) return { 'parallel_read_safe': True, 'parallel_write_safe': True } def add_statics(app, env): app.add_js_file('js/switcher.js') env.config.html_static_path.append(statics()) statics = lambda *p: os.path.join( os.path.abspath(os.path.dirname(__file__)), 'static', *p) class SwitcherDirective(Directive): has_content = True def run(self): self.assert_has_content() body = nodes.compound('\n'.join(self.content), classes=['tab-content']) self.state.nested_parse(self.content, self.content_offset, body) titles = [] for child in body.children: if isinstance(child, nodes.literal_block): titles.append(get_lexer_by_name(child['language']).name) else: assert child['names'], ( "A switcher case must be either a code block or a compound with a name" ) titles.append(' '.join(child['names'])) tabs = nodes.bullet_list('', *[ nodes.list_item('', nodes.Text(title), classes=['nav-link']) for title in titles ], classes=['nav nav-tabs'] ) node = nodes.compound('', tabs, body, classes=['content-switcher']) return [node] class CaseDirective(Directive): required_arguments = 1 final_argument_whitespace = True has_content = True def run(self): self.assert_has_content() node = nodes.compound('\n'.join(self.content), names=[self.arguments[0]]) self.state.nested_parse(self.content, self.content_offset, node) return [node]