from docutils import nodes from docutils.parsers.rst import directives # type: ignore from docutils.parsers.rst import Directive from docutils.parsers.rst.roles import set_classes class details(nodes.General, nodes.Element): pass class summary(nodes.General, nodes.Element): pass def visit_details_node(self, node): self.body.append(self.starttag(node, "details", CLASS=node.attributes.get("class", ""))) def visit_summary_node(self, node): self.body.append(self.starttag(node, "summary", CLASS=node.attributes.get("summary-class", ""))) self.body.append(node.rawsource) def depart_details_node(self, node): self.body.append("\n") def depart_summary_node(self, node): self.body.append("") class DetailsDirective(Directive): final_argument_whitespace = True optional_arguments = 1 option_spec = { "class": directives.class_option, "summary-class": directives.class_option, } has_content = True def run(self): set_classes(self.options) self.assert_has_content() text = "\n".join(self.content) node = details(text, **self.options) if self.arguments: summary_node = summary(self.arguments[0], **self.options) summary_node.source, summary_node.line = self.state_machine.get_source_and_line( self.lineno ) node += summary_node self.state.nested_parse(self.content, self.content_offset, node) return [node] def setup(app): app.add_node(details, html=(visit_details_node, depart_details_node)) app.add_node(summary, html=(visit_summary_node, depart_summary_node)) app.add_directive("details", DetailsDirective)