"""Sphinx Extensions to simplify writing Furo's Reference documentation. This provides a single `furo-demo` directive, which: - Only works when used in a MyST document. - Requires sphinx-inline-tabs' tab directive. - Requires contents to be of the following format: {lines-of-markdown} +++ {lines-of-reStructuredText} """ from textwrap import indent from docutils import nodes from docutils.statemachine import StringList from sphinx.directives import SphinxDirective def _split_by_language(block_text): try: a, b = block_text.split("+++\n") except ValueError: if block_text.endswith("+++"): return block_text[:-3], "" raise RuntimeError("Expected separator line containing only '+++'.") else: return a, b def _md_demo(block): lines = [] if not block.strip("\n"): return StringList() lines.append("`````{tab} Markdown (MyST)") lines.append("````md") lines.extend(block.splitlines()) lines.append("````") lines.extend(block.splitlines()) lines.append("`````") return StringList(lines) def _rst_demo(block): lines = [] if not block.strip(): return StringList() lines.append("`````{tab} reStructuredText") lines.append("````{eval-rst}") lines.append(".. code-block:: rest") lines.append("") lines.extend(indent(block, " ").splitlines()) lines.append("") lines.extend(block.splitlines()) lines.append("````") lines.append("`````") return StringList(lines) def _translate_into_tab_demo(block_text): md, rst = _split_by_language(block_text) string_list = StringList() string_list.extend(_rst_demo(rst)) string_list.extend(_md_demo(md)) return string_list class _FuroDemoDirective(SphinxDirective): has_content = True def run(self): self.assert_has_content() container = nodes.container() transated_content = _translate_into_tab_demo(self.block_text) self.state.nested_parse(transated_content, 0, container) return [container] def setup(app): """For setting up the directive.""" app.add_directive("furo-demo", _FuroDemoDirective)